kisenon

Branches

Copy-on-write Postgres branches in Kisenon — fork-at-LSN, lifecycle, and cascade.

A branch is a pointer to a Log Sequence Number (LSN) in the project's storage. Creating one is an O(1) row insert; it does not copy data. Branches diverge as you write to them, and only the delta is stored.

The model

Every project has a main branch from creation. From main (or any existing branch) you can fork a new branch:

  • At HEAD — the new branch starts from the parent's current LSN.
  • At a specific LSN — the new branch starts from a historical LSN within the parent's WAL retention window. This is the "time-travel" case: you can branch off a point in the past as long as the WAL is still retained.

Reads on a branch fall through to the parent's pages until the branch diverges. Writes record only the delta. The result:

  • A 100 GB project with ten small branches is billed as ~100 GB total.
  • Spawning a branch is sub-second.
  • Branches are disposable. Run a destructive migration, throw the branch away, the parent is untouched.

Naming

Branch names are user-visible labels, scoped to the parent project. Constraints match project names:

  • 1–63 characters.
  • ^[a-zA-Z][a-zA-Z0-9_-]*$.
  • Unique within the project.

The internal branch id (br_<24 hex>) is the stable reference. Use the id, not the name, when scripting against the API; names can be renamed.

State machine

A branch transitions through:

creating → ready → deleting → deleted
  • creating — control plane is registering the branch with the storage layer. Typically sub-second; longer if storage is under load.
  • ready — branch can be attached to endpoints and accept writes.
  • deleting — cascade in progress: every endpoint on this branch is being stopped and removed.
  • deleted — terminal. The row is retained for auditability for a short period, then garbage-collected.

The CLI shows the current state for every branch:

keon branches list --project <project-id>

Create

keon branches create --project <project-id> --name my-feature --parent main

To branch at a historical LSN, pass --parent-lsn <lsn>:

keon branches create \
  --project <project-id> \
  --name pre-migration \
  --parent main \
  --parent-lsn 0/1A2B3C4D

The LSN must be within the project's WAL retention window. If it has been compacted past, the branch creation fails.

Delete

Deleting a branch cascades to every endpoint attached to it:

  1. All endpoints on the branch are stopped and removed.
  2. The branch itself is torn down.
  3. Storage is reclaimed asynchronously by pageserver compaction.
keon branches delete <branch-id>

You cannot delete the main branch of a project — delete the project instead. You can delete any other branch even if it has children; in that case the children are reparented to the deleted branch's parent at the deletion LSN.

Reset and restore

From the branch detail page in the console, the actions menu exposes two re-fork operations on any non-root branch:

  • Reset to parent — re-forks the branch at its parent's current HEAD. Every write made on the branch since the original fork is discarded. Endpoints on the branch briefly suspend during the swap.
  • Restore to point-in-time — re-forks the branch at a chosen LSN or a UTC timestamp (RFC 3339). Writes after that point are discarded.

Both run asynchronously: the console issues the request and the branch returns to ready once the re-fork lands. The root (main) branch cannot be reset — there is no parent to reset to.

Snapshots

A snapshot pins a point-in-time LSN so it stays restoreable past the WAL retention horizon. Without a snapshot, a restore target is only reachable while its WAL is still retained; a snapshot keeps that point addressable indefinitely.

The Snapshots tab on the branch detail page lists the branch's snapshots and lets you capture a new one. Each row offers:

  • Restore — re-forks the branch at the snapshot's pinned LSN.
  • Delete — drops the snapshot (the underlying LSN is no longer pinned and may be reclaimed by compaction).
  • Projects — what owns the branch.
  • Endpoints — what attaches to a branch to accept client traffic.
  • Concepts — the storage / compute split that makes branches free.