You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Prove Rust flags hypercache parity via shadow comparison #88339
Prove that the Rust flags-cache-builder produces the same flags.json entries as the Python (Celery) builder, at full fleet volume, with zero serve exposure. The builder builds every team's entry from a shadow: true invalidation, diffs it against the live Python entry, and never writes.
Exit criterion: a sustained stretch at 100% shadow volume with confirmed mismatches (flags_cache_shadow_mismatch_total) at or returning to zero. When that holds, the serve ramp carries operational risk only.
Why shadow instead of a slow serve ramp
Serve routing covers 3 canary projects today. A serve ramp exposes users to any parity bug while it gathers evidence. Shadow comparison gathers the same evidence across the whole fleet with no user exposure, and soaks the builder at the volume it must absorb anyway.
Merge the builder dashboard (PostHog/grafana-dashboards#416)
Shadow publisher: _enqueue_invalidation also produces shadow: true invalidations for Celery-owned teams, behind a new percentage gate (not the serve-routing flag)
Publisher.#88585 is approved and CI is green. It is not merged yet.
Correction to the task list. The publisher does not hook _enqueue_invalidation. It publishes from the tail of update_team_service_flags_cache, gated on a successful cache write. Publishing at invalidation time raced the rebuild it measures: the builder read fresh Postgres against a pre-rebuild Redis entry and reported the gap as drift. Two invalidations inside one stale window hash the same, so the tracker promoted Celery lag to a confirmed parity defect.
Consumer.#87891 is merged, and its commit is contained in the current prod-us and prod-eu deploy.
Gate flag, done.flags-cache-shadow-compare now exists at 0% rollout, aggregated on the project group type. It is a separate flag from flags-cache-kafka-dual-write and never changes which writer serves a team. Do not delete it while the producer code is live. Local evaluation cannot resolve a flag that does not exist, so shadow volume would drop to zero with no log and no counter.
Alert, still open. This one blocks the ramp.FlagsCacheInvalidationDeliveryFailures in PostHog/charts fires at a threshold of 0 on any delivery failure for the flags_cache_invalidation topic. Shadow messages and real invalidations share that topic, and posthog_kafka_producer_messages_total carries no label that separates them.
Today a firing means a Kafka-routed team serves a stale /flags payload. After the ramp it mostly means one telemetry message did not land. The runbook still tells the responder to look for stale flag serving, and its mitigation step says to turn off flags-cache-kafka-dual-write. That is the serve-routing flag. So a lost shadow message can lead someone to disable the Rust serve path.
Real invalidations come from the 3 canary projects. Shadow messages will come from every Celery-owned team. At 100% most firings of this alert would be false positives.
Suggested additions to the task list, above the ramp step:
Create the flags-cache-shadow-compare gate flag at 0%
Update FlagsCacheInvalidationDeliveryFailures and its runbook in PostHog/charts, before the ramp
Activity
JamesPatrickGill commentedon Aug 26, 2026
Publisher status and two ramp prerequisites
Publisher. #88585 is approved and CI is green. It is not merged yet.
Correction to the task list. The publisher does not hook
_enqueue_invalidation. It publishes from the tail ofupdate_team_service_flags_cache, gated on a successful cache write. Publishing at invalidation time raced the rebuild it measures: the builder read fresh Postgres against a pre-rebuild Redis entry and reported the gap as drift. Two invalidations inside one stale window hash the same, so the tracker promoted Celery lag to a confirmed parity defect.Consumer. #87891 is merged, and its commit is contained in the current prod-us and prod-eu deploy.
Gate flag, done.
flags-cache-shadow-comparenow exists at 0% rollout, aggregated on the project group type. It is a separate flag fromflags-cache-kafka-dual-writeand never changes which writer serves a team. Do not delete it while the producer code is live. Local evaluation cannot resolve a flag that does not exist, so shadow volume would drop to zero with no log and no counter.Alert, still open. This one blocks the ramp.
FlagsCacheInvalidationDeliveryFailuresin PostHog/charts fires at a threshold of 0 on any delivery failure for theflags_cache_invalidationtopic. Shadow messages and real invalidations share that topic, andposthog_kafka_producer_messages_totalcarries no label that separates them.Today a firing means a Kafka-routed team serves a stale
/flagspayload. After the ramp it mostly means one telemetry message did not land. The runbook still tells the responder to look for stale flag serving, and its mitigation step says to turn offflags-cache-kafka-dual-write. That is the serve-routing flag. So a lost shadow message can lead someone to disable the Rust serve path.Real invalidations come from the 3 canary projects. Shadow messages will come from every Celery-owned team. At 100% most firings of this alert would be false positives.
Suggested additions to the task list, above the ramp step:
flags-cache-shadow-comparegate flag at 0%FlagsCacheInvalidationDeliveryFailuresand its runbook in PostHog/charts, before the ramp