Documentation navigation
Envoy Elevated Error Spike (4xx/5xx)
Runbook for when the rate of 4xx/5xx responses returned by the envoy-gateway data planes rises well above its rolling 7d baseline, per cluster, environment, and response code class (4/5).
Meaning
The expr is a slope test against history, same shape as the sibling traefik
alert (16-traefik-elevated-error-spike.md):
- Numerator —
increase(envoy_http_downstream_rq_xx{envoy_response_code_class=~"4|5"}[1h])summed perk8s_cluster_name, environment, envoy_response_code_class. - Denominator —
increase(...[7d] offset 1h) / (7 * 24)— the rolling 7d mean hourly count, excluding the current hour. The 7d window spans a full week so weekends and holidays — which naturally depress traffic — are only 2/7 of the baseline instead of dominating a 24h window, preventing false spikes on Monday mornings / post-holiday mornings. - Fires when the 1h count exceeds 6x the baseline and the >10/h floor holds. The 6x threshold (up from 3x in the prior 24h-based version) accounts for the wider, smoother baseline — see the sibling traefik runbook for the full rationale and backtest numbers.
The sum by (...) exists because downstream counters are emitted once per
envoy_http_conn_manager_prefix (one series per connection-manager prefix;
see 15-envoy-overload-rejecting-requests.md): without it the alert fires
one instance per prefix.
Class-level caveat — envoy only exports response classes
(envoy_response_code_class 1–5), not exact codes: this alert cannot
distinguish a 401 from a 403 or a 404. Traefik metrics carry exact codes and
front most user-facing auth traffic (assistant, keycloak), so the
traefik sibling is the fine-grained auth surface; this alert covers the
envoy data planes (LLM/AI gateways etc.) at class level. Exact-code counters
(..._upstream_rq_400-style) do not exist in Mimir today — enabling them
needs an envoy-gateway stats change, not just a scrape addition.
Downstream vs upstream — this alert reads envoy_http_downstream_rq_xx,
what envoy returned to clients. Backends can be failing much harder
upstream while retries mask it from clients — compare the upstream view
(Diagnosis step 2) against the downstream rate when the two disagree.
Impact
- Client-visible error ramps on the LLM/AI gateway surfaces — model requests failing (5xx) or being rejected upstream (4xx).
- Baselines on these gateways can be large but persistent — the ratio test is what turns persistent background into event detection.
Diagnosis
Labels give k8s_cluster_name, environment, envoy_response_code_class.
1. Confirm which gateway and how the rate evolved
QUERY='sum by (namespace, pod) (rate(envoy_http_downstream_rq_xx{envoy_response_code_class="<class>", k8s_cluster_name="<cluster>"}[15m]))'
Check whether one pod or the whole data plane is throwing the class — a
single noisy pod points at the heap/overload chain
(13-envoy-heap-saturation.md), a uniform ramp points at upstreams.
2. Which upstream cluster is failing — attribution via label_replace
rate()/increase() drop the __name__ label, and for envoy cluster stats
the cluster name is embedded in the metric name
(envoy_cluster_<name>_upstream_rq_xx). Extract it before the rate:
topk(8, sum by (envoy_cluster)
(rate(label_replace(
{__name__=~"envoy_cluster_.*_upstream_rq_xx", envoy_response_code_class="<class>", k8s_cluster_name="<cluster>"},
"envoy_cluster", "$1", "__name__", "envoy_cluster_(.*)_upstream_rq_xx")[15m:1m])))
Counter semantics: upstream_rq_xx counts what the backends returned —
with retries configured it will exceed what clients observed; treat it as
the upstream-failure view, not the client view.
3. Dashboard and logs
- Grafana dashboard
Team Platform / LLM Proxy / Envoy AI Gateway — 5xx & Upstream Health(uidllm-proxy-5xx) shows the client-visible surface. - Loki streams for the gateway pods: service names in the
envoy-gateway,envoy-shared-envoy-*family — filter{service_name=~"envoy.*", k8s_cluster_name="<cluster>"}.
Mitigation
Step 1 — Activate PIM
Activate the required Azure Privileged Identity Management roles before
touching production, as in 03-kafka/01-consumer-lag.md.
Step 2 — Fix per outcome of step 1
- Whole pod throw / heap chain signatures — follow
13-envoy-heap-saturation.md(limit bump / restart). - Specific upstream cluster failing — investigate that backend (deployment status, recent rollout, resource saturation), not the gateway.
- New-class-only spike over previously silent baseline — check for a fresh routing/config rollout of a new-ish integration; a brand-new consumer can also legitimately move a class's baseline, in which case adjust expectations, not the alert.
Verify
- The class's ratio expr returns nothing (pending holds cleared).
- Downstream
rate(envoy_http_downstream_rq_xx{envoy_response_code_class="<class>"}[15m])back to pre-episode level on the affected cluster.
Notes
- All environments — no
environment="production"filter. - Group family — shares group
envoy.proxywith the heap chain alerts (13/14/15); the same evaluation interval applies. - Metric-availability note — this alert relies only on
envoy_http_downstream_rq_xx(scraped by synapse-client today, no chart change needed). Exact-code alerting on envoy would first require enabling per-code stats (envoy-gateway stats matcher / patch policy) in the charts. - Sibling alert — traefik (
16-traefik-elevated-error-spike.md) has exact codes and most of the user-facing auth traffic.