The Deployment That Breaks Production
It's 2 AM. You deployed 4 hours ago. Stripe webhooks are failing.
Your database migration didn't run. Users can't subscribe.
This is preventable. Here's the deployment checklist that catches it.
Before Every Deploy
# 1. Verify tests pass
npm test
# 2. Verify build succeeds
npm run build
# 3. Verify TypeScript (if not part of build)
npx tsc --noEmit
# 4. Check for known vulnerabilities
npm audit --audit-level=high
# 5. Verify environment variables are set in Vercel
vercel env ls
Database Migration Strategy
# CI/CD: run migrations BEFORE deploying new code
# This ensures DB schema is ready when new code starts
# .github/workflows/deploy.yml
jobs:
deploy:
steps:
- name: Run migrations
run: npx prisma migrate deploy # Production-safe
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
- name: Deploy to Vercel
run: vercel --prod
# Deploys AFTER migrations are complete
Stripe Webhook Verification
# After every deploy, verify webhooks are configured correctly
# In Stripe Dashboard -> Webhooks -> your endpoint
# Check: endpoint URL matches your current deployment URL
# Check: webhook secret in Vercel env matches Stripe dashboard
# Test: 'Send test webhook' and verify 200 response
# Most common webhook failures after deploy:
# 1. STRIPE_WEBHOOK_SECRET not updated after rotating
# 2. Endpoint URL still pointing to old deployment
# 3. Raw body not preserved (req.json() instead of req.text())
Feature Flags for Safe Deploys
// Deploy code behind a flag -- enable separately from deploy
import { get } from '@vercel/edge-config'
const newBillingEnabled = await get<boolean>('new-billing-flow')
if (newBillingEnabled) {
return <NewBillingFlow />
}
return <OldBillingFlow />
// Now you can:
// 1. Deploy code (flag off = old behavior)
// 2. Test in production with your own account
// 3. Enable flag for 10% of users
// 4. Monitor for errors
// 5. Roll out to 100%
Rollback Strategy
# Vercel: instant rollback to previous deployment
vercel rollback
# Or in Vercel dashboard: Deployments -> previous deploy -> 'Promote to Production'
# Database rollback: harder
# Prevention: additive-only migrations in production
# - Add columns, don't drop them
# - Add tables, don't remove them
# - Make columns nullable before removing
# (Destructive changes only after code no longer references the field)
Post-Deploy Smoke Test
#!/bin/bash
# scripts/smoke-test.sh
BASE_URL=${1:-https://yourapp.com}
# Check homepage
STATUS=$(curl -s -o /dev/null -w '%{http_code}' "$BASE_URL")
[ "$STATUS" -eq 200 ] && echo 'Homepage: OK' || echo "Homepage: FAIL ($STATUS)"
# Check API health
STATUS=$(curl -s -o /dev/null -w '%{http_code}' "$BASE_URL/api/health")
[ "$STATUS" -eq 200 ] && echo 'API: OK' || echo "API: FAIL ($STATUS)"
# Run after every production deploy
The Health Endpoint
// app/api/health/route.ts
import { db } from '@/lib/db'
export async function GET() {
try {
// Check DB connection
await db.$queryRaw`SELECT 1`
return Response.json({
status: 'ok',
timestamp: new Date().toISOString(),
version: process.env.VERCEL_GIT_COMMIT_SHA?.slice(0, 7) ?? 'dev'
})
} catch (error) {
return Response.json(
{ status: 'error', message: 'DB connection failed' },
{ status: 503 }
)
}
}
Pre-Configured Deploy Pipeline
The AI SaaS Starter Kit includes GitHub Actions CI/CD, health endpoint, smoke test script, and migration-before-deploy workflow.
$99 one-time at whoffagents.com
Top comments (0)