Complete guide for isolated feature development with database branches.
Source: Inspired by Neon database branching and PlanetScale branching workflows.
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 devDone. Skip to workflow examples.
Install CLI:
npm install -g neonctl
neonctl authCreate branch:
neonctl branches create --name <branch-name> --parent mainGet connection string:
neonctl connection-string --branch <branch-name>Update .env in worktree:
echo "DATABASE_URL=<connection-string>" > .worktrees/<branch>/.envDelete 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
Install CLI:
brew install pscale
pscale auth loginCreate branch:
pscale branch create <database-name> <branch-name>Connect (spawns local proxy):
pscale connect <database-name> <branch-name> --port 3309Update .env to use localhost:3309:
echo "DATABASE_URL=mysql://root@127.0.0.1:3309/<database-name>" > .worktrees/<branch>/.envDelete 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 connectfor local dev
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 deployCleanup:
psql $DATABASE_URL -c "DROP SCHEMA <schema-name> CASCADE;"Strengths:
- Free
- Full control
Limitations:
- Manual setup
- No automatic copy-on-write
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 | 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 |
# 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# 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)# 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-
.worktreeincludecontains.env - Database branch created (if provider supports it)
-
.envin worktree updated with newDATABASE_URL - Connection tested (
npx prisma db execute --stdin <<< "SELECT 1;") - Migrations applied (
npx prisma migrate dev)
- Git worktree removed
- Database branch deleted
- No orphaned connections
Fix: Check .env was copied, verify .worktreeinclude setup
Fix: Verify DATABASE_URL points to branch, not main
Fix: Run neonctl auth to log in
Fix: Use pscale connect proxy, don't connect directly
# List existing branches
neonctl branches list
# Delete if stale
neonctl branches delete <branch-name> --force# Reset DB branch to clean state
neonctl branches reset <branch-name> --parent main
# Re-apply migrations
npx prisma migrate deploy- Database branches are NOT in
.gitignoreby default - Add
.envto.worktreeincludeso credentials are copied - Never commit
DATABASE_URLwith 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# 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# 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 onlyRelated guides: