Immutable Double-Entry Ledger
A ledger core built so balances can be proven rather than merely stored: append-only postings, no in-place mutation.
At a glance
- Append-only double-entry postings with derived balances
- Immutable journal suitable for audit and dispute
- PostgreSQL persistence with Redis-backed read paths
- Idempotent posting API keyed by transaction reference
- Reconciliation checks for debit/credit invariants
From the repository
README
High-Concurrency Autonomous Financial Accounting Engine with Mathematical Invariants & Distributed Idempotency
Overview • Key Features • Architecture • Core Workflow • Tech Stack • Structure • Quick Start • API Reference • Stress Testing
📌 Overview
The Immutable Double-Entry Ledger Core Engine is an enterprise-grade financial transaction engine designed to solve the foundational challenge of modern fintech infrastructure: guaranteeing absolute mathematical consistency, zero drift, and deadlock-free execution under massive concurrent load.
Standard database implementations in financial applications often fall prey to floating-point truncation, race conditions, bidirectional deadlocks, and silent data drift caused by in-place updates. This engine adheres to classical double-entry bookkeeping rules combined with modern distributed systems design:
- Zero Mutation Policy: All operations are strictly append-only. No
UPDATEorDELETEqueries are ever run against transaction records or journal entries. - Deterministic Concurrency: Account locks are acquired in sorted ascending sequence, rendering circular lock deadlocks impossible even during bidirectional financial transfers.
- Two-Tier Distributed Idempotency: Redis in-memory reservation (
SET NX PX) coupled with Postgres unique constraints prevents duplicate execution across network retries. - Arbitrary Precision Arithmetic: Full
NUMERIC(28, 6)fixed-point math completely eliminates IEEE 754 precision leakage.
✨ Key Features
- 📜 Strict Append-Only Ledger: Compliant with GAAP, IFRS, and SOC-2 audit requirements. Corrections are managed exclusively via compensating reversal transactions.
- ⚖️ Mathematical Balance Invariant: Every transaction requires $\ge 2$ entries enforcing $\sum \text{Debits} = \sum \text{Credits} > 0$. Unbalanced transactions are rejected before touching the disk.
- 🔒 Deadlock-Free Row-Level Locking: Dynamically sorts target account UUIDs in ascending lexicographical order prior to executing
SELECT ... FOR UPDATE, guaranteeing linear lock acquisition. - 🛡️ Distributed Idempotency Protection: Enforces
Idempotency-Keyheaders on all mutations. In-flight requests lock via Redis for 15s; finalized payloads are cached for 24h. - 🧮 Fixed-Point Precision (
shopspring/decimal): Zero use offloat32orfloat64. All monetary units use fixed-point arbitrary precision decimal math down to 6 fractional decimal digits. - ⚡ Dynamic Settled Balance Computation: Balances are dynamically aggregated on-the-fly directly from settled journal entries, completely eliminating balance caching divergence.
- 🚫 Overdraft Protection Engine: Enforces real-time balance checks within the isolated transaction snapshot; non-overdraft accounts cannot drop below zero.
🏛️ System Architecture
The system decouples client ingestion, idempotency middleware, domain invariant orchestration, and append-only database persistence into a clean, testable modular architecture.
Visual Architecture Diagram
🔍 Open Standalone Interactive HTML Architecture Viewer
Native Mermaid Architecture
Component Breakdown & Trust Boundaries
| Component | Layer | Responsibilities & Invariants Enforced |
|---|---|---|
| Idempotency Middleware | Transport | Intercepts all mutation endpoints. Executes atomic reservation (SETNX) on Redis. Returns 400 if header missing, 409 Conflict if in-flight, and replayed cached body on duplicate calls. |
| Ledger Service | Application | Validates mathematical equality ($\sum \text{Debit} = \sum \text{Credit}$), sorts participating account IDs, computes post-transaction balances, and coordinates transactional commits. |
| Deterministic Lock Sorter | Concurrency | Orders all target account UUIDs lexicographically in ascending order prior to executing SELECT ... FOR UPDATE row locks, breaking circular wait dependency graphs. |
| PostgreSQL Repository | Persistence | Houses the system of record. Enforces foreign key integrity, schema unique constraints on idempotency_key, and strict append-only constraints on journal_entries. |
| Redis Cache Manager | In-Memory | Manages transient in-flight distributed locks (15s TTL) and caches settled transaction JSON payloads (24-hour TTL) for idempotent replay. |
⚡ Transfer Execution Lifecycle
Every balance transfer undergoes an atomic, six-stage lifecycle ensuring consistency and resilience across high-concurrency workloads.
Visual Workflow Sequence
🔍 Open Standalone Interactive HTML Sequence Viewer
Native Mermaid Sequence Workflow
Execution Protocol Breakdown
- Client Submission: The client issues an HTTP POST to
/api/v1/transferscontaining anIdempotency-Keyheader and payload. - Distributed Reservation: Redis evaluates
SETNX idempotency:{key} IN_FLIGHT PX 15000:- If cached, returns HTTP 200 immediately (
X-Cache-Lookup: HIT). - If
IN_FLIGHT, rejects immediately with HTTP 409 Conflict. - If novel, acquires the distributed lock.
- If cached, returns HTTP 200 immediately (
- In-Memory Invariant Verification: Service verifies that total debits equal total credits, amounts are strictly positive, and source/destination currencies match before opening a database transaction.
- Deterministic Lock Acquisition: The service sorts all participating account UUIDs in ascending sequence and issues
SELECT ... FOR UPDATEqueries in that exact order, completely preventing circular deadlocks. - Dynamic Overdraft Guard: Settled balance is calculated dynamically from ledger entries within the transaction snapshot. If
allow_overdraft == falseand the projected balance is negative, the transaction aborts with422 Unprocessable Entity. - Append-Only Commit: The transaction record and balanced debit/credit journal entries are written in an atomic batch. The database transaction commits.
- Cache & Delivery: The completed HTTP response is cached in Redis with a 24-hour TTL, releasing the
IN_FLIGHTstate, and returns HTTP 200 to the caller.
🛠️ Tech Stack
| Technology | Role | Version / Library | Rationale |
|---|---|---|---|
| Go | Core Engine Language | 1.22+ | High-concurrency goroutine scheduling, low memory overhead, and strong typing. |
| PostgreSQL | Primary Database | 16-alpine | ACID-compliant transaction semantics, row-level FOR UPDATE locking, and robust indexing. |
| Redis | Distributed Cache & Locks | 7-alpine | Sub-millisecond atomic key-value operations (SETNX, PX, TTL) for distributed idempotency. |
| Chi | HTTP Router | github.com/go-chi/chi/v5 | Lightweight, idiomatic Go HTTP router with zero external allocations and standard net/http compatibility. |
| Decimal | Monetary Mathematics | github.com/shopspring/decimal | Precision fixed-point arithmetic (NUMERIC(28, 6)) eliminating IEEE 754 floating point inaccuracies. |
| UUID | Identifier Generation | github.com/google/uuid | Globally unique identifier generation for accounts, transactions, and journal entries. |
| Docker Compose | Local Orchestration | v3.8 | Reproducible local developer environment provisioning for Postgres and Redis. |
| Testify | Test Suite | github.com/stretchr/testify | Clean, expressive assertions for concurrency stress tests and unit test suites. |
📂 Repository Structure
.
├── cmd/
│ └── api/
│ └── main.go # Server bootstrap, configuration, and graceful shutdown
├── docs/
│ ├── architecture.html # Interactive standalone HTML system architecture diagram
│ ├── transfer_workflow.html # Interactive standalone HTML sequence workflow diagram
│ └── assets/
│ ├── architecture.svg # Vector SVG system architecture diagram
│ └── transfer_sequence.svg # Vector SVG transfer sequence diagram
├── internal/
│ ├── domain/
│ │ ├── account.go # Account entity, account types, and validation
│ │ ├── entry.go # JournalEntry entity, DEBIT/CREDIT types, and rules
│ │ └── transaction.go # LedgerTransaction model and mathematical balance invariants
│ ├── repository/
│ │ ├── postgres/
│ │ │ ├── account_repo.go # Deterministic row locking (SELECT ... FOR UPDATE)
│ │ │ ├── db.go # Connection pooling and PostgreSQL driver setup
│ │ │ └── ledger_repo.go # Append-only transaction and entry insertion, dynamic balance
│ │ └── redis/
│ │ └── idempotency.go # Distributed atomic locks and 24h payload caching
│ ├── service/
│ │ ├── ledger_service.go # Orchestration, balance calculation, and overdraft guards
│ │ └── ledger_service_test.go # Unit tests verifying invariants and overdraft rules
│ └── transport/
│ └── http/
│ ├── handler.go # REST HTTP handlers for accounts, transfers, balances
│ ├── middleware.go # Distributed Idempotency HTTP middleware
│ └── router.go # Chi v5 router definitions and middleware chaining
├── migrations/
│ └── 000001_init_ledger_schema.sql # DDL schema for accounts, ledger_transactions, journal_entries
├── tests/
│ ├── concurrency_test.go # High-load race & deadlock stress tests (50+ parallel workers)
│ └── integration_test.go # End-to-end integration test suite
├── docker-compose.yml # PostgreSQL 16 & Redis 7 container configuration
├── Makefile # Developer CLI automation (up, down, migrate, test)
├── go.mod # Go dependencies definition
├── go.sum # Dependency checksums
└── README.md # Project documentation & landing page
🚀 Quick Start & Local Setup
Prerequisites
- Go 1.22+ installed locally
- Docker & Docker Compose installed and running
curlor Postman for API testing
1. Clone the Repository
git clone https://github.com/Kavryx-Dev/Immutable-Double-Entry-Ledger-Core-Engine.git
cd Immutable-Double-Entry-Ledger-Core-Engine
2. Start PostgreSQL & Redis Containers
Start the persistent PostgreSQL 16 and Redis 7 instances:
docker compose up -d
[!NOTE] Postgres is mapped to host port
35432and Redis is mapped to36379to avoid conflicts with default local service ports.
3. Verify Database Schema Migration
The database schema initializes automatically from migrations/000001_init_ledger_schema.sql on startup. To verify or manually run:
make migrate
4. Run the Engine
Compile and run the HTTP service:
go run ./cmd/api/main.go
The server will start on port 8080:
2026/10/12 15:45:00 Starting Immutable Double-Entry Ledger Core Engine...
2026/10/12 15:45:00 Connected to PostgreSQL successfully.
2026/10/12 15:45:00 Connected to Redis successfully.
2026/10/12 15:45:00 HTTP server listening on :8080
📡 API Reference
1. Health Check
curl -X GET http://localhost:8080/health
Response (200 OK):
{
"status": "ok"
}
2. Create an Account
curl -X POST http://localhost:8080/api/v1/accounts \
-H "Content-Type: application/json" \
-d '{
"code": "ACC-USER-101",
"currency": "USD",
"account_type": "ASSET",
"allow_overdraft": false
}'
Response (201 Created):
{
"id": "e458e0a2-a276-4d51-93db-9da642f4dc23",
"code": "ACC-USER-101",
"currency": "USD",
"account_type": "ASSET",
"allow_overdraft": false,
"version": 1,
"created_at": "2026-10-12T10:15:00Z"
}
3. Execute a Transfer (Idempotent Double-Entry)
curl -X POST http://localhost:8080/api/v1/transfers \
-H "Content-Type: application/json" \
-H "Idempotency-Key: tx-uuid-98472948-4411" \
-d '{
"source_account_code": "ACC-VAULT-001",
"destination_account_code": "ACC-USER-101",
"amount": "250.000000",
"description": "Initial funding transfer"
}'
Response (200 OK):
{
"id": "7f8b9e6a-1b42-4f9e-9d2a-87428f58b012",
"idempotency_key": "tx-uuid-98472948-4411",
"description": "Initial funding transfer",
"status": "POSTED",
"posted_at": "2026-10-12T10:15:05Z",
"entries": [
{
"id": "3b29c928-874f-4d33-912a-3e8f815b3a4a",
"transaction_id": "7f8b9e6a-1b42-4f9e-9d2a-87428f58b012",
"account_id": "c138d821-65b1-4191-8fa1-7f938b1d91a1",
"entry_type": "CREDIT",
"amount": "250",
"created_at": "2026-10-12T10:15:05Z"
},
{
"id": "4c39d039-985a-5e44-a23b-4f9a926c4b5b",
"transaction_id": "7f8b9e6a-1b42-4f9e-9d2a-87428f58b012",
"account_id": "e458e0a2-a276-4d51-93db-9da642f4dc23",
"entry_type": "DEBIT",
"amount": "250",
"created_at": "2026-10-12T10:15:05Z"
}
]
}
[!TIP] If you repeat the exact same request with header
Idempotency-Key: tx-uuid-98472948-4411, the server returns the cached response with headerX-Cache-Lookup: HITwithout re-executing ledger writes.
4. Query Settled Account Balance
curl -X GET http://localhost:8080/api/v1/accounts/ACC-USER-101/balance
Response (200 OK):
{
"account": {
"id": "e458e0a2-a276-4d51-93db-9da642f4dc23",
"code": "ACC-USER-101",
"currency": "USD",
"account_type": "ASSET",
"allow_overdraft": false,
"version": 1,
"created_at": "2026-10-12T10:15:00Z"
},
"balance": "250"
}
🧪 Concurrency & Stress Testing
The engine includes rigorous integration and stress tests verifying zero deadlocks and zero balance drift during high-contention bidirectional fund movements:
# Run unit tests across domain and service layers
make test
# Run high-concurrency race condition and deadlock stress tests
make test-concurrency
What the Concurrency Test Proves:
- 50 concurrent goroutines transfer
$20.00fromAccount A$\rightarrow$Account B. - 50 concurrent goroutines simultaneously transfer
$20.00fromAccount B$\rightarrow$Account A. - Deadlock Detection Assertion: Confirms 0 occurrences of PostgreSQL error
pq: deadlock detected. - Conservation of Money Guarantee: Asserts: $$\text{Balance}(A) + \text{Balance}(B) \equiv $1,000.000000$$
- Overdraft Protection Enforcement: Asserts that non-overdraft accounts are rejected when their balance is insufficient, never dropping into negative values.
🔒 Security & Data Integrity Guarantees
- Zero Mutation Invariant: No SQL
UPDATEorDELETEqueries exist in the codebase forjournal_entriesorledger_transactions. - SQL Injection Immunity: 100% parameterized SQL queries via
database/sql. - Graceful Termination: Listens to
SIGINT/SIGTERMsignals and gives active HTTP transactions 5 seconds to commit or safely roll back. - Precision Floating Point Ban: Any compilation involving standard floats for financial arithmetic is rejected at domain boundaries.
👥 Contributing
- Fork the repository.
- Create your feature branch (
git checkout -b feature/compensation-workflows). - Commit your changes with descriptive commits (
git commit -m "feat: add automatic reversal helper"). - Run tests and race detector (
go test -v -race ./...). - Push to the branch (
git push origin feature/compensation-workflows). - Open a Pull Request.
📄 License
This project is licensed under the MIT License — see the LICENSE file for details.