← Blog3 min read

Always-Rollback Mode: True Dry-Run for Agent Writes

There is a class of agent write where you do not want a copy of the database to keep, you do not want an approval queue, and you do not want the write to persist. You just want to see what the statement would do, against real data, and then have it vanish. That is a dry-run, and most tools do not give you a real one.

A real dry-run is harder than it sounds. You cannot just refuse the write, because then the agent sees nothing. You cannot just run it, because then it persists. What you want is to run it, observe the effect, and roll it back, so the agent and you both learn what happened while the database ends up exactly as it started.

What always-rollback does

In always-rollback mode, PgBeam runs the agent's writes inside a transaction it never commits. The statements execute against real data. Constraints fire. Triggers run. The agent can read back the rows it just changed within the same transaction and see the actual result. Then, at the end, PgBeam rolls back. Nothing is committed. The database is unchanged.

From the agent's perspective, the write worked: it ran, it returned, the affected rows reflect the change when queried inside the transaction. From the database's perspective, nothing happened. The transaction opened, did its work, and was discarded.

Why this is genuinely useful

The value is that the agent's write is validated against the real schema and the real data, not a guess. A generated UPDATE that would violate a foreign key fails in dry-run exactly as it would in production, so you find out before committing. A DELETE shows you, within the transaction, how many rows it touched. A statement that depends on a trigger sees the trigger's effect. You get the truth of "what would this do," with none of the consequence.

Compare that to the alternatives. A read-only credential tells you nothing, because the write is refused outright. Reasoning about the SQL by hand is error-prone, because the answer depends on data you would have to query anyway. Running it for real and undoing it manually is exactly what always-rollback automates, correctly, every time, without trusting anyone to remember the ROLLBACK.

Dry-run vs branches

Instant branches and always-rollback solve adjacent problems, and the difference is duration and scope.

  • A branch is a stable, writable environment that persists for a session. The agent can make many writes, build on them, and you can inspect the accumulated state and even promote it. Reach for a branch when the agent needs to work in a writable copy.
  • Always-rollback is per-transaction and ephemeral. The write runs and is immediately discarded. Reach for it when you want to check a single statement against real data and keep nothing.

A branch is a workspace. Dry-run is a probe. Both keep production untouched; they differ in how much the agent gets to keep while it works.

The human angle

The same mode is a safety net for people running destructive statements. Before an engineer commits a migration or a bulk fix against production, they can run it in always-rollback mode, see the row counts and any constraint failures, confirm it does what they expect, and then run it for real with confidence. It is the difference between "I think this UPDATE is right" and "I watched this UPDATE touch exactly the 1,204 rows I expected, and nothing committed."

Always-rollback stays inside the policy engine like everything else: the statements are audited, budgets apply, and the rollback is recorded. You get a verifiable record that the write ran and was discarded, which is its own kind of proof.

Try PgBeam or see the full feature set.

Give your agent Postgres it can't wreck

Connect a database, issue a credential, and watch the audit log fill up. No credit card. 14-day trial.