import { Callout } from '@/components/mdx'
Introduction
Manually running database migrations and deploying Next.js apps via CLI is manageable for solo projects in their infancy. But the moment you add a second developer or get real paying customers, manual deployments become a massive liability.
In production SaaS environments with Next.js and Supabase, your delivery pipeline needs to handle two distinct but deeply connected lifecycles: code deployments and database schema migrations.
This guide breaks down exactly how to orchestrate a modern CI/CD pipeline using GitHub Actions, Vercel, and the Supabase CLI to achieve safe, automated, zero-downtime deployments.
The Architecture of a Full-Stack Pipeline
A production-grade Next.js + Supabase pipeline has three distinct environments:
-
Local: Dockerized Supabase running alongside
next dev. - Preview/Staging: Vercel branch previews connected to a separate Supabase "Staging" project.
- Production: Vercel production deployment connected to your Live Supabase project.
Our goal is to ensure that when a Pull Request is merged into main, GitHub Actions automatically:
- Lints and type-checks the Next.js code.
- Pushes SQL migrations to the Supabase Production Database.
- Triggers Vercel to build and promote the application.
1. Supabase Local Development Setup
To enable CI/CD, you cannot make schema changes directly in the Supabase Dashboard UI. You must treat your database schema as code.
Initialize Supabase in your Next.js project:
npx supabase init
This creates a supabase/ folder. Start your local database:
npx supabase start
Whenever you need to change your database (e.g., adding a profiles table), generate a new migration file:
npx supabase migration new create_profiles_table
Write your SQL in the generated file (supabase/migrations/<timestamp>_create_profiles_table.sql), and apply it locally:
npx supabase db reset
2. Linking the Production Project
For GitHub Actions to deploy migrations, you need to acquire a Supabase Access Token and link your project.
- Go to your Supabase Dashboard > Access Tokens -> Generate a new token.
- Copy your Production Project ID (from the dashboard URL:
https://supabase.com/dashboard/project/<project-id>).
Add these as repository secrets in GitHub:
SUPABASE_ACCESS_TOKENSUPABASE_DB_PASSWORDSUPABASE_PROJECT_ID
3. Creating the GitHub Actions Workflow
Create a new file in your project: .github/workflows/production-deployment.yml.
This file instructs GitHub to run your testing suite, deploy the Supabase migrations, and only if successful, trigger the Vercel deployment.
name: Production Deployment CI/CD
on:
push:
branches:
- main
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Type Check & Lint
run: |
npm run lint
npx tsc --noEmit
deploy-database:
needs: lint-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Supabase CLI
uses: supabase/setup-cli@v1
with:
version: latest
- name: Push Migrations to Production
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
SUPABASE_PROJECT_ID: ${{ secrets.SUPABASE_PROJECT_ID }}
run: |
supabase link --project-ref $SUPABASE_PROJECT_ID --password $SUPABASE_DB_PASSWORD
supabase db push
deploy-vercel:
needs: deploy-database
runs-on: ubuntu-latest
steps:
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
Execution Order is Critical: Notice the needs keys? Vercel deployment will only run after migrations succeed. If your Vercel build deploys new code before the database schema is updated, user queries will error out on staging/production.
4. Handling Rollbacks
A solid CI/CD strategy isn't just about pushing forward; it's about retreating safely.
Because we decoupled the frontend deployment from the database deployment, rolling back code via the Vercel Dashboard is instantly possible. However, rolling back a database migration requires manual intervention via the Supabase CLI.
Never make destructive SQL changes (like DROP COLUMN) until you are 100% certain the application has stopped using that column entirely. Instead, use a two-phase rollout:
- Add the new column.
- Update Next.js code to write to both old and new columns.
- Migrate old data.
- Drop the old column in a future PR.
Key Takeaways
-
Database as Code: Stop using the Supabase Dashboard for schema changes. Use
supabase migration new. - Pipeline Integrity: Always run code linting first, database migrations second, and frontend deployment last.
-
Secrets Management: Keep your
SUPABASE_DB_PASSWORDand access tokens strictly confined to GitHub Secrets.
Next Steps
Now that your deployment is fully automated, dive deeper into scaling the actual UI layers natively on Edge infrastructure. Our deep dive into Serverless and Edge Computing 2026 will show you how to utilize Vercel's edge network alongside Supabase.
Originally published at https://www.iloveblogs.blog
Top comments (0)