Course contents
On this page
Trace one purchase through the engine you can build
Connect representation, concurrency, recovery, retries, and delivery through a final failure trace.
Return to the shop’s last item. Product 27 has stock 1. Two buyers want it. A successful purchase must create one order and consume one unit; stock must never become negative. A client retry must not create a second purchase for the same intention.
This final walkthrough assembles the course’s mechanisms. It is a specification for an educational implementation and its tests, not evidence that an engine is ready for production.
Make the smallest complete decision path
Begin with one process and local persistent storage. Serialize purchase transactions with one execution lock. That limits concurrency but gives the first implementation a clear ordering. Use private pending changes and the logging model already taught; readers must not observe partially installed changes.
A request carries identifier R17. Within the protected transaction, the engine checks for an earlier result for R17. If none exists, it checks stock, prepares stock 0, creates order 501, and records the result for R17. Those changes form one atomic unit.
- Decide from protected state
R17 is new and stock is 1. Prepare stock 0, order 501, and the request result.
- Make the decision recoverable
Persist the complete log records and commit decision under the stated storage assumptions.
- Publish and reply
Install the committed state without exposing a partial transaction. Return order 501.
A second buyer enters afterward and sees stock 0, so its purchase fails without creating an order. Indexes can shorten the lookups, but they do not replace the transaction’s decision rule.
Crash at the moment that matters
Suppose the engine persists R17’s commit, then crashes before replying. On restart, recovery reconstructs stock 0, order 501, and R17’s result before accepting requests. When the client retries R17, the engine returns order 501 instead of decrementing stock again.
If the crash happened before a valid durable commit, recovery would discard that incomplete transaction under this model. The client still has an uncertain outcome until it queries or retries; its timeout is not evidence of abort.
To notify shipping, include an outbox record in the transaction and deliver it afterward. Delivery can repeat, so the receiver needs the deduplication contract taught earlier. A network notification is not part of a local disk commit merely because it appears next in the code.
Turn each promise into an experiment
Test the engine against a simple in-memory reference model. Check stock and orders after interleaved purchase attempts. Inject crashes before and after log writes, persistence requests, installation, and replies; restart and inspect the recovered state. Test truncated logs and explicitly define the corruption behavior your implementation supports.
Then measure scans, indexed lookups, cache misses, and commit latency. Add concurrency or replication only after naming the limit or failure the new mechanism must address. The linked learning path gives implementation milestones; the extended chapter develops the larger architectures.
Predict the missing request record
The order and stock recover correctly, but R17’s result was stored only in memory. What guarantee is now missing?
Replay the client's retry
The engine cannot reliably recognize that R17 already succeeded. It may report failure because stock is now zero, or duplicate the purchase if more stock arrives. Recovering the business state alone does not recover the request’s identity and result. They must be connected by the durable transaction contract.
Continue with the implementation milestones and readiness gates. Use SQLite’s testing account as a concrete example of how much evidence lies beyond a successful demonstration.
Extended reference
The extended chapter preserves the original technical coverage, additional examples, and citations. The explanation above supplies the concepts needed for this page; the reference develops the specialist cases.
Find a section from the original chapter
- Learning outcomes
- Begin with one invariant and an explicit failure model
- Stage 2: introduce atomic recovery
- Stage 3: make retries one logical operation
- Stage 4: choose concurrency from the workload
- Stage 5: separate execution from durability waiting
- Stage 6: add checkpoints and bounded recovery
- Stage 8: define reads and failover capacity
- Stage 9: shard along real ownership boundaries
- Stage 10: cross-shard operations force a choice
- Stage 11: maintain realtime state without coupling clients to commit
- Stage 12: operate under overload rather than assuming it away
- Stage 13: make operational state part of the design
- Three final architectures, three reasons
- A final failure trace through the complete system
- What the architecture has actually optimized
- Sources and further reading