> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackshift.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Branches

> A copy of your database you can change freely. It has its own address and password, and sleeps when nobody’s using it.

> [!NOTE]
>
> **Not yet released.** This guide describes implemented changes awaiting rollout. Availability requires the corresponding backend and dashboard release.

## Goal

Try a migration, test a fix or reproduce a bug on real data without touching your main database.

## Prerequisites

* A running PostgreSQL database
* Room for another branch on your plan (see Limits on your plan)

## Workflow

**Step 1**

Open the database and choose New branch, or run `stackshift db branch create shop-db --name fix-checkout --wait`. Pick where it starts: now, a moment in the past or a saved backup.

**Step 2**

Get its address with `stackshift db branch url shop-db/fix-checkout`. It has its own password, so your main database’s password never leaves main. Point your migration, test run or app at it.

**Step 3**

Change whatever you like. Nothing you do on the branch reaches your main database, and nothing that happens on main shows up on the branch.

**Step 4**

When you’re done, reset the branch to match its source again, make it the main database, or delete it. If you do nothing, it expires on its own.

## What a branch is

A copy of your database you can change freely. It has its own address and password, and sleeps when nobody’s using it. Reset it to match the original, make it the main one, or let it expire.

* Branches can be made from your main database or from another branch, up to three levels deep. A branch’s source is fixed.
* A branch sleeps after 5 minutes without use, and wakes the next time something connects. See Sleep when idle.
* Branches don’t count toward the number of databases your plan allows.
* A branch never takes a backup history or a standby of its own. It can always be made again from its source.
* In the dashboard a branch shows Available, Sleeping, Failed or Needs attention. The API’s `state` is `creating`, `ready`, `resetting`, `promoting`, `failed`, `deleting` or `needs_recovery`.

## Three ways to start a branch

* From now: ready in seconds, with everything your database holds at this moment. This works for databases up to 10 GB. For a bigger database, branch from a moment instead.
* From a moment: pick a time inside your history window. It takes a few minutes and works at any size. You need history for this: point-in-time restore on Starter (included on paid plans), or the retention window on Dedicated (7 to 35 days). A time outside the window is refused with the earliest time you can pick.
* From a saved backup: pick a backup you already have, or on Dedicated a restore point. Use this when the moment you want is older than your history window.

```bash Create a branch theme={null}
stackshift db branch create shop-db --name fix-checkout --ttl 24h --wait
stackshift db branch create shop-db --name before-the-bug --from "2026-10-24 14:00"
stackshift db branch create shop-db --name from-backup --backup BACKUP_ID
stackshift db branch list shop-db
stackshift db branch url shop-db/fix-checkout
```

```bash API theme={null}
curl -X POST https://api.stackshift.cloud/api/v1/databases/$DATABASE_ID/branches \
  -H "Authorization: Bearer $STACKSHIFT_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"name": "fix-checkout", "from": "now", "ttl": "24h"}'
```

```hcl Terraform theme={null}
resource "stackshift_database_branch" "fix_checkout" {
  database_id         = stackshift_database.shop.id
  name                = "fix-checkout"
  from                = "now"
  ttl                 = "24h"
  sleep_after_minutes = 5
  source_ref          = "pr:142"
}
```

```ts JavaScript theme={null}
import { StackShift } from "@stackshift-cloud/sdk";

const client = new StackShift({ apiKey: process.env.STACKSHIFT_API_KEY });
await client.databases.branches.withBranch(databaseId, async ({ url }) => {
  await runMigrations(url);
  await runTests(url);
});
```

```python Python theme={null}
with client.databases.branches.with_branch(database_id) as branch:
    run_migrations(branch["url"])
    run_tests(branch["url"])
```

## Limits on your plan

| Plan | Branches per database | Branches in your account | Awake at once | Longest life |
| - | - | - | - | - |
| Free | 1 | 1 | 1 | 24 hours |
| Ignite | 3 | 6 | 2 | 7 days |
| Pro | 10 | 25 | 5 | 30 days |
| Enterprise | 25 | 100 | 15 | No limit |

Longest life is the longest time you can ask a branch to stay before it is removed. Starter branches are included in your plan, with no hourly charge. When you reach a limit, you’re told which one and what to do: “You have 3 of 3 branches on your plan. Delete one, or move to a bigger plan.”

Dedicated databases allow 10 branches per database by default, with more on request, and no limit on how long a branch can live.

## Reset a branch

Reset throws away every change on the branch and copies its source again. The branch keeps its address and password, so anything pointing at it carries on. If a reset fails, the branch keeps the data it had.

* Dashboard: open the branch and choose Reset. CLI: `stackshift db branch reset shop-db/fix-checkout`.
* Reset is the quickest way to retry a migration. Reset the branch instead of making a new one each time.
* Over the API, `POST /api/v1/databases/{id}/branches/{branchId}/reset` needs an `Idempotency-Key` header, so a retry never resets twice.

## Make a branch the main database

Making a branch the main database puts the branch’s data into your main database. Main keeps its address and password, so your apps need no change.

* You type the name of your main database to confirm: `stackshift db branch promote shop-db/fix-checkout --confirm shop-db`. The dashboard shows what will be lost first, for example “Changes to shop-db since you branched will be lost: 1,204 rows written since 14:02.”
* A fresh backup of main is taken first. If that backup fails, nothing changes.
* Writes pause for a short moment while the data is swapped, about 5 to 15 seconds as a target.
* The old main data is kept for a day as a sleeping branch called `main-before-<date>`, so you can undo the change for 24 hours.
* Main starts a new backup history after the swap, then takes a full backup.
* If anything goes wrong during the swap, main goes back to how it was and the branch is untouched.
* It isn’t available while main has a standby. Turn the standby off first.
* Over the API, `POST /api/v1/databases/{id}/branches/{branchId}/promote` takes `{"confirm_name": "shop-db"}` and an `Idempotency-Key` header. Terraform can’t make a branch the main database.

## Expiry

* A branch made by a person lives 7 days unless you choose another time. A branch made by an agent or for a pull request lives 24 hours.
* Choose a longer life up to your plan’s longest life, with `--ttl` (`24h`, `7d`) or the Keep button. Extend it later with `stackshift db branch extend shop-db/fix-checkout --ttl 7d`, or with `PATCH /api/v1/databases/{id}/branches/{branchId}` and a new `ttl`.
* You’re warned 24 hours and 1 hour before expiry in the dashboard and by email, and in the pull request for a pull request branch.
* Expiry deletes the branch. An expired branch can’t be recovered, and this is stated when you create it.
* A branch with branches of its own can’t be deleted until those are gone, unless you add `--cascade --confirm <branch name>` (in the API, `?cascade=true&confirm=<branch name>` with an Idempotency-Key).

## Cost

* Starter: branches and sleep are included in your plan, within the limits above. No hourly line appears for them. Add-ons such as a standby or restore to any second aren’t bought again for a branch.
* Dedicated: a branch is billed per hour while it is awake, at the hourly rate of its size, plus a storage charge per GB-month for data that differs from main. A sleeping branch pays storage only. Making a branch the main database is free.
* As an example, a size priced at ₦16,000 a month costs about ₦21.92 an hour while awake. See [https://stackshift.cloud/pricing](https://stackshift.cloud/pricing) for the current prices.
* Before a Dedicated branch is created you see the hourly price and confirm it. Over the API you get `409 price_confirmation_required` until you do. Agents quote the price first.
* A branch is billed to the subscription of the database it came from. You can’t create one while that subscription is past due or suspended.

## Use branches from your tools

Every branch is also a database of its own: its own ID works with credentials, metrics, logs and the SQL browser. Branches don’t appear in your database list, only under the database they belong to.

* API: `GET /api/v1/databases/{id}/branches` lists the whole tree. `POST` creates a branch and answers `202` with an operation to follow until its `status` is `succeeded` or `failed`. `DELETE /api/v1/databases/{id}/branches/{branchId}` deletes one. For routes on a branch, `{id}` is the database it was made from.
* `from` is `now`, or an object with `time`, `restore_point_id` or `backup_id`. `ttl` is `24h`, `7d` or `never`, within your plan’s longest life. `sleep_after_minutes` is 5 to 1440.
* Add `-o json` to any CLI command for machine-readable output, and `--wait` to wait until the branch is ready. The CLI exits with 8 for a plan limit, 9 for no room right now and 10 for a time outside the window.
* Terraform creates and deletes branches. It never makes one the main database.
* The JavaScript and Python SDKs have a `branches` module under `databases`. `withBranch` (`with_branch` in Python) makes a branch that lasts 24 hours by default, gives your code its Shared connections address, and deletes the branch when your code finishes, which suits test suites. Both SDKs also have `databases.sleep` and `databases.wake`.

## Availability

Branches are rolling out. If your database page doesn’t show Branches yet, it isn’t switched on for your account.

## Expected result

> [!TIP]
>
> You have a separate database holding the data you chose. Changing it leaves your main database as it was, until you decide to make the branch the main one.

## Common failures

> [!WARNING]
>
> * `402 plan_limit`: you’re at your plan’s branch, awake or life limit. Delete branches you don’t need, or pick a shorter life.
> * `409 no_capacity`: there’s no room right now. Try again shortly. Nothing is charged.
> * `422 outside_window`: the time you chose is older than your history window. Pick the time the error gives, or branch from a saved backup.
> * `422 too_large`: a branch from now works for databases up to 10 GB. Branch from a moment instead.
> * `409 name_taken`, `has_branches` or `too_deep`: pick another name, delete or `--cascade` the branches under it, or branch from a shallower branch.
> * `400 idempotency_key` or `confirm_name`: reset and make-main requests need an `Idempotency-Key`, and make-main needs the main database’s exact name.
> * `403 replace_required`: only an owner or admin can reset the branch that holds your old main data.
> * A branch shows Failed: open it to see why and choose Try again. Your main database was not touched. A branch that shows Needs attention has to be reset or deleted before it can be used.

## Related guides

> [card] [Branches for previews and agents](https://docs.stackshift.cloud/databases/branches-for-previews-and-agents.md)
>
> Give every pull request and every agent task a database it can’t hurt production with, and try migrations there first.

> [card] [Sleep when idle](https://docs.stackshift.cloud/databases/sleep-when-idle.md)
>
> A database nobody is using goes to sleep and wakes on the next connection. Its address, password and data stay the same.

> [card] [Back up and restore a database](https://docs.stackshift.cloud/databases/back-up-and-restore-a-database.md)
>
> Use durable recovery storage correctly and understand why backups are independent from portable SQL transfers.

> [card] [Database connections and tunneling](https://docs.stackshift.cloud/databases/credentials-pooling-and-usage.md)
>
> Use private, direct public, or StackShift tunnel endpoints with TLS and explicit client IP policy.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.