Skip to content
Sleep at nightData foundation

Retry-proof saves

Clicking twice never charges twice.

Every save happens exactly once, even when a flaky network makes the app retry. The data change, its follow-up work, and its receipt all commit together. If any part fails, nothing half-happens.

  • 1

    place that writes to your database

  • 1

    step that saves data, jobs, and receipt together

  • 3

    kinds of retry keys supported

The problem this solves

Without a shared foundation, every team rebuilds these edge cases — differently.

The double charge

A flaky connection retries a payment at 2 a.m. Your customer wakes up billed twice, and you spend the morning on refunds and apology emails. Cleaning up duplicates after the fact is guesswork.

The job that ran for nothing

The save failed, but the follow-up email still went out. Or the save worked and the job silently vanished. When data and side effects live in separate systems, they drift the moment anything errors.

The screen that lies

The UI says saved. A refresh says otherwise. Two people edit the same row and one edit quietly disappears. Nobody finds out until a customer does.

How it works

The mechanism end to end, as implemented in the repository.

  1. 1

    Bad input bounces at the door

    Every write is checked against a shared contract before it touches your data. The same check runs on the first try and on every retry.

  2. 2

    Duplicates wait in line

    A database lock makes two identical requests queue up instead of racing. Then the server checks if this save already has a receipt.

  3. 3

    Everything commits together

    The data change, its background jobs, and the receipt save in one database transaction. All of it lands, or none of it does.

  4. 4

    Retries replay the receipt

    A repeat request finds the receipt and gets the original answer back. Reusing an ID for a different write gets rejected.

Interactive example

See it working

This walkthrough demonstrates the implemented backend contract without using an account, credentials, or provider calls.

Interactive example

Follow the implemented lifecycle

  1. Parse inputCurrent
  2. Derive identityWaiting
  3. Authorize scopeWaiting
  4. Commit onceWaiting

Step 1 of 4: Parse input

Deterministic sample data only. No account, provider, or network connection is used by the interaction.

Highlights

Why it matters

One door for writes

Every change goes through the server. The browser can read, but it can never write straight to your database.

Retries get the same answer

Each save keeps a receipt. Send the same request again and you get the original result back, not a second row.

Follow-up work can't get lost

Background jobs save in the same step as the data. If the save rolls back, the job never runs.

Engineering guarantees

What this does and does not promise

Safety boundary

The browser never sees your database, secret keys, or the power to pick its own tenant. This protects the write itself. Checking your own business rules inside each command is still your job.

Implementation evidence

The boundary above is code, not a claim. These files carry the contract:

  • src/server/transactions.ts
  • src/server/permissions.ts
  • docs/CONVENTIONS.md
Questions

Frequently asked questions

Build on the retry-proof saves foundation

The docs describe the same contracts this page demonstrates.