ADR 0001 — Implementation language: strictly-typed Python first, Rust later if needed
- Status: Accepted — 2026-08-05
- Context: CLAUDE.md §4 requires choosing between Rust and strictly-typed Python after comparative research (see docs/research/ledger-engines.md and llvm-architecture.md).
Decision
Phase 1–4 are implemented in Python 3.11+ with strict typing (Pydantic v2
models, mypy --strict-compatible code, frozen dataclasses). A Rust port of
the hot core (AIC passes + invariant verifier) remains an explicit later
option once the spec stabilizes.
Rationale
- Correctness needs here are logical, not mechanical. The invariants that matter (double-entry balance, exact decimals, determinism) are enforced by design (Decimal everywhere, floats rejected at every boundary, verifier after every pass) — not by the borrow checker. TigerBeetle-class problems (throughput, crash-safety under a million TPS) are not Phase 1 problems.
- Iteration speed on a moving spec. AIR/ALSL formats will churn during
Phases 1–3; Python + Pydantic gives schema evolution, JSON Schema
generation (
model_json_schema()), and golden-test iteration far faster. - Ecosystem adjacency. Ingestion (Phase 4) is LLM/OCR tooling, which is Python-native; the property-testing story (hypothesis) is mature.
- Exactness parity. Python's
decimal.Decimalprovides the same fixed-point guarantees asrust_decimal; both round via explicit modes.
Consequences
- JSON Schema is generated from the Pydantic types today; when the schema stabilizes, the direction flips (schema-first, generated types) per CLAUDE.md §3.1.
- Performance-critical kernels (batch compilation, reconciliation) may move to Rust behind the same AIR/ALSL contracts; the format, not the code, is the interface (see docs/research/llvm-architecture.md, lesson 1).