A double-entry ledger for Go and PostgreSQL. Money goes in, money goes out, and the books always add up to exactly zero. Not “roughly zero”. Not “zero after the nightly job”. Zero.
Use it as a Go library inside your app, or run it as a standalone HTTP service (ledgerd).
"5403.23" and it’s stored as exactly 540323 cents.You need Go 1.25+ and PostgreSQL.
createdb ledger
LEDGER_DATABASE_URL="postgres://postgres@localhost:5432/ledger?sslmode=disable" \
LEDGER_API_TOKEN=change-me \
go run ./cmd/ledgerd
ledgerd sets up its tables and listens on port 7710. Say hello:
curl -H "Authorization: Bearer change-me" -X POST localhost:7710/currencies -d '{"code": "USD", "decimals": 2}'
Prefer Docker? make docker-build, then see the handbook.
go get github.com/otyang/ledger
svc := ledger.New(ledger.OpenDB(dsn))
svc.Migrate(ctx)
svc.RegisterCurrency(ctx, ledger.CurrencyParams{Code: "USD", Decimals: 2})
// Alice pays Bob 5403.23 USD. Debits equal credits, or it doesn't happen.
svc.Post(ctx, ledger.PostParams{Reference: "pay-1", Currency: "USD", Legs: []ledger.Leg{
{AccountID: alice, Direction: ledger.Debit, Value: "5403.23"},
{AccountID: bob, Direction: ledger.Credit, Value: "5403.23"},
}})
| I want to… | Go here |
|---|---|
| Browse the HTTP API and try requests | Interactive API reference on the website |
| Set it up properly, configure it, run it in production | The handbook: configuration, Go library, concepts, guarantees, operations, troubleshooting |
| Understand double-entry bookkeeping from scratch | Beginner guide, with a worked example |
| Look up every request and response field | API reference (Markdown) or the OpenAPI spec |
| Know how it works inside before changing it | Architecture and internals |
Everything is also on the website: otyang.github.io/ledger/docs.
All the docs in one list:
| Doc | What’s in it |
|---|---|
| Website | The handbook as a website, with a contents sidebar and copyable code |
| Interactive API reference | Every HTTP endpoint with schemas and code samples, rendered from the OpenAPI spec |
| OpenAPI 3.0 spec | The machine-readable API definition, for code generators, Postman or your own tools |
| Handbook | Setup, configuration, the Go library, concepts, guarantees, operations and troubleshooting |
| Beginner guide | Double-entry bookkeeping explained with a worked example, from top-up to month-end |
| API reference (Markdown) | Every endpoint’s fields, status codes, errors and real example responses |
| Architecture and internals | How posting, locking, idempotency, holds, events and the database rules work |
| Go package docs | Generated reference for every exported Go type and function |
Pull requests are welcome. Run make check first (formatting, vet, and every test with the race detector), add tests for new behaviour, and add your name or GitHub handle to AUTHORS. No email needed.
Maintained by otyang, with thanks to everyone who has contributed.
Apache License 2.0. Copyright 2026 The ledger Authors. Use it, change it, ship it in commercial products; just keep the LICENSE and NOTICE files.