In a system whose components are connected by events, a subtle but frequent bug lies in wait: publishing the news before the fact has been recorded. This bug is silent — it often doesn’t show up in testing and only reveals itself in production, under load. Fortunately, a simple rule uproots it entirely: save first, then publish.

The shape of the problem

Imagine a component finishes some work and has to do two things: store the result in durable memory, and publish an event saying “the work is done.” If you reverse the order — publish the event first and then store — a dangerous window opens. A component that hears the event may react immediately and go read the result from memory — but the result isn’t there yet, because the save hasn’t happened. Now a consumer sees stale or empty data, and the bug begins right there.

The right order

The solution is to keep the right order: first write the result to durable memory and make sure the write has completed, and only then publish the event. Now any component that hears the event is guaranteed that when it goes to memory, the fact is there. This is the very principle we state in event-driven architecture: the event is only a trigger, and the truth is always in memory. If the truth isn’t written yet, you shouldn’t send a trigger.

Why this rule matters

This rule aligns with another important principle: the event should carry no data, only an identifier. If you put data in the event, you’re tempted to send it before the save — and that’s exactly where you get caught. But when the event carries only an identifier and the consumer is forced to read the truth from memory, then the “save first, then publish” order becomes not a choice but a logical necessity.

At-least-once, not at-most-once

There’s one important consequence to accept. In durable systems, event delivery is usually “at least once”: an event may be delivered twice. This means consumers must be idempotent — that is, processing the same event twice should not produce an incorrect result. Combining “save first, then publish” with idempotent consumers builds a system that neither loses messages nor is harmed by repeated ones.

Putting it together

This rule looks small, but it’s the difference between a system that stays reliable under load and one that errs occasionally and irreproducibly. Get the order of operations right — record the fact first, then announce it — and a whole class of race-condition bugs simply disappears. In designing durable systems, it’s often these simple orderings that matter most.