Skip to content
HN On Hacker News ↗

Undo for Postgres, without losing the rest of your day

▲ 24 points • 9 comments • by hnisjafx40 • 1w ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is AI.

100 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 4
SEGMENTS · AI 4 of 4
WORD COUNT 577
PEAK AI % 100% · §1
Analyzed
Oct 29
backend: pangram/v3.3
Segments scanned
4 windows
avg 144 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 577 words · 4 segments analyzed

Human AI-generated
§1 AI · 100%

Postgres gives you no way to take back a single statement. When someone runs an UPDATE without its WHERE clause, recovery is a procedure rather than a command. You restore a copy of the database to the moment before the mistake, pull out the rows that were damaged, and reconcile them by hand against a live table that has kept moving since.This kind of recovery works, and teams do it. It also takes hours, needs your most senior person, and every step is a chance to make things worse while the table is still serving traffic. One second of bad SQL turns into an afternoon of careful work by the people you can least afford to tie up.Oracle users have Flashback for exactly this case, and it is really two features: one to read the past, one to put it back. Postgres has neither. Point in time recovery is what makes that procedure possible, but it recovers an entire cluster rather than a statement. You restore it alongside production and compare, because rewinding production itself would discard everything that happened after the mistake. I wanted something smaller and more precise, so I built pgVolvra.What pgVolvra DoespgVolvra records every row change on the tables you choose. For each change, it keeps the row as it was, and the row as it became, along with who made the change, when, and in which transaction. When something goes wrong, it uses that record to put the affected rows back, and it touches nothing else.The whole engine is plain SQL and PL/pgSQL. There is no compiled extension, no shared_preload_libraries, no superuser, and no access to the server's filesystem. That was a design constraint from the first day, and it is the reason the tool runs on managed Postgres at all.Setting It UpInstallation is running one file against your database. It works from psql, from any SQL client, or from a provider's web console.psql "$DATABASE_URL" -f sql/volvra.sqlThen you pick the tables you want covered. pgVolvra records nothing until you do this, and it cannot recover anything that happened before, so this step is the one that matters.SELECT volvra.enable('public.orders');That is the entire setup. From this point every INSERT, UPDATE and DELETE on orders is recorded.A Working ExampleHere is the full sequence on a table you can create yourself. I will make the same mistake on purpose and then walk back out of it.1. Create a table and enable pgVolvra. A primary key is required, because that is how pgVolvra finds a row again later.CREATE TABLE orders ( id bigint PRIMARY KEY, customer text NOT NULL, status text NOT NULL, total numeric(10,2) ); INSERT INTO orders VALUES (1, 'ayesha', 'shipped', 240.00), (2, 'omar', 'pending', 99.50), (3, 'lena', 'shipped', 18.75); SELECT volvra.enable('public.orders');2. Make the mistake. The WHERE clause is missing, so every row is hit instead of one.UPDATE orders SET status = 'cancelled'; UPDATE 33. Look at what happened to one row. volvra.history takes the table and the primary key as jsonb, and shows every version of that row.SELECT ts, actor, op, old_row -> 'status' AS was, new_row -> 'status' AS now FROM volvra.history('public.orders', '{"id": 1}'); ts | actor | op | was | now ---------------------+-------+----+-----------+------------- 2026-09-16 11:04:19 | api | U | "shipped" | "cancelled"4.

§2 AI · 100%

Preview the undo.

§3 AI · 100%

This call writes nothing. It builds the exact plan and hands it back so you can read it before anything changes.SELECT * FROM volvra.preview_undo( target => 'public.orders', from_ts => now() - interval '5 min');5.

§4 AI · 100%

Query pgVolvra.