Database Branching

Fork databases for testing, run migrations on branches, merge schema changes back.

Overview

Database branching lets you fork a database at a point in time, make changes on the branch, test them, and merge schema changes back. Like git for your database.

Create a Branch

rf db branch main --name feature-profiles
✓ Branch created: feature-profiles
  Source: main (production)
  Snapshot: 2026-03-16T14:30:00Z
  URL: DATABASE_URL_BRANCH_FEATURE_PROFILES (auto-injected in preview env)
  Size: 2.3 GB (copy-on-write, no extra storage until changes)

Branches use copy-on-write storage. Creating a branch is instant regardless of database size. You only pay for the delta — changed pages.

Run Migrations on a Branch

# Connect to the branch
rf db connect feature-profiles

# Or run migrations directly
rf exec web "npx prisma migrate deploy" --env preview-pr-42

The preview environment for PR #42 automatically connects to the feature-profiles branch.

Compare Branch to Source

rf db diff feature-profiles --base main
SCHEMA CHANGES (main → feature-profiles)
─────────────────────────────────────────
+ TABLE user_profiles
  + id uuid PRIMARY KEY DEFAULT gen_random_uuid()
  + user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE
  + bio text
  + avatar_url text
  + created_at timestamptz DEFAULT now()

+ INDEX idx_user_profiles_user_id ON user_profiles(user_id)

~ TABLE users
  + COLUMN display_name varchar(100)

Merge Schema Changes

Generate a migration from the branch diff and apply it to the source:

rf db merge feature-profiles --to main --dry-run
DRY RUN — These SQL statements would be applied to main:

CREATE TABLE user_profiles (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  bio text,
  avatar_url text,
  created_at timestamptz DEFAULT now()
);
CREATE INDEX idx_user_profiles_user_id ON user_profiles(user_id);
ALTER TABLE users ADD COLUMN display_name varchar(100);

Apply? rf db merge feature-profiles --to main
rf db merge feature-profiles --to main
✓ Schema changes applied to main
✓ Branch feature-profiles retained (delete with rf db branch delete feature-profiles)

Branch Lifecycle

Branches are tied to preview environments by default:

  1. Developer opens PR → preview environment created → database branch created
  2. Migrations run on the branch → tests pass against real schema
  3. PR merged → schema diff reviewed → changes applied to staging/production
  4. Preview environment destroyed → branch cleaned up

Data Masking

When branching from production, mask PII automatically:

rf db branch main --name debug-issue --mask-pii

RaidFrame detects columns likely to contain PII (email, name, phone, address, SSN) and replaces values with realistic fake data. You can customize masking rules:

databases:
  main:
    masking:
      users.email: "faker.email"
      users.name: "faker.name"
      users.phone: "faker.phone"
      payments.card_last4: "****"
      audit_log: skip  # exclude entire table

Branch Management

# List all branches
rf db branches main

# View branch info
rf db branch info feature-profiles

# Delete a branch
rf db branch delete feature-profiles

# Reset branch to source snapshot
rf db branch reset feature-profiles