# pgrun alternatives: a Postgres branch for every agent, on your own machine

> pgrun gives every agent, CI run, or pull request a disposable branch of your production Postgres. Here is what it actually does and where its limits are, how to get the same workflow locally for free with the Layerbase CLI, and the hosted alternatives worth comparing: Neon, Xata, and DBLab Engine.

Published: 2026-09-18
Canonical: https://layerbase.com/blog/pgrun-alternatives

Short version: [pgrun](https://pgrun.dev) gives every agent, CI run, or pull request its own disposable Postgres branch, cut from a masked copy of your production database. It is a hosted service and a good one. But if the agents you care about are the ones running on your laptop (Claude Code, Codex, Cursor), you do not need a service for this. The Layerbase CLI pulls a copy of production to your machine and forks it copy-on-write, one branch per agent, for free and with no account.

This post covers what pgrun actually does, the local version of the same workflow step by step, and the hosted alternatives for when local is not enough.

[What is the Layerbase CLI?](https://layerbase.com/docs/cli)

## What pgrun does

You give pgrun a read-only connection string for your production Postgres, and it [forces the session read-only](https://pgrun.dev/docs/branches) before running any SQL. You decide per column what happens to sensitive data: copy it, fake it, hash it (equal values stay equal, so joins still work), or remove it. Masking runs inside the query that reads production, so a protected value never leaves your database.

That masked copy becomes the base. Branches are copy-on-write off it, ready in seconds, each with a normal `DATABASE_URL`, and each can expire after 1 hour, 6 hours, 24 hours, or 7 days. There is an MIT-licensed [CLI and MCP server](https://github.com/pgrundev/pgrun-cli) so an agent can create and delete its own branches. Branches are [free during beta](https://pgrun.dev/pricing) with $10 of credit.

The limits, all from pgrun's own docs as of 2026-09-18:

- **The copy is a snapshot.** It does not follow production, and refreshing it is not self-serve yet: you email support and delete the project's branches first.
- **Postgres 16, 17, or 18 only**, and the source needs a public address. A database that only exists inside a VPC is refused.
- **Beta caps:** databases up to 10 GB, 10 live branches per project, everything hosted in the US.

If masking at the source is a hard requirement, pgrun does something the local workflow below does not, and I will be clear about that when we get there.

## The same workflow, locally

The idea behind pgrun is simple: an agent gets real data and full write access, and the blast radius of a bad run is one throwaway branch. You can have that on your own machine in about five minutes.

### Install

```bash
npm i -g layerbase
```

That gives you `lbase`. It runs databases as native processes, with no Docker, no account, and no login.

### Pull a copy of production

Create a local Postgres and pull production into it. Keep the URL in an environment variable so it stays out of your shell history:

```bash
lbase create appdb --engine postgresql --start
lbase pull appdb --from-env PROD_DB_URL
```

For a big database, skip the rows of the tables that dominate the bytes and parallelize the rest. `--exclude-table-data` keeps the table's schema so your migrations and queries still work:

```bash
lbase pull appdb --from-env PROD_DB_URL --jobs 4 \
  --exclude-table-data 'events_*' --exclude-table-data audit_log
```

Unlike pgrun's Safe Copy, refreshing is self-serve: run the pull again whenever you want this morning's data instead of last month's. It backs up the local copy before replacing it.

### Scrub what you should not be holding

This is the honest difference from pgrun. `lbase pull` copies the rows as they are, so personal data lands on your disk before you mask it. For a solo project or a database without customer PII, that is usually fine. If it is not fine for yours, use pgrun or Xata, which mask before the data leaves production.

If it is fine, scrub the local copy once and every branch inherits the result. Put your rules in a file:

```sql
-- scrub.sql
UPDATE users
SET email = 'user' || id || '@example.test',
    name = 'User ' || id,
    phone = NULL;

UPDATE payment_methods
SET last4 = '0000',
    billing_address = NULL;

TRUNCATE sessions, password_reset_tokens;
```

```bash
lbase run appdb ./scrub.sql
lbase query appdb "SELECT id, email FROM users LIMIT 3"
```

```text
 id |         email
----+-----------------------
  1 | user1@example.test
  2 | user2@example.test
  3 | user3@example.test
```

### Give every agent its own branch

Now fork it. On APFS (every modern Mac), Btrfs, XFS with reflink, or ZFS, a branch is a copy-on-write clone: instant and close to zero extra disk, however big the database is. On other filesystems it falls back to a full copy.

```bash
lbase branch appdb agent-refactor
lbase branch appdb agent-migration
lbase url agent-refactor
```

```text
postgresql://postgres@127.0.0.1:5433/appdb
```

Each branch runs on its own port with its own data. Hand one URL to each agent session as `DATABASE_URL` and let them run migrations, seed junk, and drop tables. Nothing they do reaches `appdb` or each other.

When an agent makes a mess, reset its branch back to the parent instead of pulling again:

```bash
lbase branch reset agent-migration
```

When it is done, delete it:

```bash
lbase branch delete agent-refactor
lbase branch list
```

### Or let git choose the branch

If you would rather not juggle URLs, wire the database to your repository. Checking out a git branch swaps in a matching database branch on a stable port, so `DATABASE_URL` never changes:

```bash
lbase branch init appdb
git checkout -b feature/billing-v2   # its own database branch swaps in
git checkout main                    # the base swaps back
lbase branch prune                   # delete branches whose git branch is gone
```

The stable port serves one branch at a time, so this suits one agent working through git branches in sequence. For several agents running in parallel, give each its own branch and URL as in the previous step.

### Not just Postgres

pgrun is Postgres only. `lbase branch` works on qualified engines, so the agent that needs a scratch copy of your Postgres can get one of your Redis, Qdrant, or MongoDB the same way.

## When local is not enough

A branch on your laptop does nothing for a CI runner or an agent running in the cloud. For those you need a hosted branch, and these are the options worth comparing.

**[Neon](https://layerbase.link/neon)** is the most mature branching Postgres: copy-on-write, instant, and fully scriptable. It has [anonymized branches](https://neon.com/docs/workflows/data-anonymization) built on PostgreSQL Anonymizer, but they are in beta with real restrictions (foreign key columns cannot be masked directly, and an anonymized branch cannot be reset to its parent). Your production database has to live on Neon, and compute is billed by the CU-hour. More in [Neon alternatives](/blog/neon-alternative).

**[Xata](https://xata.io)** is the closest match to pgrun: copy-on-write branches with PII anonymization in every plan, and it can [replicate an external Postgres in](https://xata.io/blog/xata-postgres-with-data-branching-and-pii-anonymization) with column transforms along the way. It is metered, [from $0.012/hour](https://xata.io/pricing) plus $0.28 per GB-month, with a 14-day trial rather than a free tier. The platform is also open source.

**[DBLab Engine](https://github.com/postgres-ai/database-lab-engine)** is the self-hosted choice: Apache 2.0, thin clones of a production copy on ZFS or LVM in a few seconds, against sources on RDS, Cloud SQL, Supabase, and more. You run the box and keep the copy fresh yourself.

**Layerbase Cloud** branches databases hosted on Layerbase with the same CLI, so a CI job can fork a seeded parent per pull request with `lbase cloud branch seed-db pr-123`. It does not branch a database hosted elsewhere and does not mask columns. Branching works on 17 Cloud engines, and pricing is flat: Free is $0, Solo is $5/month, Pro is $15/month, with no compute meter.

## Side by side

|                                 | pgrun            | Layerbase CLI (local) | Neon               | Xata                       | DBLab Engine            |
| ------------------------------- | ---------------- | --------------------- | ------------------ | -------------------------- | ----------------------- |
| Where branches run              | Their cloud (US) | Your machine          | Their cloud        | Their cloud or self-hosted | Your server             |
| Copy of prod hosted elsewhere   | Yes              | Yes (`lbase pull`)    | No                 | Yes (replicated in)        | Yes                     |
| Masking before data leaves prod | Yes              | No (scrub after pull) | Beta, on Neon data | Yes                        | Bring your own          |
| Refresh the copy                | Via support      | Rerun `lbase pull`    | Reset from parent  | Continuous replication     | You manage it           |
| Engines                         | Postgres         | over 20               | Postgres           | Postgres                   | Postgres                |
| Cost                            | Free in beta     | Free                  | CU-hours + storage | Instance hours + storage   | Self-hosted or licensed |

## Choosing

If your agents run on your machine and the data you would pull is not sensitive, or you are comfortable scrubbing it locally, start with the CLI. It is free, it refreshes whenever you want, and it branches everything, not only Postgres.

If production data must be masked before it leaves the database, that is pgrun or Xata. If you need hosted branches for CI or cloud agents, weigh pgrun against Neon, Xata, and Layerbase Cloud on price and on whether production has to move.

The commands worth keeping:

```bash
npm i -g layerbase
lbase create appdb --engine postgresql --start
lbase pull appdb --from-env PROD_DB_URL     # rerun anytime to refresh
lbase run appdb ./scrub.sql
lbase branch appdb agent-1                  # one per agent
lbase url agent-1
lbase branch reset agent-1                  # undo everything the agent did
lbase branch delete agent-1
lbase stop appdb && lbase start appdb
```

Prefer a GUI? [Layerbase Desktop](https://layerbase.com/desktop/download) runs the same engines with a point-and-click interface.
