PATTERN Cited by 1 source
Route-tagged query isolation¶
Pattern: tag every database query with the HTTP route
(endpoint pattern) that triggered it, via middleware injection
at request-acceptance time, so per-endpoint
resource budgets
can prevent a heavy endpoint from degrading the rest of the
application. The /api/export CSV-report endpoint must not be
able to kill the /api/checkout flow.
Shape (Go)¶
One HTTP middleware + the context-threaded tag propagation substrate (Source: sources/2026-04-21-planetscale-patterns-for-postgres-traffic-control):
func SQLTagMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tags := tagsFromContext(r.Context())
route := strings.ReplaceAll(strings.ReplaceAll(r.Pattern, "{", ":"), "}", ":")
tags["route"] = route
tags["app"] = "web"
ctx := contextWithTags(r.Context(), tags)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
The { / } → : replacement normalises Go 1.22+ net/http
patterns (/api/users/{id}) into a shape that's usable as a
budget-rule key (/api/users/:id:) without breaking either
system — each endpoint collapses to a stable, bounded-cardinality
tag value.
What each tag buys¶
route=...is the per-endpoint dial. Defineroute='/api-export'with a conservative CPU limit + short per-query cap; the endpoint stays usable but can't monopolise.app='web'is a coarse stack-tier tag that distinguishes web-tier traffic from job-tier / script-tier traffic in the same cluster (complement to patterns/dedicated-application-name-per-workload).
Budgets can match on route alone, app alone, or the pair;
both tags ride on every query on the web tier.
When to use it¶
The pattern is the single most operationally valuable tagging axis for a monolith or large API service because the typical failure mode is "one endpoint started scanning too much", not "the whole service is broken". Specific triggers:
- Reports / exports / bulk-operation endpoints that do more work than typical CRUD handlers.
- Admin endpoints that may scan without LIMIT.
- Search / aggregation endpoints whose cost is query-dependent rather than constant.
- Legacy endpoints under deprecation that shouldn't expand their footprint as usage grows elsewhere.
Composes with other axes¶
The full power is in composition
(concepts/composable-tag-axes). A budget rule matching
tier='free' AND route='api-export' is strictly tighter than
either alone — enterprise customers' exports can have
headroom that free-tier exports can't.
Incident-response payoff¶
Canonical operational framing (Source:
sources/2026-04-21-planetscale-patterns-for-postgres-traffic-control):
"This also makes it easy to set up broad budgets during
incidents. If you suddenly see a spike and don't know which
route is responsible, the violation graph in Traffic Control
will show you exactly which route tag is hitting limits."
The pattern turns "which endpoint is the problem?" from a log-join problem into a dashboard click. The same tag that enforces the budget is the tag you filter on for attribution.
Operational notes¶
- Route pattern ≠ route URL. Middleware must pull the
router's pattern (
/api/users/{id}), not the path (/api/users/12345). Using the path blows up tag cardinality by the number of distinct IDs; using the pattern stays bounded. - Character normalisation matters. Brace characters in
patterns confuse some rule-matcher parsers; the canonical
{/}→:replacement is the safe default. - Middleware must wrap all handlers. Any handler not wrapped emits untagged SQL; budgets don't apply. Best practice: wrap at the root mux, not per-handler.
- Nested mux / sub-router routing may require the
middleware to run at each router layer; verify
r.Patternreflects the final route match.
Seen in¶
- sources/2026-04-21-planetscale-patterns-for-postgres-traffic-control
— canonical wiki introduction. Josh Brown's Pattern 2.
Canonicalises the Go 1.22+
r.Pattern+{/}→:normalisation +app='web'companion tag + incident- response attribution payoff.