Invental/Review lessons/Writes that span systems

Writes that span systems

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.

01 · Before and afterThe pattern

TypeScript
// claim → side effects → on failure, put the durable row back first
const won = await db.update(runs).set({ status: "running" })
  .where(and(eq(runs.id, id), ownedByCaller(), eq(runs.status, "waiting")));
if (!won) return { resumed: false };
try { await cache.save(state); await queue.publish(step); }
catch (e) { await retry(() => revertToWaiting(id)); await cache.restore(prev); throw e; }

02 · Run it on your appThe check

For each compare-and-set in your app, does the WHERE clause include tenant/workspace, and what undoes it if the next step fails?

If the honest answer is no or not sure, this is worth a look before it reaches production.

Want this checked on your code?

Tell us what you are building and what worries you. We match a senior reviewer to your code and confirm scope before anything starts.

— Get in touch
hi@invental.co ↗
— Or
— What to include

A link or short description of the code or system, what you want checked, your stack, and when you need the answer. No repository access is needed until scope is agreed.

— Or leave a note
We reply within one business day.