In event-driven systems, a subtle bug often lies in wait: publishing the news before the fact is recorded. The bug is silent. It rarely appears in testing, revealing itself only in production, under load. A strict ordering rule resolves it entirely: save first, then publish.

The shape of the problem

When a component finishes work, it must perform two actions: write the result to durable memory, and publish a completion event. If you invert this sequence — emitting the event before the write commits — a race condition opens. A downstream component hears the event, reacts immediately, and attempts to read the result. Because the save has not yet completed, the consumer reads stale or empty data. The failure cascades from there.

The right order

The fix is strict linear execution: write the result to durable memory, ensure the commit has completed, and only then publish the event. Any component receiving the event is now guaranteed to find the corresponding data in memory. This enforces a core principle of event-driven architecture: the event is merely a trigger, and the truth is always in memory. If the truth is not yet written, the trigger must not fire.

Why this rule matters

This ordering aligns with another architectural constraint: the event should carry no data, only an identifier. Including state in the event creates the temptation to emit it before persisting the data — which introduces the exact race condition. When the event carries only a reference, forcing consumers to query the data store for the truth, the “save first, then publish” pattern transitions from a best practice to a logical necessity.

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

This approach carries a consequence. In durable systems, event delivery is almost always “at least once,” meaning an event may be delivered twice. Consumers must therefore be idempotent — processing the identical event twice must not produce an incorrect result. Combining strict publish-after-save ordering with idempotent consumers yields a system that neither drops messages nor corrupts state upon retry.

Putting it together

The rule appears minor, but it forms the boundary between a system that remains resilient under load and one that fails irreproducibly. Enforce the order of operations — record the fact first, then announce the change — and an entire class of race conditions is eliminated. In designing durable systems, deterministic operational orderings matter most.