The three invariants

A balance store that can double-spend or go negative is not a balance store

Three properties hold no matter how operations interleave or how many times they are delivered. They are why amounts are integers in a minor unit and never floats, and they are stated as constraints in the reference.

And every one is enforced by SQLite, not by a check in a handler that a race can skip.

Atomic

Each operation is one batch — a D1 transaction. The ledger entry and the balance change commit together or not at all.

There is never a recorded movement with no matching balance change, and never a balance change with nothing recording it.

Idempotent

Every operation carries a caller-supplied ref, written as a UNIQUE ledger row.

A replay inserts a duplicate ref, which aborts the transaction — and the operation returns the balance unchanged.

A payout delivered twice pays once.

Overdraft-safe

A debit or a hold is applied by an UPDATE guarded by the account’s constraint:

CHECK (balance >= 0 AND held >= 0 AND held <= balance)

Never negative. Never over-reserved.

A movement that would break solvency aborts — including against a balance another concurrent operation just lowered — and surfaces ledger/insufficient_funds.

Which is why correctness lives in the schema

The constraint is on the table. Every path that moves a balance goes through it — the in-process API, the HTTP routes, a future path nobody has written yet.

A guarantee that lives in one code path is a guarantee the second code path does not have.

Amounts are integers in the minor unit

Never floats. So arithmetic is exact, and 0.1 + 0.2 is not a conversation anybody has to have about somebody’s balance.

A currency’s decimals only says how to display them. See currencies.

What this buys a wager

Hold the stake when the bet is placed, resolve it when the outcome lands.

The hold is what makes the stake unavailable without spending it — the balance is unchanged, the available amount drops, and the held <= balance half of the constraint is what stops a player reserving the same chips twice.

Then capture or release. Both are idempotent by the same ref rule, so a settlement delivered twice settles once.

ESC