Skip to content

Database Branching

Database branching allows you to create isolated copies of your database for development, testing, or preview environments. Each branch is a separate PostgreSQL database that can be used independently.

Use database branches to:

  • Test migrations before applying to production
  • Create isolated environments for PR previews
  • Safely experiment with schema changes
  • Run integration tests with real data structures

The easiest way to work with branches is using the Fluxbase CLI. The server handles all the database operations - you just run commands.

Terminal window
# Create a branch for your feature
fluxbase branch create my-feature
# Work with the branch (it's automatically used by the CLI)
fluxbase branch get my-feature
# When done, delete the branch
fluxbase branch delete my-feature
Terminal window
# Create a branch (copies schema from main by default)
fluxbase branch create my-feature
# Create a branch with full data copy
fluxbase branch create my-feature --clone-data full_clone
# List all branches
fluxbase branch list
# Show branch details
fluxbase branch get my-feature
# Reset branch to parent state (useful for testing migrations)
fluxbase branch reset my-feature
# Delete a branch
fluxbase branch delete my-feature
# Set default branch for all CLI commands
fluxbase branch use my-feature
# Check which branch is currently active
fluxbase branch current
# Switch back to main branch
fluxbase branch use main

Use fluxbase branch use to set a default branch for all CLI commands. This saves the branch to your profile and automatically includes the X-Fluxbase-Branch header in every request.

Terminal window
# Set CLI to use a specific branch
fluxbase branch use my-feature
# Output: Now using branch: my-feature
# All CLI commands will now use this branch.
# All subsequent commands automatically use this branch
fluxbase data list users # Uses my-feature branch
fluxbase function deploy # Uses my-feature branch
# Check current branch
fluxbase branch current
# Output: Current branch: my-feature
# Switch back to main
fluxbase branch use main

This is useful when you’re working on a feature branch for an extended period and don’t want to specify the branch with every command.

Create a branch from another branch:

Terminal window
# Create feature-b from feature-a (instead of main)
fluxbase branch create feature-b --from feature-a

This creates a chain: mainfeature-afeature-b

This section is for server operators only. Users of the CLI or API don’t need to configure anything - the server handles branching automatically.

The PostgreSQL user must have CREATE DATABASE privilege. Grant it if needed:

-- Connect to postgres database as superuser
GRANT CREATE ON DATABASE postgres TO your_fluxbase_user;

Enable branching in your fluxbase.yaml:

branching:
enabled: true

That’s it! The server will use its existing database credentials to create and manage branches.

branching:
enabled: true
max_total_branches: 50 # Maximum total branches across all users
max_branches_per_user: 5 # Maximum branches per user (default: 5)
default_data_clone_mode: schema_only
auto_delete_after: 24h
database_prefix: branch_
OptionDefaultDescription
enabledfalseEnable database branching
max_total_branches50Maximum total branches across all users
default_data_clone_modeschema_onlyDefault cloning mode (schema_only, full_clone, seed_data)
auto_delete_after0Auto-delete preview branches after this duration (0 = disabled)
database_prefixbranch_Prefix for branch database names

Note: When auto_delete_after is set (e.g., 24h, 7d), a background cleanup scheduler runs automatically to delete expired branches.

ModeDescription
schema_onlyCopy schema only, no data (fast)
full_cloneCopy schema and all data (slower, useful for testing with real data)
seed_dataCopy schema with seed data (coming soon)

When you create a branch, the server:

  1. Uses its database credentials to connect to the postgres database
  2. Executes CREATE DATABASE branch_my_feature (or similar)
  3. Copies the schema (and optionally data) from the parent branch
  4. Tracks the branch metadata in the branching.branches table

The server never needs separate admin credentials - it uses the same PostgreSQL user it already has.

The following diagram shows how database branching works, including what happens to the public schema:

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#f8f9fa', 'primaryTextColor': '#333', 'primaryBorderColor': '#dee2e6', 'lineColor': '#6c757d', 'secondaryColor': '#e9ecef', 'tertiaryColor': '#f8f9fa' }}}%%
flowchart TB
subgraph Request["Branch Creation Request"]
API["POST /admin/branches<br/>{name: 'my-feature',<br/>dataCloneMode: 'schema_only'}"]
end
subgraph MainDB["Main Database (fluxbase)"]
direction TB
BranchingSchema["<b>branching schema</b><br/>━━━━━━━━━━━━━━━━<br/>branches<br/>activity_log<br/>branch_access"]
PublicSchema["<b>public schema</b><br/>━━━━━━━━━━━━━━━━<br/>users (100 rows)<br/>orders (500 rows)<br/>products (50 rows)"]
end
subgraph Process["Branch Creation Process"]
direction TB
Step1["1️⃣ Validate request<br/>Check limits & permissions"]
Step2["2️⃣ Create metadata<br/>status = 'creating'"]
Step3["3️⃣ CREATE DATABASE<br/>branch_my_feature<br/>TEMPLATE fluxbase"]
Step4["4️⃣ Update status<br/>status = 'ready'"]
Step1 --> Step2 --> Step3 --> Step4
end
subgraph BranchDB["Branch Database (branch_my_feature)"]
direction TB
PublicSchemaCopy["<b>public schema</b> (CLONED)<br/>━━━━━━━━━━━━━━━━<br/>users (0 rows) ⬅ schema only<br/>orders (0 rows) ⬅ schema only<br/>products (0 rows) ⬅ schema only"]
Note["❌ No branching schema<br/>(metadata stays in main DB)"]
end
API --> Step1
BranchingSchema -.-> |"stores metadata"| Step2
PublicSchema --> |"schema copied via<br/>PostgreSQL TEMPLATE"| PublicSchemaCopy
Step4 --> BranchDB
style MainDB fill:#e8f4e8,stroke:#28a745
style BranchDB fill:#e8e8f4,stroke:#6f42c1
style PublicSchema fill:#d4edda,stroke:#28a745
style PublicSchemaCopy fill:#e2d9f3,stroke:#6f42c1
style Note fill:#fff3cd,stroke:#ffc107

Key points:

  • Database-level isolation: Each branch is a separate PostgreSQL database, not just a schema within the same database
  • Branching metadata stays in main: The branching schema (which tracks all branches) only exists in the main database
  • Public schema is cloned: Your application tables in the public schema are copied to the new database
  • Data depends on clone mode: With schema_only, tables are created but empty. With full_clone, all data is copied too
import { createClient } from "@nimbleflux/fluxbase-sdk";
const client = createClient("http://localhost:8080", "your-key");
// Create a branch
const { data: branch } = await client.branching.create("my-feature", {
dataCloneMode: "schema_only",
expiresIn: "7d",
});
// Wait for it to be ready
await client.branching.waitForReady("my-feature");
// Delete when done
await client.branching.delete("my-feature");

See the Branching API for complete documentation.

For advanced users and custom integrations:

Terminal window
# Create a branch
curl -X POST http://localhost:8080/api/v1/admin/branches \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "my-feature"}'
# Access branch data
curl http://localhost:8080/api/v1/tables/users \
-H "Authorization: Bearer $TOKEN" \
-H "X-Fluxbase-Branch: my-feature"
TypeDescriptionAuto-Delete
mainPrimary databaseNever
previewTemporary environmentsAfter auto_delete_after
persistentLong-lived branchesNever

Include the X-Fluxbase-Branch header in your requests:

Terminal window
curl http://localhost:8080/api/v1/tables/users \
-H "X-Fluxbase-Branch: my-feature"

Append ?branch= to the URL:

Terminal window
curl "http://localhost:8080/api/v1/tables/users?branch=my-feature"

Get the branch connection URL for direct PostgreSQL access:

Terminal window
fluxbase branch get my-feature --output json | jq -r .connection_url
┌─────────────────────────────────────────────────────────────┐
│ MAIN BRANCH │
│ (Always exists) │
└───────────────────────────┬─────────────────────────────────┘
┌───────────────────────────────────────────────────────────────┐
│ Creating → Ready → Migrating → Ready → Deleting │
│ (new) (use) (update) (use) (cleanup) │
└───────────────────────────────────────────────────────────────┘
StateDescription
creatingDatabase is being created
readyBranch is available for use
migratingMigrations are running
errorAn error occurred
deletingBranch is being deleted
deletedBranch has been deleted

Branch access is controlled by:

  1. Creator - Automatically has admin access
  2. Explicit Grants - Can grant read/write/admin access to others
  3. Service Keys - Have full access to all branches
  4. Dashboard Admins - Have full access to all branches
LevelPermissions
readView branch, query data
writeRead + modify data
adminWrite + delete/reset branch