SiphonEmergencyModeActive
Overview
Section titled “Overview”Fires when a Siphon producer has had emergency mode active continuously for more than one hour.
Emergency mode is a fallback write path: the producer stops publishing to NATS JetStream and writes replication events to object storage instead. Nothing is lost, the events are durably stored and can be replayed. But while it’s on:
- The ClickHouse consumers receive no events, so every table fed by the affected producer stops advancing. Users querying that data see stale results.
- An object storage backlog accumulates. The longer emergency mode stays on, the longer the drain afterwards.
It’s meant to be a short, deliberate mitigation, usually while NATS is unhealthy. An hour is long enough that a transient flip during a NATS blip or a producer deploy won’t page. If it’s still on after an hour, either NATS hasn’t recovered or the toggle was left enabled.
The PostgreSQL replication slot keeps advancing in emergency mode (the LSN is still acked), so this alert does not imply WAL accumulation on the Patroni primary. If WAL is also accumulating, expect SiphonLogicalReplicationSlotLagHigh to fire too, and treat that as the more urgent of the two.
Services
Section titled “Services”- Siphon Service
- Owned by Platform Insights
- Depends on NATS JetStream, whose health is usually why emergency mode engaged.
Metrics
Section titled “Metrics”siphon_failover_mode_active: boolean gauge,1while emergency mode is active.- Source: Siphon producer pods in the
siphonnamespace on theorbit-*clusters, scraped into theanalytics-eventsdotMimir tenant. - Aggregated with
max by (environment, app_id, cluster), so we get one alert per producer rather than one per pod. - Siphon’s metrics in this tenant carry
env="orbit-prd"/env="orbit-stg"rather than thegprd/gstgthe rest of the fleet uses, and the alertmanager route feeding incident.io matchesenv=~"gprd|ops|thanos|production". The expression therefore derives a fleet-standardenvfromclustervialabel_replace. Without it this alert would only reach Slack despite being ans2withpager: pagerduty. Keep theorbit-(prd|stg)regex in step with the clusters we run, a cluster outside it won’t page. - Threshold:
== 1sustained for1h. - Normal behaviour: flat
0. Any sustained1is a deliberate fallback state, not noise.
Alert Behavior
Section titled “Alert Behavior”- Clears automatically once emergency mode is off and the gauge returns to
0. for: 1hrequires the condition to hold continuously. A producer restart resets the pending timer, so a producer that keeps restarting while in emergency mode may never fire. Check the metric directly if you suspect that.- Silence only for the duration of a Change Request that deliberately keeps a producer in emergency mode (e.g. planned NATS maintenance), not indefinitely.
- Should be rare. Emergency mode is not part of steady-state operation.
- Previous incidents tagged with this alert
Severities
Section titled “Severities”- Default:
s2,pager: pagerduty. It pages because the failure is invisible downstream, ClickHouse looks healthy, it’s just not receiving anything, so it needs an active push rather than a channel notification. - Escalate to
s1if NATS is unhealthy with no sign of recovery, ifSiphonLogicalReplicationSlotLagHighis firing on the same cluster (WAL accumulation on a production primary is the bigger risk), or if the backlog is large enough that the drain will exceed the freshness expectations of the downstream data.
Verification
Section titled “Verification”Which producers are affected:
max(siphon_failover_mode_active{cluster=~"orbit-.*",namespace="siphon"}) by (environment, app_id)How long each has been in emergency mode (seconds, over the last 24h):
sum_over_time( max(siphon_failover_mode_active{cluster=~"orbit-.*",namespace="siphon"}) by (environment, app_id)[24h:1m]) * 60Recent changes
Section titled “Recent changes”- Recent Siphon changes
- Producer config and deployments live on the
orbit-prd/orbit-stgclusters in thesiphonnamespace. Roll back via the usual Kubernetes rollback.
Troubleshooting
Section titled “Troubleshooting”-
Identify the producer. The
app_idlabel names it. -
Check NATS JetStream health first. Turning emergency mode off before NATS is fixed will just flip it back on. See the NATS runbook.
-
Check the producer pods. The logs should say why emergency mode engaged and whether the producer has been retrying NATS.
Terminal window glsh kube use-cluster orbit-prd --no-proxykubectl get pods -n siphon -o widekubectl logs -n siphon -l app=postgres-producer-<db> --tail=200 -
Size the object storage backlog before turning emergency mode off. A large backlog replayed all at once can overwhelm NATS and push the producer straight back into emergency mode.
-
Once NATS is healthy, disable emergency mode and drain the backlog. Watch the publish rate and NATS health while it replays, and be ready to re-enable emergency mode if NATS starts to struggle.
-
Verify the downstream caught up. Check that the ClickHouse tables fed by this producer have advanced past the gap and that
siphon_failover_mode_activeis back to0.
Possible Resolutions
Section titled “Possible Resolutions”- No prior incidents yet; this alert is new. Add links here as we accumulate production experience.
- All previous incidents involving Siphon
Dependencies
Section titled “Dependencies”- NATS JetStream: the primary write path emergency mode bypasses.
- Object storage: the fallback write path holding the backlog.
- Siphon producer (
postgres-producer-*pods in thesiphonnamespace). - ClickHouse consumers: starved of events while emergency mode is on.
Escalation
Section titled “Escalation”- Primary contact:
#g_analytics_platform_insights. Most context:@ahegyi,@arun.sori,@ankitbhatnagar. - If NATS is the underlying problem and there’s no response from the primary contacts, escalate through the usual EOC path.
Definitions
Section titled “Definitions”- Alert definition (Jsonnet source)
- Generator wiring
- The only tunable is the
1hfor:window. Shorten it if an hour of staleness is already too much for the downstream consumers; lengthen it if legitimate NATS maintenance routinely runs longer. - Edit this playbook
- Update the template used to format this playbook