Say what state each failed step left behind
A rollback is only as good as its error messages: each failure point in a multi-step remote change must say exactly what state it left, or the user's “fix” makes things worse.
Read the lesson →A claim across a row, cache and queue needs undo
When a state change spans a database row, a cache and a queue, write the durable row first, make the claim tenant-scoped, and give every step after the claim a way back to the previous state.
Read the lesson →Dry runs inherit every side effect
A “dry run” endpoint inherits every side effect of the real path unless hooks can tell it's a dry run, and it can still say “valid” for data the database will reject (unique constraints). Design both into the API on day one.
Read the lesson →Close the streams you hand to other code
Every time a pipeline passes a stream to code it doesn't control, it owns closing that stream when that code throws. A codemod should never remove the old thing before the new thing is in place.
Read the lesson →Stage, commit, then delete old files
When a write spans a database and object storage, order it so every crash point leaves a recoverable state: stage the new object, commit the row, then delete the old object after the commit. Never delete before the commit.
Read the lesson →Usage metering must never fail the request
Metering and audit writes are side effects of a request, not part of its result: if recording usage can throw, a successful (and already paid-for) model call can reach the user as a failure, or a DB blip can hide the real error.
Read the lesson →Run every rejecting check before any write
Do every check that can reject a target before you write anything for that target; otherwise a retry against a different target succeeds and leaves the first one with an orphaned “in progress” record that nothing will ever finish.
Read the lesson →Re-check the owner after a remote create
When creating a remote resource takes time, the owner can disappear in the meantime. Re-check that the owner still exists after the create returns, and undo the create if not. A disconnect hook can't delete what it can't see yet.
Read the lesson →