Skip to content
Nicolas Chiong· 5 min read

An OpenTelemetry database semconv migration FAQ

A practical FAQ for moving database traces and dashboards to stable OpenTelemetry semantic conventions without breaking production alerts.

I would not treat the stable OpenTelemetry database semantic conventions as a rename chore. The obvious work is updating span attributes. The production work is keeping dashboards, alerts, cost controls, and query-redaction assumptions steady while two telemetry shapes exist at once.

That matters because database telemetry is usually wired into the least forgiving part of an engineering stack. Slow query alerts page people. Pool metrics explain outages. Redaction mistakes leak data. A small attribute rename can be harmless in code and still break the operations loop around it.

What changed?

OpenTelemetry's database semantic conventions have moved from an experimental shape toward stable database conventions. The current OpenTelemetry database docs describe the migration path for existing instrumentations: keep the old default inside the current major version, add OTEL_SEMCONV_STABILITY_OPT_IN, allow database/dup for dual emission, then move teams toward database when consumers are ready.

For Node teams using PostgreSQL, the change is visible in @opentelemetry/instrumentation-pg. Its package docs say older versions emitted experimental database conventions, while newer versions support stable database semantics through the same opt-in environment variable. Examples of the mapping are practical: db.statement becomes db.query.text, db.system becomes db.system.name, net.peer.name becomes server.address, and the database name folds into db.namespace.

The important part is not memorizing every mapping. The important part is acknowledging that every saved query around those keys is part of the migration.

Should I flip the stable flag first?

No. I would start with dual emission in one low-risk service, then inspect what actually arrives at the collector and backend.

OTEL_SEMCONV_STABILITY_OPT_IN=database/dup

That single variable is the cheapest safe step. It lets old consumers continue reading old attributes while new dashboards and alerts are built against the stable keys. If your platform already uses declarative OpenTelemetry configuration, check that first because the version-selection spec says domain-specific semconv config takes precedence over the general environment variable.

I would not enable this globally on a Friday because duplicate emission can increase attribute volume and cardinality. The lazy rollout is one service, one database client, one dashboard, one alert.

What should I check before rollout?

I use a four-part check.

First, list the attributes your dashboards and alerts read today. Search for db.statement, db.name, db.system, net.peer.name, and net.peer.port in dashboards, monitors, notebooks, log queries, and runbooks. Migration work hidden in a saved chart still counts.

Second, decide whether query text belongs in the new world. db.query.text can be useful, but it can also carry sensitive values if instrumentation or client behavior is sloppy. If you already avoided db.statement for privacy or cardinality reasons, do not accidentally reintroduce the same problem under a new key.

Third, compare span names and operation grouping. Stable conventions lean on fields like db.operation.name, db.collection.name, db.namespace, and db.query.summary. Those can make dashboards cleaner, but only if your backend groups by the new fields instead of string-parsing old span names.

Fourth, check metrics separately from traces. The database operation duration metric is the first place I expect quiet breakage because alert queries often hard-code metric names and labels. Treat metrics as a separate migration even when the same instrumentation package emits both.

How does this affect PostgreSQL work?

This is where I connect it to the way I think about PostgreSQL upgrade rehearsals. A database version upgrade and a telemetry convention upgrade are different changes, but the rehearsal shape is similar: capture current evidence, run the new path beside the old path, compare signals, then cut over only when rollback is boring.

For PostgreSQL specifically, I would watch pool acquisition spans, query spans, and operation-duration metrics. If a service uses both pg and pg-pool, make sure both paths still show up. If you rely on SQL commenter comments, verify the comments are not changing the shape of sensitive query capture. If your traces power an N plus one detector, verify it still sees the same operation groups after the attribute changes.

The boring test is simple: trigger three known database paths in staging, one read, one write, one failure. Then confirm the old dashboard still works under database/dup, the new dashboard works under database/dup, and the new dashboard still works after switching to database only.

What about AI systems?

I would keep this separate from the AI-agent trace contract, even if both live in OpenTelemetry. The contract I wrote about in production AI agent telemetry is about agent runs, tool calls, approvals, and handoffs. Database semconv migration is about infrastructure spans and metrics.

They meet at correlation. A useful agent trace should connect a tool call to the database work it triggered. That correlation does not require every team to invent custom database attributes. Stable database semconv gives the infrastructure side a cleaner base, while the agent contract carries product-specific meaning.

When do I remove dual emission?

I would remove it only after three checks pass.

The first check is consumer parity. Every dashboard, alert, notebook, and runbook that used old fields has a stable-field equivalent.

The second check is retention parity. You have enough historical data in the new shape to compare normal traffic, not just a deploy window.

The third check is failure parity. At least one real or staged database error has flowed through the new attributes, because exception and failure dashboards are where migrations often look fine until the first incident.

After that, switch one service to OTEL_SEMCONV_STABILITY_OPT_IN=database, watch it through a normal traffic cycle, then expand. The forward-looking move is not to chase every semconv update as soon as it appears. It is to make telemetry migrations boring enough that stable conventions can actually become stable operations.

opentelemetryobservabilitypostgresqltelemetry

References

  1. opentelemetry.ioOpenTelemetry
  2. opentelemetry.ioOpenTelemetry
  3. opentelemetry.ioOpenTelemetry
  4. opentelemetry.ioOpenTelemetry
  5. npmjs.comOpenTelemetry JS

Related writing

← PreviousA budgeted model router for GPT-5.6 workloads

Let's make something useful.

Start a conversation