- Sheet
- 02 / 05
- Rev
- 2026.08
- Title
- Campaigns that decide in millisecondsPlate 02
- Author
- B. BolekFrankfurt/M
- Client
- Confidential
- Role
- Architect
- Stack
- .NET Core · Event streaming · Distributed cache · React
Case study 02 · Confidential
Campaigns that decide in milliseconds
A real-time campaign engine: evaluate a customer against every live campaign, decide, and answer before the page finishes rendering.
01/Context
Campaign selection sat in a batch job. By the time a campaign reached a customer, the behaviour that qualified them for it was hours old. The work was to move the decision into the request path without making the request slow.
02/Constraints
Constraints
- Latency budget
- The decision is inside a user-facing request. It gets a fixed slice of the budget and it never gets to exceed it — a late answer is worse than a default one.
- Campaigns change constantly
- Marketing edits rules during the day. A rule change has to be live in seconds, without a deployment and without a cache stampede.
- Correct under load
- Eligibility, caps, and exclusions have to hold at peak, not just on average.
03/Architecture
Architecture
- Read path
- Campaign definitions are compiled to an in-memory decision structure on each node and swapped atomically on change. The hot path does no I/O it can avoid — no database call, no rules engine round trip.
- Write path
- Rule edits publish to an event stream; nodes rebuild and swap independently. A node that falls behind serves the previous version rather than blocking.
- Guardrails
- Every decision carries a deadline. When the budget is spent the engine returns the safe default and records the miss, so degradation is visible instead of silent.
04/Outcome
Outcome
- Campaign decisions moved from overnight batch to inside the request.
- Rule changes reach production in seconds without a release.
- Latency misses are measured and alerted rather than absorbed.