惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threat Research - Cisco Blogs
A
Arctic Wolf
S
Securelist
O
OpenAI News
T
Threatpost
Forbes - Security
Forbes - Security
N
News and Events Feed by Topic
S
Secure Thoughts
H
Heimdal Security Blog
S
Security Affairs
P
Privacy International News Feed
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
S
Security @ Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
T
Tailwind CSS Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hacker News: Ask HN
Hacker News: Ask HN
T
Troy Hunt's Blog
S
SegmentFault 最新的问题
腾讯CDC
V
Visual Studio Blog
Last Week in AI
Last Week in AI
H
Hacker News: Front Page
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Project Zero
Project Zero
WordPress大学
WordPress大学
NISL@THU
NISL@THU
博客园 - 【当耐特】
博客园 - Franky
Webroot Blog
Webroot Blog
博客园_首页
T
Tenable Blog
雷峰网
雷峰网
Google Online Security Blog
Google Online Security Blog
阮一峰的网络日志
阮一峰的网络日志
V2EX - 技术
V2EX - 技术
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
Lohrmann on Cybersecurity
The Hacker News
The Hacker News

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management Live Share: Connect to in-browser PGlite with any Postgres client
The Vibe Coder's Guide to Supabase Environments
Prashant Sridharan · 2025-08-17 · via Supabase Blog

Setting up separate development and production environments does not have to be painful. This guide shows you how to build a professional deployment workflow for your Supabase project. You will learn the essential patterns that prevent the 3am "I dropped production" panic attacks while keeping your workflow fun, simple, and safe.

Supabase is the open source Postgres development platform. At its core, it is just Postgres, but with an integrated suite: Auth, Storage, Edge Functions, Realtime, and Vector search. That means you can start hacking in minutes and also scale to millions when your app takes off.

With this post, we'll explore how to setup a professional development and staging environment for our projects to prevent those late night panics.

The fastest way to ruin your night is to treat your one Supabase project as both your playground and your live app. One wrong DROP TABLE and your users are gone. The simple fix is to create at least two projects: one for breaking things (development) and one for your users (production). Larger teams often add a staging project as well, but the minimum is two.

Create them in the Supabase Dashboard and give them obvious names like myapp-dev and myapp-prod. Boring names reduce mistakes. Grab the Project Reference IDs from Settings > General and stash them in a safe place.

Then set up the Supabase CLI:


_10

npm install supabase --save-dev

_10

supabase init


This creates a supabase/ directory, your single source of truth for migrations, functions, and seed data. Treat it like a ledger of every database change. Because it is just files, you can track it with Git, roll changes forward, and keep environments in sync. The flow should always be one direction: local development → dev project → production project. That is how you avoid the pain of trying to sync in multiple directions later.

Migrations are your safety net. Each one is a timestamped SQL file in supabase/migrations/. They record what changed and when, just like Git commits. This is how you avoid schema drift, where dev and prod quietly diverge until one day you cannot deploy without breaking things.

Here is the basic workflow:

  1. Create a migration whenever you need to change the schema:


    _10

    supabase migration new add_user_profiles


  2. Fill in the SQL, and always enable Row Level Security. Without RLS, anyone with your project URL can read all your data.


    _10

    CREATE TABLE public.profiles (

    _10

    id UUID REFERENCES auth.users ON DELETE CASCADE,

    _10

    username TEXT UNIQUE,

    _10

    avatar_url TEXT,

    _10

    created_at TIMESTAMPTZ DEFAULT NOW()

    _10

    );

    _10

    ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;

    _10

    CREATE POLICY "Users can view own profile" ON profiles

    _10

    FOR SELECT USING (auth.uid() = id);


  3. Test locally before touching any remote environment:

  4. If you make changes in the Dashboard instead of SQL, capture them:


    _10

    supabase db diff -f capture_dashboard_changes


Because migrations must run in order on a fresh database, always reset locally to prove they work. If supabase db reset works, production will too. This habit prevents the subtle drift that causes late night panics.

Every developer hits the same landmines once. Knowing them up front means you only hit them once.

  • Forgetting to enable RLS. Without it, your tables are wide open. Always add ALTER TABLE ... ENABLE ROW LEVEL SECURITY;.
  • Deploying to the wrong environment. Give production a different terminal theme, never store its credentials locally, and run supabase status to check before you push.
  • Migration conflicts. If two migrations collide after a Git merge, rename one with a later timestamp and rerun supabase db reset to verify the order.
  • Exposed service role keys. If one leaks, rotate it immediately in the Dashboard, update every environment, and scrub your Git history.

Mistakes are inevitable. Guardrails keep them from becoming disasters.

Manual deploys are risky. Automating them with GitHub Actions removes the human error. The idea is simple: push to develop to deploy to staging, merge to main to deploy to production.

Add your secrets in Settings > Secrets and variables > Actions. Then create .github/workflows/deploy.yml:


_21

name: Deploy Supabase

_21

on:

_21

push:

_21

branches: [main, develop]

_21

jobs:

_21

deploy:

_21

runs-on: ubuntu-latest

_21

steps:

_21

- uses: actions/checkout@v4

_21

- uses: supabase/setup-cli@v1

_21

with: { version: latest }

_21

- name: Deploy to staging

_21

if: github.ref == 'refs/heads/develop'

_21

run: |

_21

supabase link --project-ref ${{ secrets.STAGING_PROJECT_ID }}

_21

supabase db push

_21

- name: Deploy to production

_21

if: github.ref == 'refs/heads/main'

_21

run: |

_21

supabase link --project-ref ${{ secrets.PRODUCTION_PROJECT_ID }}

_21

supabase db push


Now deployments happen automatically with every push. You do not have to remember commands or worry about sending them to the wrong project. Larger teams often extend this with integration tests that run against staging before code can be promoted, but even this simple setup eliminates most accidents.

Every production app needs a backup plan. The best plans run without you thinking about them. Set up a GitHub Action to dump your database nightly.

Backups are only useful if you know they work. Schedule a monthly drill: restore a backup to a new project, run through your app, and confirm the data is intact. If you cannot restore, you do not have a backup.

For high stakes apps, combine PITR with read replicas and multi region deployments. That way you can recover from mistakes without downtime or lost data.

Secrets are a common leak. The rule is simple: anything with NEXT_PUBLIC_ is visible in browser code. Only use anon keys there.

Keep secrets like service role keys in .env.local, and never commit that file. Document what is required in .env.example. Then in your code, create two Supabase clients: one safe for the browser, one for server side code.

For bigger teams, a secrets manager like Doppler, Vault, or GitHub's encrypted environment variables makes rotation and auditing easier.

Your Git branches should map to your environments. Keep it simple: main for production, develop for staging, and feat/* for features. Supabase will even create preview branches for you automatically when you open a PR. Each one is a fully isolated Supabase instance with unique credentials, perfect for testing features before they hit staging.

This structure keeps your workflow clean and prevents confusion about which branch is safe to merge.

With all the pieces in place, you need habits to tie them together.

For daily development:

  • Start Supabase locally with supabase start
  • Branch from develop
  • Make schema changes with migrations
  • Test with supabase db reset
  • Commit and push

For deployments:

  • Open a pull request from your feature branch into develop
  • Test your changes in staging
  • Open a pull request from develop into main
  • Merge to deploy to production
  • Monitor production for 15 minutes to catch issues quickly

Pull requests are not just ceremony. They create an audit trail, trigger preview branches, and give you a chance to test before you touch production. That small delay saves hours of recovery work later.

Let's say your weekend project took off and people are using it. Let's build separate dev and prod environments. To start, you will create two Supabase projects instead of one. Use the dev project for breaking things, keep the production project for your users. After that, you'll set up Vercel to automatically use the right database for each environment.

Separate your environments#

Create a development project in the Supabase Dashboard and name it yourapp-dev. Rename your existing project to yourapp-prod for clarity. Now you have a safe place to experiment.

Extract your production schema and turn it into migration files:


_10

npm install supabase --save-dev

_10

supabase init

_10

_10

# Capture your production schema

_10

supabase link --project-ref YOUR_PROD_PROJECT_ID

_10

supabase db pull

_10

_10

# Apply the same schema to development

_10

supabase link --project-ref YOUR_DEV_PROJECT_ID

_10

supabase db push


This creates migration files in supabase/migrations/ that represent your current database structure. These files are your new source of truth for schema changes.

Configure Vercel environments#

Tell Vercel which database to use for each deployment. Go to your Vercel project settings and add environment variables:

Production environment (only main branch):


_10

NEXT_PUBLIC_SUPABASE_URL = https://yourapp-prod.supabase.co

_10

NEXT_PUBLIC_SUPABASE_ANON_KEY = your_prod_anon_key


Preview environment (all other branches):


_10

NEXT_PUBLIC_SUPABASE_URL = https://yourapp-dev.supabase.co

_10

NEXT_PUBLIC_SUPABASE_ANON_KEY = your_dev_anon_key


Update your local .env.local to point to the dev project so you never accidentally test against production data.

Your new daily workflow#

The workflow stays almost identical to what you know, with one key difference: you never touch the production Supabase Dashboard again.

For regular features:

  • Code locally (automatically uses dev database)
  • Push any branch to get a Vercel preview: git push origin feature/new-comments. Vercel automatically creates a preview URL like yourapp-git-feature-new-comments.vercel.app that connects to your dev database with safe test data.
  • Test the preview URL with fake data
  • Merge to main when ready: Create a pull request on GitHub, review your changes, then merge. Vercel automatically deploys to your production domain using the production database.

For database changes:

  • Create a migration: supabase migration new add_comments_table
  • Write SQL in the generated file
  • Test on dev: supabase db push
  • Commit the migration file and push: git add supabase/migrations/ then git commit -m "Add comments table" then git push origin feature/comments. The migration file gets committed to your repo like any other code.
  • Production gets the same changes automatically

Automate production deployments#

Without automation, you would need to manually apply database changes to production every time you merge code. That means remembering to run supabase db push against your production project, which is error-prone and easy to forget.

GitHub Actions solves this by watching your repository and automatically running commands when specific events happen. Set up GitHub Actions to handle production database changes. Create .github/workflows/deploy.yml:


_17

name: Deploy to Production

_17

on:

_17

push:

_17

branches: [main]

_17

_17

jobs:

_17

deploy:

_17

runs-on: ubuntu-latest

_17

steps:

_17

- uses: actions/checkout@v4

_17

- uses: supabase/setup-cli@v1

_17

- name: Apply migrations to production

_17

run: |

_17

supabase link --project-ref ${{ secrets.PRODUCTION_PROJECT_ID }}

_17

supabase db push

_17

env:

_17

SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}


This file tells GitHub: "Every time someone merges code into the main branch, automatically connect to the production Supabase project and apply any new migration files." Vercel handles your frontend deployment, but your database changes need this extra step.

Here is what happens when you merge a pull request:

  1. Vercel automatically deploys your new frontend code to production
  2. GitHub Actions triggers and connects to your production Supabase project
  3. Any new migration files get applied to the production database
  4. Your frontend and database stay in perfect sync

Add your project IDs and access token to GitHub secrets. Now every merge to main automatically applies your migrations to production. No more forgetting to update the database. No more manual steps that can go wrong at 2am.

The safety net effect#

Every branch you push creates a preview deployment that uses development data. You can test destructive changes, experiment with new features, and invite others to try things without any risk to production.

The key insight is that your development and production environments stay perfectly in sync through migrations. When a migration works in development, it will work in production. No more schema drift, no more surprise failures.

Enable Row Level Security immediately#

Your weekend project probably skipped RLS. Fix this now before you ship new features:


_10

ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;

_10

CREATE POLICY "Users can only access their own data" ON your_table

_10

FOR ALL USING (auth.uid() = user_id);


Apply these policies to both environments. RLS is your last line of defense against data breaches.

This setup takes one afternoon to implement but eliminates the fear of breaking production. You can move fast again while your users stay protected. The same tools, the same workflow, just organized safely.

The path from vibe coder to confident deployer is not about memorizing every DevOps buzzword. It is about a handful of patterns that keep you safe: separate environments, migrations as save points, automated deployments, tested backups, and strict RLS. Supabase makes this easy because everything is Postgres, deeply integrated, and scalable from weekend project to millions of users.