Skip to content

Latest commit

 

History

History
349 lines (257 loc) · 7.59 KB

File metadata and controls

349 lines (257 loc) · 7.59 KB

Database Branch Setup with Worktrees

Complete guide for isolated feature development with database branches.

Source: Inspired by Neon database branching and PlanetScale branching workflows.


TL;DR (90% Use Case)

Using Neon:

/git-worktree feature/auth
cd .worktrees/feature-auth
neonctl branches create --name feature-auth --parent main
# Copy DATABASE_URL from output to .env
pnpm prisma migrate dev

Done. Skip to workflow examples.


Provider Setup

Neon (Recommended)

Install CLI:

npm install -g neonctl
neonctl auth

Create branch:

neonctl branches create --name <branch-name> --parent main

Get connection string:

neonctl connection-string --branch <branch-name>

Update .env in worktree:

echo "DATABASE_URL=<connection-string>" > .worktrees/<branch>/.env

Delete when done:

neonctl branches delete <branch-name>

Strengths:

  • Instant branch creation (~1s)
  • True copy-on-write (efficient storage)
  • Branch resets without data loss
  • Excellent CLI

Limitations:

  • Connection pooling configuration needed

PlanetScale

Install CLI:

brew install pscale
pscale auth login

Create branch:

pscale branch create <database-name> <branch-name>

Connect (spawns local proxy):

pscale connect <database-name> <branch-name> --port 3309

Update .env to use localhost:3309:

echo "DATABASE_URL=mysql://root@127.0.0.1:3309/<database-name>" > .worktrees/<branch>/.env

Delete when done:

pscale branch delete <database-name> <branch-name>

Strengths:

  • Git-like workflow for schema
  • Built-in schema diff
  • Safe deploy requests

Limitations:

  • Different connection string per branch
  • Requires pscale connect for local dev

Local Postgres (Schema-based)

For projects without cloud DB:

Create schema:

psql $DATABASE_URL -c "CREATE SCHEMA <schema-name>;"

Update .env to use schema:

DATABASE_URL="postgresql://user:pass@localhost:5432/db?schema=<schema-name>"

Run migrations in schema:

npx prisma migrate deploy

Cleanup:

psql $DATABASE_URL -c "DROP SCHEMA <schema-name> CASCADE;"

Strengths:

  • Free
  • Full control

Limitations:

  • Manual setup
  • No automatic copy-on-write

When to Use Database Branches

Decision Tree

Does feature touch database schema?
├─ No → Use shared database, skip branch creation
└─ Yes → Create database branch
    ├─ Using Neon/PlanetScale? → Use native branching
    ├─ Using local Postgres? → Create dedicated schema
    └─ Other provider? → Consider Docker or shared DB with caution

Scenario Table

Scenario Use DB Branch? Rationale
Adding database migrations ✅ Yes Isolate schema changes
Refactoring data model ✅ Yes Safe to experiment
Performance testing ✅ Yes Dedicated resources
Bug fix (no schema change) ❌ No Shared DB is fine
Feature with schema changes ✅ Yes Avoid conflicts
Hotfix (urgent) ❌ No Speed over isolation

Workflow Examples

Example 1: Schema Migration Feature

# 1. Create worktree + DB branch
/git-worktree feature/add-user-roles
cd .worktrees/feature-add-user-roles

# 2. Create Neon branch
neonctl branches create --name feature-add-user-roles --parent main

# 3. Update .env with new DATABASE_URL
# (Copy from neonctl output)

# 4. Create migration in steps
npx prisma migrate dev --name step1_add_role_column
npx prisma migrate dev --name step2_migrate_existing_users
npx prisma migrate dev --name step3_add_constraints

# 5. Test entire migration sequence
pnpm prisma migrate reset --skip-seed
pnpm prisma migrate deploy
pnpm test

# 6. If successful, merge PR
# 7. Apply to main DB after deploy

Example 2: Data Model Experimentation

# Try different schemas without commitment
/git-worktree experiment/normalize-addresses
cd .worktrees/experiment-normalize-addresses

# Create DB branch
neonctl branches create --name experiment-normalize-addresses --parent main

# Completely remodel data
# Test with real-ish data
# Compare performance

# If better → merge
# If worse → delete branch (no cleanup needed)

Example 3: Parallel Feature Development

# Terminal 1
/git-worktree feature/payments
cd .worktrees/feature-payments
neonctl branches create --name feature-payments --parent main
# DATABASE_URL → feature-payments branch

# Terminal 2
/git-worktree feature/subscriptions
cd .worktrees/feature-subscriptions
neonctl branches create --name feature-subscriptions --parent main
# DATABASE_URL → feature-subscriptions branch

# Both can modify schema independently
# No conflicts until merge

Checklist

Before starting work in worktree with DB changes:

  • .worktreeinclude contains .env
  • Database branch created (if provider supports it)
  • .env in worktree updated with new DATABASE_URL
  • Connection tested (npx prisma db execute --stdin <<< "SELECT 1;")
  • Migrations applied (npx prisma migrate dev)

After PR merge:

  • Git worktree removed
  • Database branch deleted
  • No orphaned connections

Troubleshooting

Issue: "Database not found" in worktree

Fix: Check .env was copied, verify .worktreeinclude setup

Issue: Migrations affect main database

Fix: Verify DATABASE_URL points to branch, not main

Issue: Can't create Neon branch - "not authenticated"

Fix: Run neonctl auth to log in

Issue: PlanetScale branch exists but can't connect

Fix: Use pscale connect proxy, don't connect directly

Issue: "Branch already exists"

# List existing branches
neonctl branches list

# Delete if stale
neonctl branches delete <branch-name> --force

Issue: Migration failed

# Reset DB branch to clean state
neonctl branches reset <branch-name> --parent main

# Re-apply migrations
npx prisma migrate deploy

Security Notes

⚠️ Remember:

  • Database branches are NOT in .gitignore by default
  • Add .env to .worktreeinclude so credentials are copied
  • Never commit DATABASE_URL with real credentials
  • Use different credentials per environment

Best Practice:

# .worktreeinclude
.env
.env.local
.env.development

# Each worktree gets copy of credentials
# But each points to different DB branch

Advanced Patterns

Pattern: Progressive Schema Migration

# 1. Create worktree + DB branch
/git-worktree migration/split-user-table
cd .worktrees/migration-split-user-table

# 2. Create migration in steps
npx prisma migrate dev --name step1_add_new_columns
npx prisma migrate dev --name step2_migrate_data
npx prisma migrate dev --name step3_drop_old_columns

# 3. Test entire migration sequence
pnpm prisma migrate reset --skip-seed
pnpm prisma migrate deploy

# 4. If successful, merge PR
# 5. Apply to main DB after deploy

Pattern: Performance Benchmarking

# Create worktree with isolated DB
/git-worktree perf/optimize-queries
cd .worktrees/perf-optimize-queries

# DB branch lets you:
# - Add indexes without affecting dev
# - Run load tests safely
# - Compare before/after metrics

# Merge proven optimizations only

Related guides: