Inspiration
AWS retired QLDB last year. QLDB was their ledger database, and the entire reason to reach for it was that you could cryptographically prove the log had never been altered. What surprised me is that AWS's own migration guide admits the recommended replacement does not carry that property forward, so anyone who needed a verifiable ledger on AWS basically lost the clean way to get one. I wanted to see whether I could rebuild that missing guarantee on Aurora DSQL, their newest distributed SQL database, using nothing proprietary and only cryptography that anyone can check for themselves.
What it does
Indelible is an audit log that can prove it has not been edited. Every event is hashed and chained to the one before it, and verifying does not trust a status column or take the app's word for anything. It recomputes every hash from the raw stored bytes up to the latest record, so a direct UPDATE or DELETE on the table gets caught at the exact event that was touched, even when the person doing it has full database credentials. It also handles the smarter version of that attack, where someone edits a record and then recomputes every hash after it so the chain looks consistent again. On a schedule, Indelible signs a checkpoint of the chain and publishes it to a separate public repository that my own servers cannot write to, so a rewrite that fools the in-chain check still fails against that signed anchor. The same stream runs active-active across two AWS regions, and I can switch which region I read from and verify the identical head hash with no lag. It also exposes an MCP server, so an AI agent gets a tamper-proof record of everything it does.
How I built it
The ledger lives in Aurora DSQL and I reach it through the standard pg driver, with the AWS DSQL signer handling authentication. The core of the system is a small hashing and canonicalization library that I unit tested heavily, because everything depends on each record hashing to exactly the same value every time it is checked. Checkpoints are RFC 6962 style Merkle roots signed with an Ed25519 key, and the published anchors are tiny, only a couple hundred bytes each. The console is built in Next.js 16 and TypeScript and runs on Vercel. The anchors are pushed to a public GitHub repository by a scheduled Action that is only allowed to pull, which is deliberate, since I never want my own infrastructure to hold a key that could rewrite the published proofs.
Challenges I ran into
The hardest problem by far was getting two regions to write into one clean chain. DSQL uses optimistic concurrency, so two appends that land at the same instant can collide, and the obvious fix of simply retrying would quietly fork the history into two parallel branches, which would defeat the whole purpose. I ended up making the retry re-read the current head of the chain and re-link against it, so two writers racing each other always fold back into a single ordered chain instead of splitting into two.
Accomplishments that I'm proud of
The thing I am most proud of is that Indelible catches the one attack a plain hash chain cannot, which is a full rewrite by someone who already controls the database. It does that with only portable cryptography, no proprietary formats, and nothing that locks you to a single vendor, which means an outside auditor can verify the entire log with just a public key and never has to trust me or my servers. For a solo build, getting that working end to end and running live in two regions felt like the real win.
What I learned
Two things took most of my time and both surprised me. The first was how strong consistency actually behaves in Aurora DSQL once you push concurrent writes at it from more than one place. The second was how much thought goes into putting your proof outside the system you are trying to protect. The cryptography itself turned out to be the easy part. The genuinely hard part was deciding what I was willing to trust, and then designing so the proof does not depend on any of it.
What's next for Indelible
Next I want to publish the anchors to more than one destination so the proof never rests on a single host, build a public verifier that anyone can point at a stream and check for themselves, and expand the MCP tooling so audit trails for AI agents become a first class use case rather than a demo.
Built With
- amazon-aurora-dsql
- amazon-web-services
- ed25519
- merkle-tree
- model-context-protocol
- next.js
- node.js
- postgresql
- tailwind-css
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.