All posts

Why we answer only after the commit

What "your order is confirmed" has to mean when the server can be killed at any moment.

Sunrise breaking above a layer of clouds, photographed from orbit.
Photo: NASA

We test Spacestocks harshly on purpose. While traders are placing orders, the server process is killed with kill -9, at random moments, over and over. There is no warning and no chance to clean up. After each restart, every order the exchange had confirmed must still be there, and the books must still balance to the last share.

That rules out a lot of comfortable designs. Here is the one rule that gets us through it.

The rule

We send a confirmation only after the database has committed the change.

Placing an order touches several things at once: the order itself, any trades it makes, the cash and shares of everyone involved, and the reservations. All of it goes into one database transaction. The exchange waits for that transaction to commit, then updates its in-memory order book, and only then answers the trader.

What a crash can do now

There are only three moments a crash can land in, and each one is safe.

Before the commit. The transaction never finished, so the database throws all of it away. As far as the exchange is concerned, the order never arrived. The trader got no confirmation either, so nobody believes something happened that did not.

After the commit, before the reply. The order is in the database, but the trader never heard back. When the exchange restarts it reloads every open order from the database, and the trader can look the order up. The order exists and the trader can find it.

After the reply. Everything the trader was told is already on disk.

There is no fourth case where the trader was told “done” and the work is lost. That is the whole point.

Why not reply first and save later

Replying first feels faster, and it is, by a few milliseconds. But for those milliseconds the exchange has promised something it cannot keep. One badly timed crash and a confirmed order disappears, or worse, a trade is half-recorded: the buyer’s shares saved, the seller’s cash not.

For an exchange, a slightly slower confirmation is cheap. A broken promise is not.

The memory is a copy

The order book in memory makes matching fast, but it is never the source of truth. The database is. If anything goes wrong between the two, for example a connection that drops in the middle of a commit so we cannot tell whether it went through, the exchange throws that asset’s in-memory book away and reloads it from the database before touching it again.

What it costs

Every order waits for a commit, so throughput is limited by how fast PostgreSQL can make data durable. For an exchange serving hundreds of traders, that limit is far away. If we ever get close to it, the usual next step is to commit several orders in one transaction. We would still never reply before the commit.

Display

Theme
Text size
Line height
Reading
Seeing
Moving and navigating
Page structure

Headings

    Regions

      Saved in this browser only.