Skip to content

Does DD_DBM_PROPAGATION_MODE=full interact with psycopg3's automatic prepared statement caching (prepare_threshold)? #16487

@billykern

Description

@billykern

Question

We're evaluating enabling DD_DBM_PROPAGATION_MODE=full across our Python services that use psycopg3 (via SQLAlchemy). Before doing so, we wanted to understand if there's a known interaction between full-mode DBM propagation and psycopg3's automatic prepared statement caching (prepare_threshold).

Background

psycopg3 introduced automatic prepared statement caching (not present in psycopg2). By default, after a query is executed 5 times on a connection (prepare_threshold=5), psycopg3 automatically prepares it server-side. The cache key is the raw SQL text.

In full mode, handle_dbm_injection prepends a SQL comment with a dynamic traceparent (containing trace/span IDs) to each query before it reaches psycopg3's cursor.execute(). Since the trace context changes per-request, psycopg3 would see a different SQL string each time, and the prepare_threshold would never be reached — effectively disabling auto-prepare for the lifetime of the connection.

What appears to be the case

  • The psycopg.execute event uses the standard handle_dbm_injection handler with no special handling for prepared statements
  • By contrast, asyncpg.execute has a dedicated handle_dbm_injection_asyncpg that skips injection for bind_execute_many (which uses prepared statements) — added in #8935
  • The Go tracer (dd-trace-go) handles a similar case by downgrading full mode to service mode inside PrepareContext, so prepared statement cache keys remain stable — this was a deliberate design decision from the initial implementation

Questions

  1. Is this a known/expected interaction? Is there documentation or prior discussion we might have missed?
  2. For long-lived services with persistent connection pools using psycopg3, would Datadog recommend disabling prepare_threshold when using full mode, or is there a planned fix similar to the asyncpg or Go approaches?
  3. Is this a non-concern because the DBM comment injection happens at a layer where psycopg3's internal prepare logic doesn't see the modified SQL? (We read the source and believe it does, but want to confirm.)

Environment

  • ddtrace (latest)
  • psycopg 3.x (psycopg3)
  • DD_DBM_PROPAGATION_MODE=full

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions