C.W.K.
Stream
Lesson 02 of 05 · published

Persist the Paid Fact First

~10 min · receipts, write-ahead, ordering

Level 0Silent
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"The moment the provider says 'done and charged,' write that down — before you touch the audio. Everything after is reversible; that fact is not."

The Fact That Can't Be Undone

When a paid call succeeds, two very different kinds of thing happen. One is irreversible: you were charged, and there's a request ID and a cost that are now true forever. The other is reversible: you're going to validate the audio, maybe transcode it, maybe stitch chunks, and write it to the cache — all local work you can redo. Bellows persists the irreversible fact first. The receipt — request ID, cost, provider audio — lands in durable storage before any post-processing begins.

Why Order Is Everything Here

Imagine the other order: post-process first, save the receipt only if everything worked. Now a crash during transcode erases every trace that you paid. The credits are gone, the audio the provider made is gone, and your system doesn't even know it owes you a repair. By persisting the receipt first, a later failure is survivable: you still hold the request ID, the cost, and the raw provider audio, so the paid work can be repaired instead of blindly bought again.

This Is Write-Ahead, for Money

Databases have known this forever: write the intent to a durable log before you mutate the thing, so a crash mid-mutation is recoverable. Bellows applies the same shape to paid work. The receipt is the write-ahead record; the cache file is the mutation. The rule generalizes to any expensive irreversible step followed by cheap reversible ones — record the irreversible fact before you start the reversible work.

Code

Irreversible fact first, reversible work second·python
async def on_provider_success(job: Job, receipt: Receipt, raw_audio: bytes):
    # STEP 1 (first, ALWAYS): persist the paid fact + the raw provider bytes.
    # If anything below crashes, THIS survives -- we can repair, not re-pay.
    store.persist_receipt(job.id, receipt)          # request_id, cost, model
    lineage.save_raw(job.id, raw_audio)             # durable copy of paid audio

    # STEP 2 (after): the REVERSIBLE local work -- validate, transcode, cache.
    processed = transcode_and_validate(raw_audio)   # may fail; that's survivable
    cache.publish(job.identity, processed)

# Crash between step 1 and step 2? The receipt + raw audio are already durable.
# Reconcile rebuilds the cache file with NO new paid call.

External links

Exercise

Find a flow in a system you know with an expensive irreversible step followed by cheaper reversible ones — charge then send a receipt email, mint an ID then render a document, call an API then update a UI. Write down the current order of persistence. If the irreversible step's record isn't saved first, describe the state a crash in the middle leaves you in, and reorder it write-ahead style.
Hint
Ask: 'if the process died right after the irreversible step, would my system know it happened?' If the answer depends on a later step succeeding, the durable record is in the wrong place.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.