Skip to content

PATTERN Cited by 2 sources

Query comment tag propagation via ORM

Pattern: instrument the ORM (or the ORM-adjacent middleware layer) to automatically attach a structured SQL comment to every query emitted during a request or unit of work, carrying the request's contextual metadata. The comment travels unchanged through connection pooling, driver layers, and any proxies to the database, and is observable on the database side by any tool that parses SQL comments.

Shape

At the application layer:

  1. Middleware captures per-request context at the beginning of the request (controller, action, background-job class, authenticated principal, request-ID, feature-flag state).
  2. Context is stored in request-local or thread-local storage.
  3. ORM hook (ActiveSupport::Notifications subscriber, ORM query formatter, query-log pipeline) renders the context as a structured SQL comment on every query issued.
  4. The rendered comment string is memoised per request so per-query rendering cost is O(1) lookup.

Emitted SQL looks like:

SELECT body, author_id FROM posts WHERE id = $1
/* controller='posts', action='show', job='', user='alice@example.com' */

On the database side, the comment is inert (all SQL engines ignore leading/trailing comments at execution time) but observable by any tool that parses the SQL text — query-log analysers, proxy layers, database extensions.

Why ORM-layer, not application-layer or driver-layer

Three candidate altitudes for where to attach the tag:

  1. ORM-layer (this pattern) — tags emitted on every query the ORM issues, including ones inside library code the application author didn't write. Captures everything without requiring per-call-site discipline. Highest coverage, modest complexity.
  2. Application-layer per-call-site — author calls annotate(...) at each query site. Highest precision, lowest coverage; doesn't catch library-originated queries. Useful as an override on top of ORM-layer defaults — see ActiveRecord annotate.
  3. Driver-layer / proxy-layer — tags emitted at the SQL driver or connection-pool layer. Cannot see request context (driver is below the request layer). Limited to auto-tags the driver itself can infer — application_name, username, remote_address (Source: sources/2026-04-21-planetscale-enhanced-tagging-in-postgres-query-insights — PlanetScale Insights auto-tags). Complementary to, not replacement for, the ORM-layer pattern.

The ORM layer is the sweet spot because it sees both the request context (above it) and the query-issuance event (below it).

Canonical implementations

  • Ruby on Rails:
  • Marginalia gem (2013-ish, pre-Rails-7 canonical implementation; Basecamp).
  • Rails 7+ native query_log_tags framework feature (2022+); framework-absorbed successor to Marginalia.
  • PlanetScale's activerecord-sql_commenter gem (2022-06-29) — emission-format shim on top of Rails 7 query_log_tags that writes SQLCommenter format instead of Rails's default convention.
  • Django: django-sqlcommenter (Google-maintained), analogous shape — middleware captures request context, ORM hook emits SQLCommenter-format tags.
  • Spring Data / Hibernate: datasource-micrometer-sqlcommenter (Spring Cloud), analogous shape on the JVM.
  • Node.js: Prisma, TypeORM, Sequelize each have their own SQLCommenter integrations via extensions or hooks.

Operational properties

  • Framework-native is cheaper than gem. Rails 7 absorbed query_log_tags into the framework precisely because every non-trivial Rails app ended up installing Marginalia or equivalent. Framework-native eliminates the dependency and makes the feature available to every app by default.
  • Per-request memoisation is mandatory. Rendering the tag string per query is N× work per request with N queries; memoising per request is O(1) per query after the first. Rails exposes this as cache_query_log_tags = true.
  • Custom tag providers extend the vocabulary. Rails 7 accepts procs or lambdas for tag values — e.g. a feature_flag_state tag that captures which feature flags were active for the request. Pattern generalises to any key computable from the request context.
  • Format is a convention choice. Rails default, SQLCommenter, Marginalia's legacy format, custom in-house formats — the same pattern can emit different on-the-wire formats. The choice is downstream-tooling-driven: emit the format your query-log consumer parses.
  • Connection-pool preservation required. Some ORM layers or connection pools strip comments from SQL to canonicalise for plan-cache lookup; the pattern fails silently if this happens. Must verify end-to-end that the comment reaches the database.

Complements, doesn't replace

  • Per-query annotate is the per-query override — for cases where the per-request baseline isn't enough. Both mechanisms compose cleanly; a query in a query_log_tags-enabled request with annotate carries both annotations.
  • Driver-layer auto-tags (Postgres application_name, username, remote_address) provide a baseline that works even if no application-layer instrumentation is deployed. The ORM-layer pattern adds the application context the driver can't see. (Source: sources/2026-04-21-planetscale-enhanced-tagging-in-postgres-query-insights.)

Seen in

  • sources/2026-04-21-planetscale-patterns-for-postgres-traffic-controlcanonical framework-less Go counterpart. Josh Brown (2026-04-02) canonicalises patterns/context-threaded-sql-tag-propagation — the same ORM-layer-tag-propagation shape specialised for languages without ORM middleware conventions. Go's context.Context is the explicit per-request storage vehicle; a wrapper QueryContext / ExecContext method on the database handle renders tags at query time. Same on-the-wire format (SQLCommenter), same observability outcomes, different coverage boundary: ORM-middleware covers every query the ORM issues (library queries included); context.Context- threading covers every query on a ctx-accepting call site (excludes legacy ctx-less helpers).

  • sources/2026-04-21-planetscale-identifying-slow-rails-queries-with-sqlcommenterearliest canonical wiki instance. Coutermarsh + Ekechukwu (2022-06-29) walk the complete Rails application of the pattern — ORM-layer auto-tagging via query_log_tags + per-query override via annotate + format choice via activerecord-sql_commenter — and show the production debugging loop (slow-query in PlanetScale Insights → read the tag → localise the code).

  • sources/2026-04-21-planetscale-debugging-database-errors-with-insights — Rafer Hazen (2022-09-27) extends the pattern to error-query attribution. The actor tag (authenticated principal) is the canonical application-layer tag that the ORM-layer middleware captures once per request, and every query in that request carries it. Framed as the patterns/actor-tagged-query-observability pattern — the same ORM-level pattern specialised for the authenticated-user key.
Last updated · 378 distilled / 1,213 read