Rounding drift
An ordinary JavaScript number loses whole units above 253. RURAL keeps 64-bit integers in their declared domain.
Live check: Number(2^53 + 1) gives 9007199254740992. One unit gone.
We aim to build a database that is as fast and as exact as a financial ledger, and that stays that way for fifty years. This page shows what is real today, and what is still an aim.
Small errors do not stay small. They compound, they replay, and they hide behind a network timeout. A database for long-lived work has to refuse them at the door.
An ordinary JavaScript number loses whole units above 253. RURAL keeps 64-bit integers in their declared domain.
Live check: Number(2^53 + 1) gives 9007199254740992. One unit gone.
Networks repeat requests. A repeated payment must not become two payments. Retries carry an identity, and a replay returns the original answer.
A crash can land between "written" and "told you". RURAL treats an unknown outcome as its own state and makes it explicit. It does not guess.
Two accounts hold signed 64-bit balances. Move units between them. Push past a limit. Press the same idempotency key twice.
| Seq | Key | Move | A after | B after |
|---|---|---|---|---|
| No receipts yet. | ||||
The model checks every step with BigInt in your browser. Refusals change nothing. The receipt table is capped at 6 here to show bounded tables: a full table refuses, it never evicts. Nothing is stored or sent.
Replacing a report of 100 with 103 must produce 103, not 203.
A report is replaced by value, and a retried replacement returns the original receipt. A scalar analytics report works this way today.
100 + 103
203
The retry ran twice. The books are wrong and nothing says so.
same identity
103
The second request finds its receipt and gets the original answer.
The engine says "done" only after the change is on disk. Prepare, journal, sync, publish, receipt. In that order, every time.
TigerBeetle is a reference point for the aim. RURAL does not reuse its code and does not claim to match it.
| Capability | Today | Aim |
|---|---|---|
| Exact numbers | Today Checked signed and unsigned 64-bit values; overflow is refused. | Aim u128 amounts and identifiers. |
| Atomic transfer | Today Checked add, compare-and-set and atomic transfer between numeric values. | Aim Immutable accounts and transfers as first-class records. |
| Retries | Today Durable receipts bound to the request; replay returns the original. Tables are bounded (default 100,000) and never evict. | Aim The same guarantee at ledger scale. |
| Pending, posted, void | Not available. | Aim Two-phase transfers. |
| Linked events | Today Atomic document batches only. | Aim Linked ledger events that succeed or fail together. |
| Double-entry | No qualified double-entry ledger exists today. | Aim A qualified double-entry ledger. |
| Test ledger | Today A synthetic TEST_CREDIT ledger on a control branch: 16 accounts, 128 postings, no real money. | Aim A qualified ledger profile, kept apart from the synthetic one. |
| Throughput | No throughput or latency win over any incumbent has been shown. | Aim Targets stated only after they are measured. |
The commit-path invariants (acknowledged implies durable, exact receipt identity) are covered by bounded TLA+ models. That is not a certification and not a performance result.
Run checked arithmetic against the real engine in the playground, or read what the numeric profile does and does not promise.