┌────────────────────────────────────────────────────────────┐ │ TRANSACTOLOGY.DEV :: the science of moving money safely │ └────────────────────────────────────────────────────────────┘
transactology.dev
// developer-facing toolkit for high-throughput transaction processing
$ cat ./README.md
Welcome to transactology. We build primitives for engineers who treat "a transaction" as a first-class citizen of their architecture — not an afterthought stitched into request handlers.
Atomicity. Idempotency. Linearizability. These are not buzzwords here. They are contracts that the runtime enforces.
$ npm install @transactology/core
// resolving dependencies... + @transactology/core@4.2.1 + @transactology/ledger@2.8.0 + @transactology/runtime@1.6.4 added 3 packages in 1.42s
// 01. atomic boundaries
import { tx } from "@transactology/core"; await tx(async (ctx) => { const debit = await ctx.account("acc_a3f8c2").debit(42.00); const credit = await ctx.account("acc_b7e1d9").credit(42.00); return { debit, credit }; }, { isolation: "serializable", retries: 3 }); // → commit hash: 3f8c2a • 1.8ms • OK
$ transactology --features
- [ok] serializable + snapshot isolation, per-call
- [ok] deterministic retry with exponential jitter
- [ok] append-only ledger, content-addressed commits
- [ok] p99 latency < 4ms at 12k tx/s sustained
- [ok] first-class idempotency keys, 7-day window
- [~] two-phase commit across regions (beta)
- [~] SAGA orchestration DSL (beta)
// 02. mental model
Every tx() call opens an atomic boundary. Inside it, the world is yours: reads are consistent, writes are buffered, side effects are queued. On commit, the runtime fuses the buffered write-set into the global ledger using a "first-writer-wins" reconciliation pass, then drains side effects to the bus.
If anything throws, nothing happened. There is no "partial state" to clean up. There is no compensating action to remember. There is, in fact, very little to remember at all — which is the point.
┌──────────┐ open() ┌──────────────┐ commit() ┌────────┐
│ caller │ ─────────────> │ tx{ctx} │ ─────────────> │ ledger │
└──────────┘ │ read-set │ └────────┘
│ write-set │
│ side-effects│
└──────────────┘
│ rollback()
▼
(∅ noop)
// 03. observability, by default
Every transaction emits a structured trace before it is even acknowledged: input hash, isolation level, retry count, write-set size, commit hash, wall-clock latency. Pipe it into your favorite sink — OpenTelemetry, ClickHouse, a flat file. The runtime does not care.
on("tx.commit", (e) => { console.log(`[${e.ts}] TX_OK hash=${e.hash} amt=${e.amount} lat=${e.lat}ms`); });
// 04. getting started
- 01. npm install @transactology/core
- 02. point TRANSACTOLOGY_LEDGER_URL at any postgres >= 14
- 03. wrap your handler in tx()
- 04. stop worrying about partial writes
$ █
┌─ runtime ──────────────────────┐ │ region us-east-1 / eu-west-1│ │ nodes 7 / 7 healthy │ │ load ▓▓▓▓▓▓▓▓░░ 72% │ │ ledger append-only • OK │ └────────────────────────────────┘