Skip to content

CONCEPT Cited by 4 sources

SQLCommenter query tagging

SQLCommenter is a Google-originated (google.github.io/sqlcommenter) open standard for appending key-value metadata to SQL queries as a SQL comment. The SQL is executed unchanged; the comment is inert from the database-engine perspective but observable to extensions, proxies, and log analyzers.

Syntax

A trailing (or inline) SQL comment with structured key-value pairs:

SELECT body, author_id, created_at FROM posts WHERE id = $1
/* category='viewPost', priority='critical' */

The application is in full control of the keys and values. Conventional keys the SQLCommenter spec defines include application, controller, action, framework, route, db_driver, traceparent. Teams routinely add their own (team, priority, category, user_id, feature_flag, etc.).

What it enables

Because the comment is an inert annotation on the SQL itself rather than a side-channel, any layer that inspects the SQL text can act on it:

  1. Query attribution — map each query back to the application code path that issued it (patterns/actor-tagged-query-observability, concepts/actor-tagged-error).
  2. Aggregate statistics broken down by tagconcepts/aggregate-tag-attribution / concepts/per-pattern-tag-cardinality at the observability tier.
  3. Workload-class resource enforcementpatterns/workload-class-resource-budget / patterns/shed-low-priority-under-load at the control tier. Budget rules key on tag values; queries get blocked or accepted by the tag they carry.
  4. Search / filter surface over captured query logs — tag:key:value filter syntax in the observability UI.
  5. Priority-based load sheddingpriority tiers encoded as a SQLCommenter tag at every call-site; the runtime control plane decides which class to shed.

Why comments, not side-channels

A few alternatives exist; SQLCommenter chose the comment-inside-SQL path deliberately:

  • Dedicated metadata headers — require client modifications, don't flow through connection pools cleanly, don't work with vanilla SQL clients.
  • Session variables (SET LOCAL) — one per session, not per query; also require round-trip and don't interleave with batched queries.
  • Stored-proc parameters — can't be added retroactively to existing query patterns.
  • Sampling / tracing context (OpenTelemetry) — orthogonal and compatible; SQLCommenter supports traceparent natively.

A SQL comment travels with the query through every layer (app ORM → connection pool → wire protocol → replica fanout → query log → extension) unchanged, with no engine-side coupling.

Canonical consumers

  • PlanetScale Insights Postgres extension — parses SQLCommenter tags at the extension layer, emits them into the observability pipeline, indexes per-tag aggregate stats.
  • PlanetScale Traffic Control — the control-plane consumer. Budget rules match on tag values (priority='critical', action='analytics', etc.); over-budget queries are blocked.
  • Google Cloud SQL Insights — Google's own first-party consumer; the spec is effectively a Google-originated convention promoted to an open standard.

Auto-populated tags alongside application-populated tags

Insights augments application-authored SQLCommenter tags with three auto-populated ones set at the Postgres / extension layer (Source: sources/2026-04-21-planetscale-enhanced-tagging-in-postgres-query-insights):

  • application_name — set by the Postgres driver.
  • username — the Postgres role that issued the query.
  • remote_address — the client IP.

Auto-tags are available even if the application never adds a single SQLCommenter tag, giving operators a baseline attribution surface before application-level tag discipline is deployed.

Gotchas

  • Connection pool stripping. Some ORMs / pools strip comments from SQL by default (to canonicalise for cache lookup). Has to be configured to preserve comments.
  • Query-plan cache key sensitivity. If the cache key includes comment bytes, each new tag value produces a plan-cache miss. Postgres's pg_stat_statements normalises over comments by default; mixed-extension setups may differ.
  • Log-line bloat. Every query in the log is now longer; downstream log-analysis pipelines must be cardinality- aware (concepts/per-pattern-tag-cardinality, patterns/dynamic-cardinality-reduction-by-tag-collapse).
  • Arbitrary-string injection risk. User-controlled strings should never be interpolated into SQLCommenter tags — the same SQL-injection-hygiene rules apply as anywhere else in the SQL path.
  • Tag discipline is app-level work. The comment doesn't magically appear; every query path that matters must be tagged, which is a coordination problem across a codebase.

Seen in

Last updated · 347 distilled / 1,201 read