Stories · Season 3 — Magpie · Episode 08
The Fraud Team Who Showed Up Late
In which Magpie hires a fraud team a year too late, and asks them to analyze events that — until now — nobody was listening to.

The story
For Magpie’s first year, “fraud detection” was Owen squinting at a spreadsheet on Sunday nights. It worked until it spectacularly didn’t, and Magpie hired an actual fraud team with an actual model. The model needed to watch the stream of money movements — deposits, transfers, card payments — in real time, and it needed to train on the entire history that had happened before it existed.
This is where Kemi hit the wall. New consumers of an event stream have two awkward needs at once: catch up on everything that already happened, and then keep up with everything new — without missing or double-reading anything across restarts. The quick hacks all failed. Reading “from now on” meant the model had no history to learn from. Reading “from the beginning” with a hand-tracked position meant that every deploy or crash risked either re-processing events (double-counting suspicious activity) or skipping them (missing the fraud you hired the team to catch).
Then the second fraud consumer arrived — a separate “spending insights” feature that also wanted to read the same stream from the beginning, at its own pace, without interfering with the fraud model’s progress. Kemi’s home-grown position-tracking was now being copy-pasted per consumer, each with its own subtly broken bookkeeping.
“Every new thing that wants to read our history,” Kemi said, “is reinventing the same fragile cursor.”
Why this is hard the traditional way
Reading an event log reliably, over time, is harder than it looks. A consumer needs a durable position — where am I up to? — that survives restarts, so it neither re-reads (causing duplicates) nor skips (causing gaps). It needs to start from the beginning to get history, then transition smoothly to live tailing. And when you have multiple independent consumers, each needs its own position, advancing at its own speed, without stepping on the others.
Hand-rolled, this becomes a last_processed_id column per consumer, updated by
hope, with all the classic bugs: update the position before processing and a crash
loses events; update after and a crash double-processes; share a position between
consumers and they corrupt each other. Every new consumer re-implements — and
re-breaks — the same logic.
How Relay changes the ending
Relay provides persistent named subscriptions: durable, named readers over the global event log. Each subscription has its own saved position, can start from the beginning to replay all history and then follow live, and resumes exactly where it left off after any restart. Adding a new consumer is naming a new subscription — not rebuilding a cursor.
// The fraud model: one named, durable reader. Replays all history, then tails live.
var fraud = await subscriptions.SubscribeAsync(
name: "fraud-model", from: Position.Beginning);
// Spending insights: a second, independent subscription with its own position.
var insights = await subscriptions.SubscribeAsync(
name: "spending-insights", from: Position.Beginning);
// Each resumes exactly where it left off after a restart. Neither affects the other.
Now the fraud team gets exactly what they asked for: train on a year of real history, then watch live, with a position that survives deploys so nothing is double-flagged or missed. The insights feature reads the same history at its own pace without collision. And the next consumer — whatever Magpie dreams up — is a new named subscription, not another fragile cursor to debug.
What it costs you to ignore this
- New consumers can’t see the past. “From now on” is useless for anything that needs to learn from history — fraud, analytics, ML.
- Hand-tracked positions lose or duplicate events. The crash-at-the-wrong-moment bug is subtle, recurring, and exactly what you can’t afford in fraud.
- Consumers collide. Sharing position state means one reader’s progress corrupts another’s.
- Every new reader re-pays the cost. Without durable subscriptions, each feature reinvents — and re-breaks — the same bookkeeping.