supabase-multi-env-setup

Configure Supabase across development, staging, and production with separate projects, environment-specific secrets, and safe migration promotion. Use when setting up multi-environment deployments, isolating dev from prod data, configuring per-environment Supabase projects, or promoting migrations through environments. Trigger with "supabase environments", "supabase staging", "supabase dev prod", "supabase multi-project", "supabase env config", "database branching".

Allowed Tools

ReadWriteEditBash(npx supabase:*)Bash(supabase:*)Bash(vercel:*)

Provided by Plugin

supabase-pack

Claude Code skill pack for Supabase (30 skills)

saas packs v1.53.0
View Plugin

Installation

This skill is included in the supabase-pack plugin:

/plugin install supabase-pack@claude-code-plugins-plus

Click to copy

Instructions

Supabase Multi-Environment Setup

Overview

Production Supabase deployments require a separate project per environment — each with its

own URL, API keys, database, and RLS policies. This skill configures a three-tier

architecture (local dev, staging, production) with safe migration promotion via

supabase db push, environment-aware createClient initialization, database branching

for preview deployments, and CI/CD that prevents accidental cross-environment operations.

When to use: setting up a new project with multiple environments, migrating from a

single-project setup, adding staging to an existing dev/prod split, or configuring preview

environments with database branching.

Prerequisites

  • Three separate Supabase projects created at supabase.com/dashboard (dev, staging, production)
  • Supabase CLI installed: npm install -g supabase or npx supabase --version
  • @supabase/supabase-js v2+ installed in your project
  • Node.js 18+ with a framework that supports .env files (Next.js, Nuxt, SvelteKit, etc.)
  • A secret management solution for CI (GitHub Actions Secrets, Vercel env vars, etc.)

Instructions

The workflow is three steps. Each step below gives the shape and the one command that

matters; the full implementation walkthrough carries the

complete env files, TypeScript client factory, RLS policies, CI/CD workflow, and seed data

verbatim.

Step 1: Environment Files and Project Layout

Keep one Supabase CLI project with shared migrations and one .env.* file per

environment. Each file points at a different Supabase project; only .env.local is safe to

commit.


supabase/migrations/   # shared schema — every env applies the same migrations
.env.local             # supabase start defaults (safe to commit)
.env.staging           # staging project creds  (gitignored)
.env.production        # production project creds (gitignored — NEVER commit)

The CLI links one project at a time. Before any db push or functions deploy,

re-link to the target:


npx supabase link --project-ref <target-ref>

See the implementation walkthrough (Step 1)

for full .env.* contents, the .gitignore block, and the local-port reference.

Step 2: Environment-Aware Client and Safeguards

Detect the active environment once, then build browser (anon key, respects RLS) and server

(service-role key, bypasses RLS) clients from it. Gate every destructive helper behind a

production guard so seeds and resets can never fire against prod:


export function requireNonProduction(operation: string): void {
  if (isProduction()) {
    throw new Error(`[BLOCKED] "${operation}" is not allowed in production.`);
  }
}

The implementation walkthrough (Step 2)

has the full lib/env.ts detection, the createBrowserClient / createServerClient

factory, the seedTestData / resetDatabase guards, and environment-scoped RLS policies.

Step 3: Migration Promotion and Database Branching

Promote schema changes strictly local → staging → production. db reset applies

everything plus seed.sql locally; db push applies only new migrations to a linked

remote:


npx supabase db reset                              # local: all migrations + seed
npx supabase link --project-ref <staging-ref> && npx supabase db push   # then staging
npx supabase link --project-ref <prod-ref>    && npx supabase db push   # then production

For preview deployments, supabase branches create (Pro plan) gives each feature its own

isolated database, URL, and keys. Full migration workflow, branching commands, the

GitHub Actions deploy workflow (with a production approval gate), and seed data live in the

implementation walkthrough (Step 3).

Output

Completing this skill produces:

  • Three isolated Supabase projects — each with its own URL, API keys, database, and storage
  • Environment-specific .env files.env.local, .env.staging, .env.production with correct credentials
  • Environment-aware createClient — browser and server clients auto-configured from env vars with x-environment header tracking
  • Production safeguardsrequireNonProduction() blocks destructive operations outside local/staging
  • Migration promotion pipelinesupabase db push promotes schema changes local → staging → production
  • Database branching — preview environments get isolated database branches (Pro plan)
  • CI/CD workflows — GitHub Actions deploys migrations and Edge Functions per environment with approval gates for production
  • Generated TypeScript typesdatabase.types.ts generated from local or linked project schema

Error Handling

Error Cause Solution
Cannot find project ref CLI not linked to a project Run npx supabase link --project-ref before db push
Migration has already been applied Re-running an existing migration Check supabasemigrations.schemamigrations table; migrations are idempotent by ref
Permission denied for schema public Wrong database password Verify SUPABASEDBPASSWORD matches the project's database password in dashboard
Seed data appeared in production Ran supabase db reset on prod seed.sql only runs on db reset — never reset production; use db push instead
Wrong environment keys in client .env file mismatch Check SUPABASE_ENV var and verify URL matches expected project ref
Branch creation failed Free plan or branching not enabled Database branching requires Supabase Pro plan; enable in project settings
Migration drift between envs Skipped staging promotion Always promote through staging first; compare with supabase migration list per project
Type generation mismatch Types generated from wrong env Regenerate from local (--local) or re-link to the canonical environment

Examples

Three worked examples live in references/examples.md. The fastest

path — a full three-env bootstrap from supabase init to a production db push — is:


npx supabase init && npx supabase start        # local, copy keys to .env.local
npx supabase migration new create_users        # author schema, then:
npx supabase db reset                           # verify locally
npx supabase link --project-ref "<staging-ref>" && npx supabase db push
npx supabase link --project-ref "<prod-ref>"    && npx supabase db push

Examples 2 and 3 (full file) show a Next.js middleware that

stamps and gates on x-supabase-env, and an admin handler that calls requireNonProduction

before a destructive RPC.

Resources

Next Steps

  • For authentication patterns across environments, see supabase-auth-storage-realtime-core
  • For RLS policy testing and validation, see supabase-policy-guardrails
  • For local development workflow optimization, see supabase-local-dev-loop
  • For monitoring and observability across environments, see supabase-observability

Ready to use supabase-pack?