·Back to demos
Sessioninitializing…
Watch this session →
← All posts
EngineeringMay 22, 2026·Lia M.

Inside the cycle engine: how we scope two-week sprints across 12k workspaces

When a customer rolls a cycle, three things need to happen atomically: the cycle marks itself complete, incomplete issues either roll forward or get explicitly dropped, and the next cycle starts its clock. For a long time these were three Postgres updates wrapped in a transaction, plus a Redis cache invalidation, plus a webhook fan-out. It worked. It also took 400-800ms per workspace at p99, and the Redis cache was the source of every cycle-related incident we had in 2025.

In Q1 we collapsed the whole thing into a single Postgres CTE that returns the new cycle row directly. The Redis cache went away. p99 is now 47ms. The webhook fan-out moved to a side-effect log we drain async, which means the user-facing operation no longer waits on third-party HTTP.

What we learned: caching state that changes on a fixed cadence is almost always wrong. The cache hit rate looked great, but every miss was a "cycle is rolling" miss — which is the only time the data actually matters. Source of truth, no cache.