Skip to navigation

pgvector 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.

Create an account at platform.respan.ai and grab an API key.

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

Setup

1

Install packages

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

Set environment variables

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.

3

Initialize and run

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()
4

View your trace

Open the Traces page 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:

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

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to the RESPAN_API_KEY environment variable.
base_urlstr | NoneNoneFalls back to the RESPAN_BASE_URL environment variable.
instrumentationslist[]Plugin instrumentations to activate, such as PGVectorInstrumentor().
capture_contentboolTruePGVectorInstrumentor option that controls SQL, vector, and result capture.
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag, such as "production".

Attributes

In Respan()

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

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()
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related operations into a thread.
metadatadictCustom key-value pairs merged with default metadata.