sandbank
Your agent writes to a real branch of production Postgres. You get every row it changed as a diff, and you approve it or throw it away. Merging back is the part nobody else does.
docker compose up -d
Runs against any Postgres — RDS, Supabase, Neon, your own box.
On 25 April 2026 a coding agent deleted PocketOS's production database and its backups in nine seconds. It hit a credential mismatch on a routine staging task, did not stop to ask, and found a token in an unrelated file that carried authority over the whole account.
Destructive-action guardrails, plan mode, tool-use safety and the founder's own project rules were all switched on that day. None of them fired.
Reported by The Register and The New Stack.
Sandboxes isolate the process, not the data. An agent in a microVM still connects to production over the network with real credentials. Sandbank puts the boundary around the rows instead.
It gets a connection string with search_path already set. It writes
ordinary SQL and never learns it is fenced in. The branch role can read and write
its branch and nothing else in the database — not the production tables, not
another branch, not the change log.
Twelve edits to one record read as one change. A record created and then deleted inside the branch reads as nothing at all. What you review is the net result, not a transcript.
Merging is three-way. If the branch changed notes while production
changed email on the same record, both survive. If both changed the same
field, that is a conflict and nothing is applied. Approval is bound to the exact plan
you saw: if the agent writes again afterwards, the approval expires and comes back to
you.
A branch is not a copy. Tables become views over production plus a delta holding only the rows the agent touched, so branch time does not depend on database size. Measured on a 551 MB table of 5 million rows, Postgres 17:
| Sandbank | Copying the data | |
|---|---|---|
| Create the branch | 35 ms | 4 110 ms |
| Storage it occupies | 24 kB | 658 MB |
| Read one row by key | 1 ms | 1 ms |
| Write 100 rows | 14 ms | 14 ms |
| Full table scan | 163 ms | 52 ms |
The last row is the honest cost: reading through the overlay adds a check against the delta, so a full scan runs about three times slower. Point reads and writes are unaffected, and a 300 GB database branches in the same 35 ms as a 551 MB one, because nothing is being moved.
| Branches data | Merges data back | Runs on your Postgres | |
|---|---|---|---|
| Neon | Yes | No — reset from parent only | No, hosted |
| Supabase | Schema only | Schema only | No, hosted |
| Doltgres | Yes | Yes | No, it replaces Postgres |
| Sandbank | Yes | Yes, with conflict detection | Yes, any Postgres 15+ |
Hosted branching is copy-on-write at the storage layer, where a branch is a set of blocks. Two branches that wrote to the same block cannot be reconciled, which is why the only way home is to discard your work. Sandbank tracks rows, so it can tell you exactly which field moved and who moved it.
The same shape of billing follows from the same architecture. Neon charges $1.50 per branch per month, which is a fee on exactly the thing agents produce by the thousand. An overlay branch costs 24 kB and no compute, so Sandbank does not meter branches at all.
Agent data security starts around $50,000 a year if you buy it from an enterprise vendor, and most of them will not show you a number without a sales call. Here is ours.
| Self-host | Solo | Team | Scale | |
|---|---|---|---|---|
| Price | Free | $0 | $29/mo | $99/mo |
| Databases | unlimited | 1 | 3 | 15 |
| Branches | unlimited | unlimited | unlimited | unlimited |
| People who can approve | unlimited | 1 | 5 | 25 |
| Diff history kept | your database | 7 days | 90 days | 2 years |
| Approval policies, pre-merge hooks | — | — | yes | yes |
| SSO and per-branch roles | — | — | — | yes |
Branches are never metered. Self-hosting is the whole product, not a crippled build — you pay when a second person needs to approve a merge, when you point it at a database you have tagged production, or when you need the history for an incident review.
One container next to your database. Nothing is sent anywhere, and your database never has to be reachable from outside.
git clone https://github.com/trackme341-sys/sandbank && cd sandbank cp .env.example .env docker compose up -d # point it at the database you want to branch SANDBANK_TRUNK_URL=postgres://user:pass@your-host:5432/app
Review at localhost:8790. Agents connect
over MCP: they can open a branch, read their own diff and propose a merge. Approving one
is a person's job — there is no merge tool for agents unless you turn it on.