The thesis
A business app's audit log can be its database — not adjacent to it.
That sentence is the whole pitch. Everything else is consequences.
What a normal ERP looks like
Customer row → Postgres. Invoice row → Postgres. updated_at column. An audit table on the side that the app code remembers to write to. A reporting database that nightly-ETLs the live one. Backups via pg_dump. Branching for what-if scenarios? Nope.
The audit trail and the data are two different artifacts maintained by two different code paths. Most of the time they agree. Sometimes they don't. When they don't, you find out months later.
What accelerando does
Every record is a .agi file in a git repo. Creating an invoice is a git commit. Editing it is another git commit. The audit log isn't a thing the app remembers to write — it's a thing the app cannot help but write, because writes are commits.
The disk shape:
data/
acme/
Invoice/
8f3b2e1a-....agi
ad9320de-....agi
Customer/
30cf071b-....agi
The audit shape:
$ git log data/acme/Invoice/8f3b2e1a-....agi
3a4f8b2 edit Invoice 8f3b2e1a: status → paid
Christopher Bender, 2 hours ago
c91d7e5 edit Invoice 8f3b2e1a: due_date → 2026-07-25
Christopher Bender, 1 day ago
64bbf4f create Invoice 8f3b2e1a
Christopher Bender, 4 days ago
That's not a feature. That's just how the system works.
What this proves
- You don't need an event bus to have event sourcing. Git is one. The objects are immutable, the history is total, the diffs are first-class.
- You don't need a backup product.
git cloneis the backup.git pushis the offsite replication. - You don't need branches as a roadmap feature. Forecast as a branch. Year-end close as a tag. What-if scenarios as pull requests against
main. - You don't need to choose between speed and durability. The hot path writes one small text file. The query path reads a derived SQL projection that rebuilds from the canonical tree on demand.
What this isn't
- It isn't fast at "select * from invoices where total > 10000" without the SQL projection. The git tree alone would scan every file. The projection exists exactly for this. See The SQL projection.
- It isn't atomic across many writes by default — git commits are atomic per-commit, but four
git commitcalls in sequence aren't one event. The transaction primitive fixes this where it matters (invoices with line items, journal entries with debits and credits). - It isn't multi-master out of the box. Two workers writing the same record race. See Optimistic concurrency.
Read the architecture next.