Why
PlanetScale Query Insights groups queries by fingerprint. Without tags, hot paths likeFindKeyForVerification appear as anonymous load. Tags let us answer:
- Which service issued this query?
- Which deploy introduced the regression?
- Which sqlc operation or tRPC route drove the spike?
POST /v2/keys.verifyKey serialize safely.
Tag schema
| Key | Source | Example |
|---|---|---|
application | constant | unkey |
service | process name | api, frontline, dashboard |
region | UNKEY_REGION (set in helm per cluster) | us-east-1 |
release_sha | link-time git SHA (7 chars) | a1b2c3d |
operation | sqlc -- name: header (Go only) | FindKeyForVerification |
mode | connection role (Go only) | rw, ro |
route | request context | deploy.envVars.create (tRPC path) |
source | request context | http, restate, trpc, webhook |
environment tag. Infra labels clusters production001, canary, or legacy staging, but those labels are not injected into platform pod env vars today. Use release_sha to identify the deployed commit (Bazel/goreleaser set buildinfo.Revision on Go binaries; Vercel sets UNKEY_GIT_COMMIT_SHA / GIT_COMMIT for dashboard).
Example comment appended to SQL:
Go services
Annotation happens inpkg/mysql.Replica (and the mirrored pkg/db package). sqlc call sites stay unchanged.
- Pass static tags when opening the database:
- Optional dynamic tags via context (HTTP zen services set these automatically with
zen.WithSQLComment):
zen.WithSQLComment() reads http.Request.Pattern (for example POST /v2/keys.verifyKey) and is registered in api and frontline middleware stacks.
ctrl-worker wraps the Restate ingress with sqlcomment.WrapRestateInvokeHandler, tagging routes like hydra.v1.DeployService/Deploy with source=restate.
sqlcomment.Static{} disables annotation (tests and dev seeds).
Package reference: pkg/mysql/sqlcomment.
TypeScript apps
Dashboard and portal use Drizzle on top ofcreateCommentedPool from @unkey/db. The pool proxy annotates query and execute on the pool and on connections from getConnection, which is what Drizzle uses inside transactions.
Useful tags on the TypeScript side:
- Static (per pool):
service,region,release_sha - Dynamic (per request):
route(tRPC procedure path) andsource(trpc,webhook, etc.)
route and source through runWithSqlCommentTags in the base procedure middleware. Non-tRPC entrypoints (Stripe webhooks, server actions) should wrap their handler with runWithSqlCommentTags and set source accordingly.
TypeScript pools do not emit mode: mysql2 uses a single pool without the read/write split that Go services have, so a mode tag would be misleading.
Static tags read UNKEY_REGION / REGION and UNKEY_GIT_COMMIT_SHA / GIT_COMMIT for release_sha.
Verification
After deploy to staging:- Open PlanetScale Query Insights for the
unkeydatabase. - Find a high-traffic fingerprint (for example
FindKeyForVerification). - Confirm
service,operation, andrelease_shaappear on sampled queries. - For dashboard traffic, confirm
routetags on tRPC-backed queries.
Agent notes
- Do not add high-cardinality values to SQL comments.
- New Go services: wire
sqlcomment.ForServiceinrun.gowhen constructingdb.Config. - New TS apps using
@unkey/db: usecreateCommentedPoolinstead ofmysql.createPool. - HTTP handlers that bypass tRPC can set
sqlcomment.WithDynamic(Go) orrunWithSqlCommentTags(TS) per request.

