Branches
A branch is a fork of a database that carries a stable external
identifier (a ref — typically a PR number or a git branch name).
The (parent, ref) pair is unique, so a CI pipeline can PUT the
same ref repeatedly and either create the branch the first time or
reset it from the parent’s current state every other time.
For each pull request:
- First commit:
PUT /branches/pr-42→ branch is forked from parent. - Every later commit:
PUT /branches/pr-42→ branch is reset back to the parent’s current state. - PR closes:
DELETE /branches/pr-42→ branch is gone.
No “is this the first run?” branching in your workflow, no collisions if two jobs race, no manual cleanup of stale forks.
Console
Section titled “Console”Each database has a Branches tab. Click New branch, give it a ref, and PerSQL forks the parent for you. Each row shows the ref, status, fork timestamp, and an optional auto-delete date. Reset and delete actions live next to each branch.
Create or reset a branch
Section titled “Create or reset a branch”curl -X PUT \ --cookie cookies.txt \ -H 'Content-Type: application/json' \ -d '{"ttlDays": 7}' \ https://api.persql.com/api/namespaces/acme/databases/main/branches/pr-42Body fields:
name(optional) — display name. Defaults to<parent name> (<ref>).region(optional) — DO location hint, only honored on first create. Defaults toauto.ttlDays(optional, 1–30) — branch is auto-deleted after this many days by the daily 04:00 UTC cron. Reset on every PUT.
Returns the branch’s full database row, including branchRef,
forkedFrom, and expiresAt.
List branches
Section titled “List branches”curl --cookie cookies.txt \ https://api.persql.com/api/namespaces/acme/databases/main/branchesDelete a branch
Section titled “Delete a branch”curl -X DELETE --cookie cookies.txt \ https://api.persql.com/api/namespaces/acme/databases/main/branches/pr-42The DO is destroyed and the registry row removed.
Ref format
Section titled “Ref format”Refs must be 1–64 characters, start with an alphanumeric, and
contain only A-Z, a-z, 0-9, ., _, -, and /. Examples:
pr-42feat/login-redesignrelease-2026.04
The branch’s slug is derived from the parent’s slug + a sanitized
ref (e.g. main + pr-42 → slug main-pr-42). Slugs collide
gracefully with a short suffix.
What we copy
Section titled “What we copy”Same as a regular fork:
- Tables, indexes, triggers, views.
- All rows of all tables.
We don’t copy:
- Saved queries, migrations history, schedules — those live on the parent and stay there.
- Custom hostnames.
API tokens are namespace-scoped and apply to the branch automatically.
What it costs
Section titled “What it costs”There is no per-branch fee and no plan-tier gate. Branches bill against the same four meters as the parent:
- Requests / rows read / rows written — only when the branch is queried. An idle branch costs nothing on these meters.
- Storage — metered from creation, because a branch is a full copy
of the parent’s data (tables, indexes, rows). A 100 MB parent
branched for a 7-day PR-preview costs ~$0.01 in storage; the
ttlDaysauto-delete keeps that bill bounded.
The cheapest branches are branches of small or empty parents. For
schema-only experiments against a large parent, fork and DROP the
heavy tables before populating fixtures.
See also
Section titled “See also”- Forking — the underlying primitive
- PR preview databases — full CI workflow