Production Deployment Runbook
March 30, 2026 · View on GitHub
Quick Reference
Production URL: https://gharam.in
Hosting: Vercel
Database: Supabase (PostgreSQL)
CDN: Cloudinary
Monitoring: Sentry
Common Issues & Solutions
1. Database Connection Errors
Symptoms:
- "P1001: Can't reach database server"
- 500 errors on API routes
- Timeouts on database queries
Diagnosis:
# Test connection
curl https://gharam.in/api/health
# Check database status in Supabase dashboard
# Verify connection pooler is active
Solutions:
- Connection Pool Exhausted: Restart Supabase connection pooler in dashboard
- Wrong DATABASE_URL: Verify uses
?pgbouncer=truefor pooled connection - IP Restrictions: Check Supabase allowlist includes Vercel IPs
2. Razorpay Payment Failures
Symptoms:
- Payment button not loading
- "Invalid key_id" errors
- Payments stuck in "pending"
Diagnosis:
# Check Razorpay API status
curl https://api.razorpay.com/v1/payments -u rzp_live_XXX:secret
# Test webhook endpoint
curl -X POST https://gharam.in/api/webhooks/razorpay \
-H "Content-Type: application/json" \
-d '{"test": true}'
Solutions:
- Live Mode Not Active: Switch from test to live keys in Razorpay dashboard + env vars
- Webhook URL Wrong: Update webhook URL in Razorpay:
https://gharam.in/api/payments/webhook - Signature Mismatch: Verify
RAZORPAY_KEY_SECRETmatches dashboard
3. Image Upload Failures
Symptoms:
- 413 Payload Too Large
- Uploads timing out
- Images not displaying
Diagnosis:
# Test Cloudinary config
curl -X POST https://api.cloudinary.com/v1_1/YOUR_CLOUD_NAME/image/upload \
-F "file=@test.jpg" \
-F "api_key=YOUR_API_KEY" \
-F "timestamp=$(date +%s)" \
-F "signature=SIGNATURE"
Solutions:
- File Too Large: Enforce 5MB limit client-side, show clear error
- Wrong Cloud Name: Verify
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAMEin env - API Limits Exceeded: Check Cloudinary quota, upgrade plan if needed
4. Redis/Rate Limiting Issues
Symptoms:
- "429 Too Many Requests" on all users
- Rate limits not working (abuse possible)
- Connection timeouts to Redis
Diagnosis:
# Check Redis connectivity
curl https://gharam.in/api/health
# Test rate limit manually
for i in {1..15}; do
curl https://gharam.in/api/auth/login
done
Solutions:
- Redis Down: Check Upstash dashboard, restart if needed
- Wrong Credentials: Verify
UPSTASH_REDIS_REST_URLand token - Too Strict Limits: Temporarily increase limits in
src/lib/rateLimit.ts
5. Email Delivery Issues
Symptoms:
- Emails not arriving
- Emails in spam
- "Invalid API key" errors
Diagnosis:
# Test Resend API
curl https://api.resend.com/emails \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"noreply@gharam.in","to":"test@example.com","subject":"Test","html":"Test"}'
# Check SPF/DKIM records
dig txt gharam.in
dig txt _dmarc.gharam.in
Solutions:
- Domain Not Verified: Verify domain in Resend dashboard, add DNS records
- SPF/DKIM Missing: Add TXT records from Resend to DNS:
- SPF:
v=spf1 include:resend.com ~all - DKIM: Copy from Resend dashboard
- SPF:
- Wrong From Address: Use
noreply@gharam.in(verified domain)
6. Session/Authentication Issues
Symptoms:
- Users logged out randomly
- "Unauthorized" on all requests
- Session expires too quickly
Diagnosis:
# Check NextAuth config
curl -I https://gharam.in/api/auth/session
# Verify JWT secret is set
echo $NEXTAUTH_SECRET | wc -c # Should be >= 32 chars
Solutions:
- Wrong NEXTAUTH_URL: Must match production domain exactly
- Short Session: Increase
maxAgeinsrc/lib/auth.ts(currently 24h) - Cookie Issues: Check
secure: trueandsameSite: "lax"in cookies
7. Build/Deployment Failures
Symptoms:
- "Module not found" errors
- TypeScript compilation errors
- Deployment stuck
Diagnosis:
# Local build test
npm run build
# Check Vercel logs
vercel logs --prod
# Verify all env vars set
vercel env ls
Solutions:
- Missing Env Vars: Add all from
.env.production.exampleto Vercel dashboard - Prisma Client: Run
npx prisma generatebefore build (automatic in build script) - Out of Memory: Upgrade Vercel plan or optimize build
Emergency Procedures
Rollback to Previous Version
# Via Vercel CLI
vercel rollback
# Or via dashboard: Deployments → Previous deployment → "Promote to Production"
Take Site Offline (Maintenance Mode)
- Create
src/app/maintenance/page.tsx:
export default function Maintenance() {
return <div>We'll be back soon! Scheduled maintenance in progress.</div>
}
- Add redirect in
src/middleware.ts:
if (process.env.MAINTENANCE_MODE === "true") {
return NextResponse.redirect(new URL("/maintenance", req.url))
}
- Set
MAINTENANCE_MODE=truein Vercel env vars
Database Rollback
# Restore from Supabase backup
# 1. Go to Supabase dashboard → Database → Backups
# 2. Select backup point
# 3. Click "Restore"
# 4. Wait 5-10 minutes
# 5. Test with curl https://gharam.in/api/health
Escalation Contacts
| Issue | Contact | Response Time |
|---|---|---|
| Database down | Supabase Support (support@supabase.com) | 2-4 hours |
| Payment failures | Razorpay Support (support@razorpay.com) | 1-2 hours |
| Vercel deployment | Vercel Support (vercel.com/support) | 4-8 hours |
| Critical errors | Developer (your-email@example.com) | Immediate |
Monitoring & Alerts
Health Checks
- Endpoint:
https://gharam.in/api/health - Uptime Monitor: Set up UptimeRobot/Pingdom to ping every 5 min
- Alerts: Email + SMS on downtime
Sentry Alerts
- Critical Errors: Email immediately (payment, auth, database)
- Warning Errors: Daily digest
- Performance: Alert if API response > 2s
Database Alerts
- Connection Pool: Alert if > 80% utilization
- Query Performance: Alert if query > 5s
- Disk Space: Alert if > 80% full
Performance Optimization
Slow API Routes
- Check Sentry performance monitoring
- Add database indexes if missing
- Implement caching with Redis
- Optimize Prisma queries (use
selectinstead of fetching all fields)
High Memory Usage
- Check for memory leaks in long-running processes
- Optimize image sizes (use Cloudinary transformations)
- Upgrade Vercel plan if needed
Slow Page Loads
- Analyze with Vercel Analytics
- Optimize images (lazy loading, WebP format)
- Reduce bundle size (check
npm run analyze)
Backup & Recovery
Automated Backups
- Database: Supabase daily backups (7-day retention)
- Images: Cloudinary auto-backup
- Code: Git repository (GitHub)
Manual Backup
# Export database
pg_dump $DATABASE_URL > backup_$(date +%Y%m%d).sql
# Download from Supabase dashboard:
# Database → Backups → Download
Disaster Recovery Steps
- Restore database from latest backup (Supabase dashboard)
- Redeploy last known good version (Vercel rollback)
- Verify all services healthy (
/api/health) - Test critical flows (signup, login, booking)
- Notify users if data loss occurred
Security Incidents
Suspected Data Breach
- Immediate: Rotate all API keys and secrets
- Investigate: Check Sentry for suspicious errors, Vercel logs for unusual traffic
- Notify: Email affected users within 24 hours
- Fix: Patch vulnerability, deploy immediately
- Report: File incident report, consider security audit
DDoS Attack
- Verify: Check Vercel analytics for spike in traffic
- Mitigate: Enable Vercel DDoS protection (Pro plan)
- Block: Add IP ranges to blocklist if identified
- Monitor: Watch Sentry for elevated error rates
Routine Maintenance
Weekly
- Review Sentry errors (top 10)
- Check database query performance
- Monitor Cloudinary usage
- Review Razorpay transaction failures
Monthly
- Update dependencies (
npm outdated, thennpm update) - Review and optimize slow API routes
- Check disk space usage
- Test backup restoration
Quarterly
- Security audit (npm audit, Snyk)
- Performance review (Core Web Vitals)
- Cost optimization (review usage of all services)
- User feedback review
Last Updated: March 27, 2026
Version: 1.0.0