Developer Docs

Database Management

Managing PostgreSQL databases with Neon branching, running migrations, resetting data, and auditing database branches.

Database Management

DevStride uses Neon for PostgreSQL hosting, with Drizzle ORM for schema management and migrations. Every developer gets isolated database branches — like git branches, but for your database.

How Neon Branching Works

Neon provides instant, copy-on-write database branches:

main (staging data)
├── dev-phil-local              ← Phil's local dev branch (stable, branch-independent)
├── dev-phil-feature-auth       ← Phil's cloud deploy branch (created by ds deploy up)
├── dev-sarah-local             ← Sarah's local dev branch
└── dev-ci-pr-142               ← CI/CD ephemeral branch
  • main contains the latest staging data. All new branches fork from it.
  • Local branches (dev-{developer}-local) are used for local development. One per developer, stable across git branch switches.
  • Cloud branches (dev-{developer}-{branch}) are created by ds deploy up for isolated cloud testing. Each cloud stage gets its own separate database branch.
  • Branches are cheap — they use copy-on-write storage, so a branch with no changes uses almost no additional space.

Migrations

Running Migrations

ds db migrate

Applies all pending Drizzle ORM migrations to your database. Migrations are idempotent — already-applied migrations are skipped.

Options:

FlagDescription
--target <stage>Target a specific stage (default: your current DEVSTRIDE_STAGE)

Creating a Migration

When you modify a database schema:

  1. Edit the SQL entity file — e.g., backend/src/modules/notification/infrastructure/persistence/notification.sql-entity.ts
  2. Generate the migration:
    cd backend && pnpm generate-sql
    

    This compares your entity definitions against the current schema and generates a migration file in backend/drizzle/.
  3. Apply the migration:
    ds db migrate
    
  4. Restart the backend to pick up schema changes:
    ds local run backend
    

Branch Management

Neon branches are automatically provisioned by the tooling. You don't need to create or delete branches manually.

  • ds setup creates your local branch (dev-{developer}-local) from main and writes the connection string to .env
  • ds deploy up (CI) creates a separate branch for each cloud stage (dev-{developer}-{branch}) and stores credentials in Secrets Manager
  • ds deploy down tears down the cloud branch along with all other cloud stage resources

Your local branch (dev-{developer}-local) is independent from cloud branches. Running ds db migrate locally applies migrations to your local branch. Cloud deployments run their own migrations against their own branches.

For branch inspection and cleanup, use ds db status and ds db audit.

Check Branch Status

ds db status

Shows your active Neon branch, connection details, and environment info.

Options:

FlagDescription
--target <stage>Check a specific stage
--jsonMachine-readable JSON output

Resetting Data

Reset from Main

ds db reset

Resets your Neon branch to match the main branch, then re-applies all migrations. This is the cleanest way to get fresh staging data.

What happens:

  1. Restores your branch from the main branch snapshot (Neon copy-on-write)
  2. Your connection string stays the same (no .env update needed)
  3. Re-applies all Drizzle migrations
  4. You need to restart your backend after

Options:

FlagDescription
--target <stage>Target a specific stage (default: your current DEVSTRIDE_STAGE)

When to use:

  • Your data is in a bad state from testing
  • You want the latest staging data
  • Migrations got tangled and you need a clean slate

Refresh Staging Data

ds db refresh-staging

This is an admin operation that refreshes the main Neon branch with production data:

  1. Dispatches a GitHub Actions workflow
  2. Copies a specified organization's data from production to the staging main branch
  3. All future developer branches will inherit this refreshed data
  4. Existing developer branches are not affected

Options:

FlagDescription
-o, --organization <id>Organization ID to copy (default: demo organization)

Use this when staging data has drifted too far from production, or when you need realistic data for testing.

Auditing Branches

Branch Audit

ds db audit

An interactive explorer that cross-references Neon branches with Pulumi stacks:

  • Lists all Neon branches with age and state
  • Shows which branches have a matching Pulumi stack (deployed stage)
  • Flags marooned branches — branches with no corresponding stage
  • Interactive selection to view branch details
  • Press d to delete a stale branch

Options:

FlagDescription
--jsonMachine-readable output

When to use:

  • Periodic cleanup of forgotten branches
  • Investigating disk usage
  • Finding branches left behind after ds deploy down

Database Lifecycle Summary

Here's how database branches fit into the development lifecycle:

PhaseCommandWhat Happens
Setupds setupCreates your Neon branch from main automatically
Schema changepnpm generate-sql then ds db migrateGenerates and applies migration
Fresh datads db resetResets branch to main data + re-applies migrations
Quick checkds db statusShows which Neon branch you're on
Cleanupds db auditFind and delete stale/orphaned branches
Staging refreshds db refresh-stagingRefreshes main with latest prod data

Next Steps