Forking
A fork is a brand-new database, in the same namespace, populated with a snapshot of the source’s schema and data. Once forked, the two databases are independent — writes to one don’t affect the other.
In the console: Database → Fork in the page header. Pick a name and slug for the fork; PerSQL provisions the new DO and applies the dump.
Lineage
Section titled “Lineage”Forked databases remember where they came from. The detail page
shows a “Forked from <source-slug> · 3d ago” breadcrumb that links
back to the parent. The lineage stays even if the parent is later
deleted (the link goes dead, but the label remains).
The same fields are exposed on the API:
db.forkedFrom; // { id, slug, name } | nulldb.forkedAt; // ISO string | nullOnly GET /api/namespaces/:ns/databases/:slug resolves the parent’s
slug+name; the namespace list endpoint returns just the raw
forkedAt to keep the response cheap.
What we copy
Section titled “What we copy”- Tables, indexes, triggers, views (everything in
sqlite_master). - All rows of all tables.
What we don’t copy
Section titled “What we don’t copy”- Saved queries (per-database, scoped to source).
- Migrations history (per-database).
- Schedules (per-database).
- Custom hostnames.
- API tokens (those are per-namespace and apply to the fork too).
How it works
Section titled “How it works”- PerSQL streams a SQL dump from the source database via the same
path as
Export SQL. - A new database row is inserted into the namespace registry with
status
provisioning. - A fresh DO is initialized at the new database’s id and the dump
is applied via
importSql(one transaction). - On success, the new database is flipped to
healthy. - On failure, the new database row + DO are cleaned up and the error is surfaced to the user.
Ephemeral forks (TTL)
Section titled “Ephemeral forks (TTL)”Forks can carry a self-destruct timer. Pass ttlDays (1–30) on the
REST call, or --ttl 7d on the CLI, and the daily 04:00 UTC cron
deletes the fork — DO and registry row — once the timestamp passes.
Pre-existing forks without a TTL are unaffected.
persql db fork acme/orders pr-142 --ttl 7dThe detail page shows an “Auto-deletes in 6d” line; the database list shows an “expires in 6d” badge that turns red under 6 hours.
For PR-style ephemeral databases, the Branches API is usually a better fit: it’s idempotent (PUT-by-ref creates or resets), so CI doesn’t need to track whether the database already exists.
POST /api/namespaces/:ns/databases/:db/fork{ "name": "Orders staging", "slug": "orders-staging", "region": "auto", "ttlDays": 7 }ttlDays is optional. Manage permission required on the source. The
response is the new database row, including its expiresAt field.
Caveats
Section titled “Caveats”- Fork is bounded by the same 50 MB import cap as
Import SQL. - Forking a hot database briefly pauses writes on the source while we read; in practice this takes hundreds of milliseconds.
- Cross-namespace fork is not supported in v1 — fork within the namespace, then transfer if needed.