Fork databases for testing, run migrations on branches, merge schema changes back.
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.
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.
# 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.
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)
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)
Branches are tied to preview environments by default:
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
# 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