supabase-prod-checklist

3
1
Source

Execute Supabase production deployment checklist and rollback procedures. Use when deploying Supabase integrations to production, preparing for launch, or implementing go-live procedures. Trigger with phrases like "supabase production", "deploy supabase", "supabase go-live", "supabase launch checklist".

Install

mkdir -p .claude/skills/supabase-prod-checklist && curl -L -o skill.zip "https://mcp.directory/api/skills/download/4213" && unzip -o skill.zip -d .claude/skills/supabase-prod-checklist && rm skill.zip

Installs to .claude/skills/supabase-prod-checklist

About this skill

Supabase Production Deployment Checklist

Overview

Actionable 14-step checklist for taking a Supabase project to production. Covers RLS enforcement, key separation, connection pooling (Supavisor), backups/PITR, network restrictions, custom domains, auth emails, rate limits, monitoring, Edge Functions, Storage policies, indexes, and migrations. Based on Supabase's official production guide.

Prerequisites

  • Supabase project on Pro plan or higher (required for PITR, network restrictions)
  • Separate production project (never share dev/prod)
  • @supabase/supabase-js v2+ installed
  • Supabase CLI installed (npx supabase --version)
  • Domain and DNS configured for custom domain
  • Deployment platform ready (Vercel, Netlify, Cloudflare, etc.)

Instructions

Step 1: Enforce Row Level Security on ALL Tables

RLS is the single most critical production requirement. Without it, any client with your anon key can read/write every row.

-- Audit: find tables WITHOUT RLS enabled
-- This query MUST return zero rows before going live
SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public' AND rowsecurity = false;
-- Enable RLS on a table
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;

-- Create a basic read policy (authenticated users see own rows)
CREATE POLICY "Users can view own profile"
  ON public.profiles
  FOR SELECT
  USING (auth.uid() = user_id);

-- Create an insert policy
CREATE POLICY "Users can insert own profile"
  ON public.profiles
  FOR INSERT
  WITH CHECK (auth.uid() = user_id);

-- Create an update policy
CREATE POLICY "Users can update own profile"
  ON public.profiles
  FOR UPDATE
  USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);
  • RLS enabled on every public table (zero rows from audit query above)
  • SELECT, INSERT, UPDATE, DELETE policies defined for each table
  • Policies tested with both authenticated and anonymous roles
  • No tables use USING (true) without intent (public read tables only)

Step 2: Enforce Key Separation — Anon vs Service Role

The anon key is safe for client-side code. The service_role key bypasses RLS entirely and must never leave server-side environments.

// Client-side — ONLY use anon key
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!  // Safe for browsers
);
// Server-side only — service_role key (API routes, webhooks, cron jobs)
import { createClient } from '@supabase/supabase-js';

const supabaseAdmin = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!,  // NEVER expose to client
  { auth: { autoRefreshToken: false, persistSession: false } }
);
  • Anon key used in all client-side code (NEXT_PUBLIC_ prefix)
  • Service role key used only in server-side code (API routes, Edge Functions)
  • Service role key not in any client bundle (verify with grep -r "service_role" dist/)
  • Database password changed from the auto-generated default

Step 3: Configure Connection Pooling (Supavisor)

Supabase uses Supavisor for connection pooling. Serverless functions (Vercel, Netlify, Cloudflare Workers) MUST use the pooled connection string to avoid exhausting the database connection limit.

# Direct connection (migrations, admin tasks only)
postgresql://postgres:[PASSWORD]@db.[REF].supabase.co:5432/postgres

# Pooled connection via Supavisor (application code — USE THIS)
# Port 6543 = Supavisor pooler (vs 5432 direct)
postgresql://postgres.[REF]:[PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
// For serverless environments — use pooled connection
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!,
  {
    db: { schema: 'public' },
    // Supavisor handles pooling at port 6543
    // No need to configure pgBouncer settings in the client
  }
);
  • Application code uses pooled connection string (port 6543)
  • Direct connection reserved for migrations and admin tasks only
  • Connection string in deployment platform env vars (not hardcoded)
  • Verified pool mode: transaction for serverless, session for long-lived connections

Step 4: Enable Database Backups

Supabase provides automatic daily backups on Pro plan. Point-in-time recovery (PITR) enables granular restores.

  • Automatic daily backups enabled (Pro plan — verify in Dashboard > Database > Backups)
  • Point-in-time recovery configured (Dashboard > Database > Backups > PITR)
  • Tested restore procedure on a staging project (do not skip this)
  • Migration files committed to version control (supabase/migrations/ directory)
  • npx supabase db push tested against a fresh project to verify migrations replay cleanly

Step 5: Configure Network Restrictions

Restrict database access to known IP addresses. This prevents unauthorized direct database connections even if credentials leak.

  • IP allowlist configured (Dashboard > Database > Network Restrictions)
  • Only deployment platform IPs and team office IPs are allowed
  • Verified that application still connects after restrictions applied
  • Documented which IPs are allowed and why

Step 6: Configure Custom Domain

A custom domain replaces the default *.supabase.co URLs with your brand domain for API and auth endpoints.

  • Custom domain configured (Dashboard > Settings > Custom Domains)
  • DNS CNAME record added and verified
  • SSL certificate provisioned and active
  • Application code updated to use custom domain URL
  • OAuth redirect URLs updated to use custom domain

Step 7: Customize Auth Email Templates

Default Supabase auth emails show generic branding. Customize them so users see your domain and brand.

  • Confirmation email template customized (Dashboard > Auth > Email Templates)
  • Password reset email template customized
  • Magic link email template customized
  • Invite email template customized
  • Custom SMTP configured (Dashboard > Auth > SMTP Settings) — avoids rate limits and improves deliverability
  • Email confirmation enabled (Dashboard > Auth > Settings)
  • OAuth redirect URLs restricted to production domains only
  • Unused auth providers disabled

Step 8: Understand Rate Limits Per Tier

Supabase enforces rate limits that vary by plan. Hitting these in production causes 429 errors.

ResourceFreeProTeam
API requests500/min1,000/min5,000/min
Auth emails4/hour30/hour100/hour
Realtime connections200 concurrent500 concurrent2,000 concurrent
Edge Function invocations500K/month2M/month5M/month
Storage bandwidth2GB/month250GB/monthCustom
Database size500MB8GB50GB
  • Rate limits documented for your plan tier
  • Client-side retry logic with exponential backoff for 429 responses
  • Auth email rate limits understood (use custom SMTP to increase)
  • Realtime connection limits planned for expected concurrent users

Step 9: Review Monitoring Dashboards

Supabase provides built-in monitoring. Review these before launch to establish baselines.

// Health check endpoint — deploy this to your application
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!
);

export async function GET() {
  const start = Date.now();
  const { data, error } = await supabase
    .from('_health_check')  // Create a small table for this
    .select('id')
    .limit(1);

  const latency = Date.now() - start;

  return Response.json({
    status: error ? 'unhealthy' : 'healthy',
    latency_ms: latency,
    timestamp: new Date().toISOString(),
    supabase_reachable: !error,
  }, { status: error ? 503 : 200 });
}
  • Dashboard > Reports reviewed (API requests, auth, storage, realtime)
  • Dashboard > Logs > API checked for error patterns
  • Dashboard > Database > Performance Advisor reviewed and recommendations applied
  • Health check endpoint deployed and monitored (uptime service)
  • Error tracking configured (Sentry, LogRocket, etc.)
  • Alerts set for: error rate spikes, high latency, connection pool exhaustion

Step 10: Deploy Edge Functions with Proper Env Vars

Edge Functions run on Deno Deploy. Environment variables must be set via the Supabase CLI or Dashboard, not hardcoded.

# Set secrets for Edge Functions
npx supabase secrets set STRIPE_SECRET_KEY=sk_live_...
npx supabase secrets set RESEND_API_KEY=re_...

# List current secrets
npx supabase secrets list

# Deploy all Edge Functions
npx supabase functions deploy

# Deploy a specific function
npx supabase functions deploy process-webhook
// supabase/functions/process-webhook/index.ts
import { createClient } from '@supabase/supabase-js';

Deno.serve(async (req) => {
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL')!,
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!  // Available automatically
  );

  const body = await req.json();
  // Process webhook payload...

  return new Response(JSON.stringify({ received: true }), {
    headers: { 'Content-Type': 'application/json' },
  });
});
  • All Edge Functions deployed to production (npx supabase functions deploy)
  • Environment secrets set via npx supabase secrets set (not hardcoded)
  • SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY available automatically (no need to set)
  • Edge Functions tested with npx supabase functions serve locally before deploying
  • CORS headers configured for Edge Functions that receive browser requests

Step 11: Verify Storage Bucket Policies

Storage buckets need ex


Content truncated.

svg-icon-generator

jeremylongshore

Svg Icon Generator - Auto-activating skill for Visual Content. Triggers on: svg icon generator, svg icon generator Part of the Visual Content skill category.

11240

d2-diagram-creator

jeremylongshore

D2 Diagram Creator - Auto-activating skill for Visual Content. Triggers on: d2 diagram creator, d2 diagram creator Part of the Visual Content skill category.

9033

automating-mobile-app-testing

jeremylongshore

This skill enables automated testing of mobile applications on iOS and Android platforms using frameworks like Appium, Detox, XCUITest, and Espresso. It generates end-to-end tests, sets up page object models, and handles platform-specific elements. Use this skill when the user requests mobile app testing, test automation for iOS or Android, or needs assistance with setting up device farms and simulators. The skill is triggered by terms like "mobile testing", "appium", "detox", "xcuitest", "espresso", "android test", "ios test".

18828

performing-penetration-testing

jeremylongshore

This skill enables automated penetration testing of web applications. It uses the penetration-tester plugin to identify vulnerabilities, including OWASP Top 10 threats, and suggests exploitation techniques. Use this skill when the user requests a "penetration test", "pentest", "vulnerability assessment", or asks to "exploit" a web application. It provides comprehensive reporting on identified security flaws.

5519

designing-database-schemas

jeremylongshore

Design and visualize efficient database schemas, normalize data, map relationships, and generate ERD diagrams and SQL statements.

12516

optimizing-sql-queries

jeremylongshore

This skill analyzes and optimizes SQL queries for improved performance. It identifies potential bottlenecks, suggests optimal indexes, and proposes query rewrites. Use this when the user mentions "optimize SQL query", "improve SQL performance", "SQL query optimization", "slow SQL query", or asks for help with "SQL indexing". The skill helps enhance database efficiency by analyzing query structure, recommending indexes, and reviewing execution plans.

5513

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

1,6851,428

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

1,2681,335

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

1,5421,149

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

1,357809

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

1,264728

pdf-to-markdown

aliceisjustplaying

Convert entire PDF documents to clean, structured Markdown for full context loading. Use this skill when the user wants to extract ALL text from a PDF into context (not grep/search), when discussing or analyzing PDF content in full, when the user mentions "load the whole PDF", "bring the PDF into context", "read the entire PDF", or when partial extraction/grepping would miss important context. This is the preferred method for PDF text extraction over page-by-page or grep approaches.

1,491684