> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://respan.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://respan.ai/docs/_mcp/server.

# pgvector (tracing)

> Trace pgvector registration, SQL execution, and fetched vector results with Respan.

[pgvector](https://github.com/pgvector/pgvector-python) adds vector types and similarity operators to PostgreSQL. The Respan-owned pgvector instrumentation traces pgvector registration and psycopg 3 connection and cursor operations, including synchronous and asynchronous execution and fetched results.

#### Set up Respan

Create an account at [platform.respan.ai](https://platform.respan.ai) and grab an [API key](https://platform.respan.ai/platform/gateway/api-keys).

Run `npx @respan/cli setup` to set up with your coding agent.

#### Example projects

* [Python examples](https://github.com/respanai/respan-example-projects/tree/main/python/tracing/pgvector)

#### Tracing

## Setup

#### Install packages

```bash
pip install respan-ai respan-instrumentation-pgvector pgvector "psycopg[binary]"
```

#### Set environment variables

```bash
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
export PGVECTOR_DSN="postgresql://postgres:postgres@localhost:5432/postgres"
```

The PostgreSQL user must be able to use the `vector` extension. If it is not already installed in the database, the quickstart also requires permission to run `CREATE EXTENSION`.

#### Initialize and run

```python
import os

import pgvector.psycopg as pgvector_psycopg
import psycopg
from pgvector import Vector
from respan import Respan, workflow
from respan_instrumentation_pgvector import PGVectorInstrumentor

respan = Respan(
    api_key=os.environ["RESPAN_API_KEY"],
    instrumentations=[PGVectorInstrumentor()],
)


@workflow(name="pgvector_similarity_queries_workflow")
def run_pgvector_query():
    with psycopg.connect(
        os.environ["PGVECTOR_DSN"],
        autocommit=True,
    ) as connection:
        connection.execute("CREATE EXTENSION IF NOT EXISTS vector")
        pgvector_psycopg.register_vector(connection)
        connection.execute(
            """
            CREATE TEMP TABLE respan_pgvector_docs (
                id integer PRIMARY KEY,
                content text NOT NULL,
                embedding vector(4) NOT NULL
            )
            """
        )

        with connection.cursor() as cursor:
            cursor.executemany(
                """
                INSERT INTO respan_pgvector_docs (id, content, embedding)
                VALUES (%s, %s, %s)
                """,
                [
                    (
                        1,
                        "Respan traces vector database operations.",
                        Vector([0.9, 0.1, 0.0, 0.0]),
                    ),
                    (
                        2,
                        "PostgreSQL supports pgvector similarity search.",
                        Vector([0.2, 0.8, 0.0, 0.0]),
                    ),
                ],
            )

        query = Vector([0.85, 0.15, 0.0, 0.0])
        return connection.execute(
            """
            SELECT id, content, embedding, embedding <-> %s AS distance
            FROM respan_pgvector_docs
            ORDER BY embedding <-> %s
            LIMIT 2
            """,
            (query, query),
        ).fetchall()


for row in run_pgvector_query():
    print(row)

respan.flush()
respan.shutdown()
```

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces) and search for workflow name `pgvector_similarity_queries_workflow`.

## Covered operations

The instrumentor traces pgvector type registration plus psycopg 3 `execute`, `executemany`, `fetchone`, `fetchmany`, and `fetchall` calls for synchronous and asynchronous connections, cursors, and server cursors. This captures dense, half-precision, sparse, and binary vector workflows and PostgreSQL similarity operators. The optional `psycopg2` extra also traces pgvector's psycopg 2 type registration.

## Content capture

SQL arguments, vector parameters, operation summaries, and fetched rows are captured by default. Disable content capture when those values should not be attached to spans:

```python
from respan import Respan
from respan_instrumentation_pgvector import PGVectorInstrumentor

respan = Respan(
    instrumentations=[PGVectorInstrumentor(capture_content=False)],
)
```

Operation names, status, and PostgreSQL attributes remain available when content capture is disabled.

## Configuration

| Parameter             | Type           | Default | Description                                                                  |
| --------------------- | -------------- | ------- | ---------------------------------------------------------------------------- |
| `api_key`             | `str \| None`  | `None`  | Falls back to the `RESPAN_API_KEY` environment variable.                     |
| `base_url`            | `str \| None`  | `None`  | Falls back to the `RESPAN_BASE_URL` environment variable.                    |
| `instrumentations`    | `list`         | `[]`    | Plugin instrumentations to activate, such as `PGVectorInstrumentor()`.       |
| `capture_content`     | `bool`         | `True`  | `PGVectorInstrumentor` option that controls SQL, vector, and result capture. |
| `customer_identifier` | `str \| None`  | `None`  | Default customer identifier for all spans.                                   |
| `metadata`            | `dict \| None` | `None`  | Default metadata attached to all spans.                                      |
| `environment`         | `str \| None`  | `None`  | Environment tag, such as `"production"`.                                     |

## Attributes

### In Respan()

```python
from respan import Respan
from respan_instrumentation_pgvector import PGVectorInstrumentor

respan = Respan(
    instrumentations=[PGVectorInstrumentor()],
    customer_identifier="user_123",
    metadata={"service": "pgvector-rag-api", "version": "1.0.0"},
)
```

### With propagate_attributes

```python
from pgvector import Vector
from respan import propagate_attributes


def search(connection, user_id: str, query_vector: list[float]):
    with propagate_attributes(
        customer_identifier=user_id,
        thread_identifier="pgvector_thread",
        metadata={"table": "respan_pgvector_docs", "plan": "pro"},
    ):
        query = Vector(query_vector)
        return connection.execute(
            """
            SELECT id, content
            FROM respan_pgvector_docs
            ORDER BY embedding <=> %s
            LIMIT 2
            """,
            (query,),
        ).fetchall()
```

| Attribute             | Type   | Description                                          |
| --------------------- | ------ | ---------------------------------------------------- |
| `customer_identifier` | `str`  | Identifies the end user in Respan analytics.         |
| `thread_identifier`   | `str`  | Groups related operations into a thread.             |
| `metadata`            | `dict` | Custom key-value pairs merged with default metadata. |