@intentsolutionsio/supabase-pack 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +73 -47
  3. package/package.json +4 -4
  4. package/skills/supabase-advanced-troubleshooting/SKILL.md +404 -200
  5. package/skills/supabase-advanced-troubleshooting/references/errors.md +11 -0
  6. package/skills/supabase-advanced-troubleshooting/references/evidence-collection-framework.md +34 -0
  7. package/skills/supabase-advanced-troubleshooting/references/examples.md +11 -0
  8. package/skills/supabase-advanced-troubleshooting/references/rls-edge-functions-realtime.md +363 -0
  9. package/skills/supabase-advanced-troubleshooting/references/systematic-isolation.md +56 -0
  10. package/skills/supabase-advanced-troubleshooting/references/timing-analysis.md +35 -0
  11. package/skills/supabase-architecture-variants/SKILL.md +395 -216
  12. package/skills/supabase-architecture-variants/references/errors.md +11 -0
  13. package/skills/supabase-architecture-variants/references/examples.md +12 -0
  14. package/skills/supabase-architecture-variants/references/serverless-and-multi-tenant.md +251 -0
  15. package/skills/supabase-architecture-variants/references/variant-a-monolith-(simple).md +44 -0
  16. package/skills/supabase-architecture-variants/references/variant-b-service-layer-(moderate).md +72 -0
  17. package/skills/supabase-architecture-variants/references/variant-c-microservice-(complex).md +81 -0
  18. package/skills/supabase-auth-storage-realtime-core/SKILL.md +471 -37
  19. package/skills/supabase-ci-integration/SKILL.md +315 -67
  20. package/skills/supabase-ci-integration/references/errors.md +10 -0
  21. package/skills/supabase-ci-integration/references/examples.md +36 -0
  22. package/skills/supabase-ci-integration/references/implementation.md +54 -0
  23. package/skills/supabase-common-errors/SKILL.md +320 -62
  24. package/skills/supabase-common-errors/references/errors.md +53 -0
  25. package/skills/supabase-common-errors/references/examples.md +23 -0
  26. package/skills/supabase-cost-tuning/SKILL.md +365 -131
  27. package/skills/supabase-cost-tuning/references/cost-estimation.md +34 -0
  28. package/skills/supabase-cost-tuning/references/cost-reduction-strategies.md +40 -0
  29. package/skills/supabase-cost-tuning/references/errors.md +11 -0
  30. package/skills/supabase-cost-tuning/references/examples.md +15 -0
  31. package/skills/supabase-data-handling/SKILL.md +378 -145
  32. package/skills/supabase-data-handling/references/errors.md +11 -0
  33. package/skills/supabase-data-handling/references/examples.md +27 -0
  34. package/skills/supabase-data-handling/references/implementation.md +223 -0
  35. package/skills/supabase-data-handling/references/retention-and-backup.md +221 -0
  36. package/skills/supabase-debug-bundle/SKILL.md +267 -73
  37. package/skills/supabase-debug-bundle/references/errors.md +12 -0
  38. package/skills/supabase-debug-bundle/references/examples.md +24 -0
  39. package/skills/supabase-debug-bundle/references/implementation.md +54 -0
  40. package/skills/supabase-deploy-integration/SKILL.md +258 -147
  41. package/skills/supabase-deploy-integration/references/errors.md +11 -0
  42. package/skills/supabase-deploy-integration/references/examples.md +21 -0
  43. package/skills/supabase-deploy-integration/references/google-cloud-run.md +36 -0
  44. package/skills/supabase-deploy-integration/references/vercel-deployment.md +35 -0
  45. package/skills/supabase-enterprise-rbac/SKILL.md +327 -160
  46. package/skills/supabase-enterprise-rbac/references/api-scoping-and-enforcement.md +255 -0
  47. package/skills/supabase-enterprise-rbac/references/errors.md +11 -0
  48. package/skills/supabase-enterprise-rbac/references/examples.md +12 -0
  49. package/skills/supabase-enterprise-rbac/references/role-implementation.md +33 -0
  50. package/skills/supabase-enterprise-rbac/references/sso-integration.md +35 -0
  51. package/skills/supabase-hello-world/SKILL.md +160 -54
  52. package/skills/supabase-incident-runbook/SKILL.md +453 -131
  53. package/skills/supabase-incident-runbook/references/errors.md +11 -0
  54. package/skills/supabase-incident-runbook/references/examples.md +10 -0
  55. package/skills/supabase-incident-runbook/references/immediate-actions-by-error-type.md +41 -0
  56. package/skills/supabase-install-auth/SKILL.md +186 -50
  57. package/skills/supabase-install-auth/references/examples.md +102 -0
  58. package/skills/supabase-known-pitfalls/SKILL.md +411 -241
  59. package/skills/supabase-known-pitfalls/references/errors.md +11 -0
  60. package/skills/supabase-known-pitfalls/references/examples.md +12 -0
  61. package/skills/supabase-load-scale/SKILL.md +346 -217
  62. package/skills/supabase-load-scale/references/capacity-planning.md +47 -0
  63. package/skills/supabase-load-scale/references/errors.md +11 -0
  64. package/skills/supabase-load-scale/references/examples.md +26 -0
  65. package/skills/supabase-load-scale/references/load-testing-with-k6.md +59 -0
  66. package/skills/supabase-load-scale/references/scaling-patterns.md +65 -0
  67. package/skills/supabase-load-scale/references/table-partitioning.md +263 -0
  68. package/skills/supabase-local-dev-loop/SKILL.md +272 -73
  69. package/skills/supabase-local-dev-loop/references/errors.md +11 -0
  70. package/skills/supabase-local-dev-loop/references/examples.md +21 -0
  71. package/skills/supabase-local-dev-loop/references/implementation.md +60 -0
  72. package/skills/supabase-migration-deep-dive/SKILL.md +338 -177
  73. package/skills/supabase-migration-deep-dive/references/backfill-versioning-rollback.md +258 -0
  74. package/skills/supabase-migration-deep-dive/references/errors.md +11 -0
  75. package/skills/supabase-migration-deep-dive/references/examples.md +12 -0
  76. package/skills/supabase-migration-deep-dive/references/implementation-plan.md +80 -0
  77. package/skills/supabase-migration-deep-dive/references/pre-migration-assessment.md +39 -0
  78. package/skills/supabase-multi-env-setup/SKILL.md +393 -152
  79. package/skills/supabase-multi-env-setup/references/configuration-structure.md +59 -0
  80. package/skills/supabase-multi-env-setup/references/errors.md +11 -0
  81. package/skills/supabase-multi-env-setup/references/examples.md +11 -0
  82. package/skills/supabase-observability/SKILL.md +318 -196
  83. package/skills/supabase-observability/references/alert-configuration.md +40 -0
  84. package/skills/supabase-observability/references/errors.md +11 -0
  85. package/skills/supabase-observability/references/examples.md +13 -0
  86. package/skills/supabase-observability/references/metrics-collection.md +65 -0
  87. package/skills/supabase-performance-tuning/SKILL.md +304 -160
  88. package/skills/supabase-performance-tuning/references/caching-strategy.md +49 -0
  89. package/skills/supabase-performance-tuning/references/errors.md +11 -0
  90. package/skills/supabase-performance-tuning/references/examples.md +13 -0
  91. package/skills/supabase-policy-guardrails/SKILL.md +248 -221
  92. package/skills/supabase-policy-guardrails/references/ci-cost-security.md +484 -0
  93. package/skills/supabase-policy-guardrails/references/errors.md +11 -0
  94. package/skills/supabase-policy-guardrails/references/eslint-rules.md +46 -0
  95. package/skills/supabase-policy-guardrails/references/examples.md +10 -0
  96. package/skills/supabase-prod-checklist/SKILL.md +474 -84
  97. package/skills/supabase-prod-checklist/references/errors.md +63 -0
  98. package/skills/supabase-prod-checklist/references/examples.md +153 -0
  99. package/skills/supabase-prod-checklist/references/implementation.md +113 -0
  100. package/skills/supabase-rate-limits/SKILL.md +311 -98
  101. package/skills/supabase-rate-limits/references/errors.md +11 -0
  102. package/skills/supabase-rate-limits/references/examples.md +46 -0
  103. package/skills/supabase-rate-limits/references/implementation.md +66 -0
  104. package/skills/supabase-reference-architecture/SKILL.md +249 -182
  105. package/skills/supabase-reference-architecture/references/errors.md +29 -0
  106. package/skills/supabase-reference-architecture/references/examples.md +116 -0
  107. package/skills/supabase-reference-architecture/references/key-components.md +244 -0
  108. package/skills/supabase-reference-architecture/references/project-structure.md +109 -0
  109. package/skills/supabase-reliability-patterns/SKILL.md +229 -234
  110. package/skills/supabase-reliability-patterns/references/circuit-breaker.md +36 -0
  111. package/skills/supabase-reliability-patterns/references/dead-letter-queue.md +48 -0
  112. package/skills/supabase-reliability-patterns/references/errors.md +11 -0
  113. package/skills/supabase-reliability-patterns/references/examples.md +11 -0
  114. package/skills/supabase-reliability-patterns/references/idempotency-keys.md +36 -0
  115. package/skills/supabase-reliability-patterns/references/offline-degradation-health-dualwrite.md +489 -0
  116. package/skills/supabase-schema-from-requirements/SKILL.md +373 -34
  117. package/skills/supabase-sdk-patterns/SKILL.md +388 -99
  118. package/skills/supabase-sdk-patterns/references/errors.md +11 -0
  119. package/skills/supabase-sdk-patterns/references/examples.md +45 -0
  120. package/skills/supabase-sdk-patterns/references/implementation.md +67 -0
  121. package/skills/supabase-security-basics/SKILL.md +282 -102
  122. package/skills/supabase-security-basics/references/errors.md +10 -0
  123. package/skills/supabase-security-basics/references/examples.md +70 -0
  124. package/skills/supabase-security-basics/references/implementation.md +39 -0
  125. package/skills/supabase-upgrade-migration/SKILL.md +248 -66
  126. package/skills/supabase-upgrade-migration/references/errors.md +10 -0
  127. package/skills/supabase-upgrade-migration/references/examples.md +51 -0
  128. package/skills/supabase-upgrade-migration/references/implementation.md +29 -0
  129. package/skills/supabase-webhooks-events/SKILL.md +412 -138
  130. package/skills/supabase-webhooks-events/references/errors.md +55 -0
  131. package/skills/supabase-webhooks-events/references/event-handler-pattern.md +106 -0
  132. package/skills/supabase-webhooks-events/references/examples.md +133 -0
  133. package/skills/supabase-webhooks-events/references/signature-verification.md +165 -0
@@ -1,119 +1,509 @@
1
1
  ---
2
2
  name: supabase-prod-checklist
3
- description: |
4
- Execute Supabase production deployment checklist and rollback procedures.
5
- Use when deploying Supabase integrations to production, preparing for launch,
6
- or implementing go-live procedures.
7
- Trigger with phrases like "supabase production", "deploy supabase",
8
- "supabase go-live", "supabase launch checklist".
9
- allowed-tools: Read, Bash(kubectl:*), Bash(curl:*), Grep
3
+ description: 'Execute Supabase production deployment checklist covering RLS, key hygiene,
4
+
5
+ connection pooling, backups, monitoring, Edge Functions, and Storage policies.
6
+
7
+ Use when deploying to production, preparing for launch,
8
+
9
+ or auditing a live Supabase project for security and performance gaps.
10
+
11
+ Trigger with "supabase production", "supabase go-live",
12
+
13
+ "supabase launch checklist", "supabase prod ready", "deploy supabase",
14
+
15
+ "supabase production readiness".
16
+
17
+ '
18
+ allowed-tools: Read, Write, Edit, Bash(npx supabase:*), Bash(curl:*), Grep
10
19
  version: 1.0.0
11
20
  license: MIT
12
21
  author: Jeremy Longshore <jeremy@intentsolutions.io>
22
+ tags:
23
+ - saas
24
+ - supabase
25
+ - deployment
26
+ - production
27
+ - security
28
+ - rls
29
+ compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
13
30
  ---
14
-
15
- # Supabase Production Checklist
31
+ # Supabase Production Deployment Checklist
16
32
 
17
33
  ## Overview
18
- Complete checklist for deploying Supabase integrations to production.
34
+
35
+ 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](https://supabase.com/docs/guides/deployment/going-into-prod).
19
36
 
20
37
  ## Prerequisites
21
- - Staging environment tested and verified
22
- - Production API keys available
23
- - Deployment pipeline configured
24
- - Monitoring and alerting ready
38
+
39
+ - Supabase project on Pro plan or higher (required for PITR, network restrictions)
40
+ - Separate production project (never share dev/prod)
41
+ - `@supabase/supabase-js` v2+ installed
42
+ - Supabase CLI installed (`npx supabase --version`)
43
+ - Domain and DNS configured for custom domain
44
+ - Deployment platform ready (Vercel, Netlify, Cloudflare, etc.)
25
45
 
26
46
  ## Instructions
27
47
 
28
- ### Step 1: Pre-Deployment Configuration
29
- - [ ] Production API keys in secure vault
30
- - [ ] Environment variables set in deployment platform
31
- - [ ] API key scopes are minimal (least privilege)
32
- - [ ] Webhook endpoints configured with HTTPS
33
- - [ ] Webhook secrets stored securely
34
-
35
- ### Step 2: Code Quality Verification
36
- - [ ] All tests passing (`npm test`)
37
- - [ ] No hardcoded credentials
38
- - [ ] Error handling covers all Supabase error types
39
- - [ ] Rate limiting/backoff implemented
40
- - [ ] Logging is production-appropriate
41
-
42
- ### Step 3: Infrastructure Setup
43
- - [ ] Health check endpoint includes Supabase connectivity
44
- - [ ] Monitoring/alerting configured
45
- - [ ] Circuit breaker pattern implemented
46
- - [ ] Graceful degradation configured
47
-
48
- ### Step 4: Documentation Requirements
49
- - [ ] Incident runbook created
50
- - [ ] Key rotation procedure documented
51
- - [ ] Rollback procedure documented
52
- - [ ] On-call escalation path defined
53
-
54
- ### Step 5: Deploy with Gradual Rollout
48
+ ### Step 1: Enforce Row Level Security on ALL Tables
49
+
50
+ RLS is the single most critical production requirement. Without it, any client with your anon key can read/write every row.
51
+
52
+ ```sql
53
+ -- Audit: find tables WITHOUT RLS enabled
54
+ -- This query MUST return zero rows before going live
55
+ SELECT schemaname, tablename, rowsecurity
56
+ FROM pg_tables
57
+ WHERE schemaname = 'public' AND rowsecurity = false;
58
+ ```
59
+
60
+ ```sql
61
+ -- Enable RLS on a table
62
+ ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
63
+
64
+ -- Create a basic read policy (authenticated users see own rows)
65
+ CREATE POLICY "Users can view own profile"
66
+ ON public.profiles
67
+ FOR SELECT
68
+ USING (auth.uid() = user_id);
69
+
70
+ -- Create an insert policy
71
+ CREATE POLICY "Users can insert own profile"
72
+ ON public.profiles
73
+ FOR INSERT
74
+ WITH CHECK (auth.uid() = user_id);
75
+
76
+ -- Create an update policy
77
+ CREATE POLICY "Users can update own profile"
78
+ ON public.profiles
79
+ FOR UPDATE
80
+ USING (auth.uid() = user_id)
81
+ WITH CHECK (auth.uid() = user_id);
82
+ ```
83
+
84
+ - [ ] RLS enabled on every public table (zero rows from audit query above)
85
+ - [ ] SELECT, INSERT, UPDATE, DELETE policies defined for each table
86
+ - [ ] Policies tested with both authenticated and anonymous roles
87
+ - [ ] No tables use `USING (true)` without intent (public read tables only)
88
+
89
+ ### Step 2: Enforce Key Separation — Anon vs Service Role
90
+
91
+ The `anon` key is safe for client-side code. The `service_role` key bypasses RLS entirely and must never leave server-side environments.
92
+
93
+ ```typescript
94
+ // Client-side — ONLY use anon key
95
+ import { createClient } from '@supabase/supabase-js';
96
+
97
+ const supabase = createClient(
98
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
99
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! // Safe for browsers
100
+ );
101
+ ```
102
+
103
+ ```typescript
104
+ // Server-side only — service_role key (API routes, webhooks, cron jobs)
105
+ import { createClient } from '@supabase/supabase-js';
106
+
107
+ const supabaseAdmin = createClient(
108
+ process.env.SUPABASE_URL!,
109
+ process.env.SUPABASE_SERVICE_ROLE_KEY!, // NEVER expose to client
110
+ { auth: { autoRefreshToken: false, persistSession: false } }
111
+ );
112
+ ```
113
+
114
+ - [ ] Anon key used in all client-side code (`NEXT_PUBLIC_` prefix)
115
+ - [ ] Service role key used only in server-side code (API routes, Edge Functions)
116
+ - [ ] Service role key not in any client bundle (verify with `grep -r "service_role" dist/`)
117
+ - [ ] Database password changed from the auto-generated default
118
+
119
+ ### Step 3: Configure Connection Pooling (Supavisor)
120
+
121
+ 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.
122
+
123
+ ```
124
+ # Direct connection (migrations, admin tasks only)
125
+ postgresql://postgres:[PASSWORD]@db.[REF].supabase.co:5432/postgres
126
+
127
+ # Pooled connection via Supavisor (application code — USE THIS)
128
+ # Port 6543 = Supavisor pooler (vs 5432 direct)
129
+ postgresql://postgres.[REF]:[PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
130
+ ```
131
+
132
+ ```typescript
133
+ // For serverless environments — use pooled connection
134
+ const supabase = createClient(
135
+ process.env.SUPABASE_URL!,
136
+ process.env.SUPABASE_ANON_KEY!,
137
+ {
138
+ db: { schema: 'public' },
139
+ // Supavisor handles pooling at port 6543
140
+ // No need to configure pgBouncer settings in the client
141
+ }
142
+ );
143
+ ```
144
+
145
+ - [ ] Application code uses pooled connection string (port 6543)
146
+ - [ ] Direct connection reserved for migrations and admin tasks only
147
+ - [ ] Connection string in deployment platform env vars (not hardcoded)
148
+ - [ ] Verified pool mode: `transaction` for serverless, `session` for long-lived connections
149
+
150
+ ### Step 4: Enable Database Backups
151
+
152
+ Supabase provides automatic daily backups on Pro plan. Point-in-time recovery (PITR) enables granular restores.
153
+
154
+ - [ ] Automatic daily backups enabled (Pro plan — verify in Dashboard > Database > Backups)
155
+ - [ ] Point-in-time recovery configured (Dashboard > Database > Backups > PITR)
156
+ - [ ] Tested restore procedure on a staging project (do not skip this)
157
+ - [ ] Migration files committed to version control (`supabase/migrations/` directory)
158
+ - [ ] `npx supabase db push` tested against a fresh project to verify migrations replay cleanly
159
+
160
+ ### Step 5: Configure Network Restrictions
161
+
162
+ Restrict database access to known IP addresses. This prevents unauthorized direct database connections even if credentials leak.
163
+
164
+ - [ ] IP allowlist configured (Dashboard > Database > Network Restrictions)
165
+ - [ ] Only deployment platform IPs and team office IPs are allowed
166
+ - [ ] Verified that application still connects after restrictions applied
167
+ - [ ] Documented which IPs are allowed and why
168
+
169
+ ### Step 6: Configure Custom Domain
170
+
171
+ A custom domain replaces the default `*.supabase.co` URLs with your brand domain for API and auth endpoints.
172
+
173
+ - [ ] Custom domain configured (Dashboard > Settings > Custom Domains)
174
+ - [ ] DNS CNAME record added and verified
175
+ - [ ] SSL certificate provisioned and active
176
+ - [ ] Application code updated to use custom domain URL
177
+ - [ ] OAuth redirect URLs updated to use custom domain
178
+
179
+ ### Step 7: Customize Auth Email Templates
180
+
181
+ Default Supabase auth emails show generic branding. Customize them so users see your domain and brand.
182
+
183
+ - [ ] Confirmation email template customized (Dashboard > Auth > Email Templates)
184
+ - [ ] Password reset email template customized
185
+ - [ ] Magic link email template customized
186
+ - [ ] Invite email template customized
187
+ - [ ] Custom SMTP configured (Dashboard > Auth > SMTP Settings) — avoids rate limits and improves deliverability
188
+ - [ ] Email confirmation enabled (Dashboard > Auth > Settings)
189
+ - [ ] OAuth redirect URLs restricted to production domains only
190
+ - [ ] Unused auth providers disabled
191
+
192
+ ### Step 8: Understand Rate Limits Per Tier
193
+
194
+ Supabase enforces rate limits that vary by plan. Hitting these in production causes 429 errors.
195
+
196
+ | Resource | Free | Pro | Team |
197
+ |----------|------|-----|------|
198
+ | API requests | 500/min | 1,000/min | 5,000/min |
199
+ | Auth emails | 4/hour | 30/hour | 100/hour |
200
+ | Realtime connections | 200 concurrent | 500 concurrent | 2,000 concurrent |
201
+ | Edge Function invocations | 500K/month | 2M/month | 5M/month |
202
+ | Storage bandwidth | 2GB/month | 250GB/month | Custom |
203
+ | Database size | 500MB | 8GB | 50GB |
204
+
205
+ - [ ] Rate limits documented for your plan tier
206
+ - [ ] Client-side retry logic with exponential backoff for 429 responses
207
+ - [ ] Auth email rate limits understood (use custom SMTP to increase)
208
+ - [ ] Realtime connection limits planned for expected concurrent users
209
+
210
+ ### Step 9: Review Monitoring Dashboards
211
+
212
+ Supabase provides built-in monitoring. Review these before launch to establish baselines.
213
+
214
+ ```typescript
215
+ // Health check endpoint — deploy this to your application
216
+ import { createClient } from '@supabase/supabase-js';
217
+
218
+ const supabase = createClient(
219
+ process.env.SUPABASE_URL!,
220
+ process.env.SUPABASE_ANON_KEY!
221
+ );
222
+
223
+ export async function GET() {
224
+ const start = Date.now();
225
+ const { data, error } = await supabase
226
+ .from('_health_check') // Create a small table for this
227
+ .select('id')
228
+ .limit(1);
229
+
230
+ const latency = Date.now() - start;
231
+
232
+ return Response.json({
233
+ status: error ? 'unhealthy' : 'healthy',
234
+ latency_ms: latency,
235
+ timestamp: new Date().toISOString(),
236
+ supabase_reachable: !error,
237
+ }, { status: error ? 503 : 200 });
238
+ }
239
+ ```
240
+
241
+ - [ ] Dashboard > Reports reviewed (API requests, auth, storage, realtime)
242
+ - [ ] Dashboard > Logs > API checked for error patterns
243
+ - [ ] Dashboard > Database > Performance Advisor reviewed and recommendations applied
244
+ - [ ] Health check endpoint deployed and monitored (uptime service)
245
+ - [ ] Error tracking configured (Sentry, LogRocket, etc.)
246
+ - [ ] Alerts set for: error rate spikes, high latency, connection pool exhaustion
247
+
248
+ ### Step 10: Deploy Edge Functions with Proper Env Vars
249
+
250
+ Edge Functions run on Deno Deploy. Environment variables must be set via the Supabase CLI or Dashboard, not hardcoded.
251
+
252
+ ```bash
253
+ # Set secrets for Edge Functions
254
+ npx supabase secrets set STRIPE_SECRET_KEY=sk_live_...
255
+ npx supabase secrets set RESEND_API_KEY=re_...
256
+
257
+ # List current secrets
258
+ npx supabase secrets list
259
+
260
+ # Deploy all Edge Functions
261
+ npx supabase functions deploy
262
+
263
+ # Deploy a specific function
264
+ npx supabase functions deploy process-webhook
265
+ ```
266
+
267
+ ```typescript
268
+ // supabase/functions/process-webhook/index.ts
269
+ import { createClient } from '@supabase/supabase-js';
270
+
271
+ Deno.serve(async (req) => {
272
+ const supabase = createClient(
273
+ Deno.env.get('SUPABASE_URL')!,
274
+ Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! // Available automatically
275
+ );
276
+
277
+ const body = await req.json();
278
+ // Process webhook payload...
279
+
280
+ return new Response(JSON.stringify({ received: true }), {
281
+ headers: { 'Content-Type': 'application/json' },
282
+ });
283
+ });
284
+ ```
285
+
286
+ - [ ] All Edge Functions deployed to production (`npx supabase functions deploy`)
287
+ - [ ] Environment secrets set via `npx supabase secrets set` (not hardcoded)
288
+ - [ ] `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY` available automatically (no need to set)
289
+ - [ ] Edge Functions tested with `npx supabase functions serve` locally before deploying
290
+ - [ ] CORS headers configured for Edge Functions that receive browser requests
291
+
292
+ ### Step 11: Verify Storage Bucket Policies
293
+
294
+ Storage buckets need explicit policies, similar to RLS on tables. Without policies, buckets are inaccessible (default deny).
295
+
296
+ ```sql
297
+ -- Check storage bucket configurations
298
+ SELECT id, name, public, file_size_limit, allowed_mime_types
299
+ FROM storage.buckets;
300
+
301
+ -- Check existing storage policies
302
+ SELECT policyname, tablename, cmd, qual
303
+ FROM pg_policies
304
+ WHERE schemaname = 'storage';
305
+ ```
306
+
307
+ ```sql
308
+ -- Example: Allow authenticated users to upload to their own folder
309
+ CREATE POLICY "Users can upload own files"
310
+ ON storage.objects
311
+ FOR INSERT
312
+ WITH CHECK (
313
+ bucket_id = 'avatars'
314
+ AND auth.uid()::text = (storage.foldername(name))[1]
315
+ );
316
+
317
+ -- Example: Allow public read access to a bucket
318
+ CREATE POLICY "Public read access"
319
+ ON storage.objects
320
+ FOR SELECT
321
+ USING (bucket_id = 'public-assets');
322
+ ```
323
+
324
+ - [ ] Each bucket has explicit SELECT/INSERT/UPDATE/DELETE policies
325
+ - [ ] Public buckets are intentionally public (not accidentally open)
326
+ - [ ] File size limits set per bucket (`file_size_limit` in bucket config)
327
+ - [ ] Allowed MIME types restricted per bucket (`allowed_mime_types`)
328
+ - [ ] User upload paths scoped to `auth.uid()` to prevent overwrites
329
+
330
+ ### Step 12: Add Database Indexes on Frequently Queried Columns
331
+
332
+ Missing indexes are the leading cause of slow queries after launch. Add indexes on foreign keys, filter columns, and sort columns.
333
+
334
+ ```sql
335
+ -- Find missing indexes on foreign keys
336
+ SELECT
337
+ tc.table_name, kcu.column_name,
338
+ CASE WHEN i.indexname IS NULL THEN '** MISSING INDEX **' ELSE i.indexname END AS index_status
339
+ FROM information_schema.table_constraints tc
340
+ JOIN information_schema.key_column_usage kcu
341
+ ON tc.constraint_name = kcu.constraint_name
342
+ LEFT JOIN pg_indexes i
343
+ ON i.tablename = tc.table_name
344
+ AND i.indexdef LIKE '%' || kcu.column_name || '%'
345
+ WHERE tc.constraint_type = 'FOREIGN KEY'
346
+ AND tc.table_schema = 'public';
347
+
348
+ -- Find slow queries (requires pg_stat_statements extension)
349
+ CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
350
+
351
+ SELECT query, calls, mean_exec_time::numeric(10,2) AS avg_ms,
352
+ total_exec_time::numeric(10,2) AS total_ms
353
+ FROM pg_stat_statements
354
+ ORDER BY mean_exec_time DESC
355
+ LIMIT 10;
356
+
357
+ -- Check table bloat (dead tuples from updates/deletes)
358
+ SELECT relname, n_live_tup, n_dead_tup,
359
+ round(n_dead_tup::numeric / greatest(n_live_tup, 1) * 100, 1) AS dead_pct
360
+ FROM pg_stat_user_tables
361
+ WHERE n_dead_tup > 1000
362
+ ORDER BY n_dead_tup DESC;
363
+ ```
364
+
365
+ ```sql
366
+ -- Create indexes on commonly filtered columns
367
+ CREATE INDEX idx_profiles_user_id ON public.profiles(user_id);
368
+ CREATE INDEX idx_orders_created_at ON public.orders(created_at DESC);
369
+ CREATE INDEX idx_posts_status ON public.posts(status) WHERE status = 'published'; -- Partial index
370
+
371
+ -- Set query timeout for the authenticated role
372
+ ALTER ROLE authenticated SET statement_timeout = '10s';
373
+ ```
374
+
375
+ - [ ] Indexes on all foreign key columns
376
+ - [ ] Indexes on columns used in WHERE, ORDER BY, and JOIN clauses
377
+ - [ ] `pg_stat_statements` enabled for ongoing query monitoring
378
+ - [ ] Performance Advisor reviewed (Dashboard > Database > Performance)
379
+ - [ ] `statement_timeout` set for authenticated role to prevent runaway queries
380
+ - [ ] Table bloat checked — VACUUM if dead tuple percentage > 10%
381
+
382
+ ### Step 13: Apply Migrations with `npx supabase db push`
383
+
384
+ All schema changes must go through migration files, never manual Dashboard edits in production.
385
+
55
386
  ```bash
56
- # Pre-flight checks
57
- curl -f https://staging.example.com/health
58
- curl -s https://status.supabase.com
387
+ # Generate a migration from local changes
388
+ npx supabase db diff --use-migra -f add_indexes
389
+
390
+ # Apply migrations to production (linked project)
391
+ npx supabase db push
392
+
393
+ # Verify migration history
394
+ npx supabase migration list
395
+
396
+ # If a migration fails, create a rollback
397
+ npx supabase migration new rollback_bad_change
398
+ ```
399
+
400
+ - [ ] All schema changes in `supabase/migrations/` directory (version controlled)
401
+ - [ ] `npx supabase db push` tested against a fresh project
402
+ - [ ] Migration history matches between local and remote (`npx supabase migration list`)
403
+ - [ ] Rollback migration prepared for risky schema changes
404
+ - [ ] No manual schema edits in production Dashboard
59
405
 
60
- # Gradual rollout - start with canary (10%)
61
- kubectl apply -f k8s/production.yaml
62
- kubectl set image deployment/supabase-integration app=image:new --record
63
- kubectl rollout pause deployment/supabase-integration
406
+ ### Step 14: Pre-Launch Final Verification
64
407
 
65
- # Monitor canary traffic for 10 minutes
66
- sleep 600
67
- # Check error rates and latency before continuing
408
+ ```bash
409
+ # Verify RLS status one final time
410
+ npx supabase inspect db table-sizes --linked
68
411
 
69
- # If healthy, continue rollout to 50%
70
- kubectl rollout resume deployment/supabase-integration
71
- kubectl rollout pause deployment/supabase-integration
72
- sleep 300
412
+ # Check that the project is linked to production
413
+ npx supabase status
73
414
 
74
- # Complete rollout to 100%
75
- kubectl rollout resume deployment/supabase-integration
76
- kubectl rollout status deployment/supabase-integration
415
+ # Verify connection string works
416
+ npx supabase db ping --linked
77
417
  ```
78
418
 
419
+ - [ ] CORS settings match production domain (Dashboard > API > CORS)
420
+ - [ ] Environment variables set correctly in deployment platform
421
+ - [ ] Realtime enabled only on tables that need it (reduces connection usage)
422
+ - [ ] Webhook endpoints registered and tested
423
+ - [ ] Load test completed on staging (see `supabase-load-scale`)
424
+ - [ ] SSL enforcement enabled (Dashboard > Database > Settings > SSL)
425
+ - [ ] DNS and custom domain verified end-to-end
426
+
79
427
  ## Output
80
- - Deployed Supabase integration
81
- - Health checks passing
82
- - Monitoring active
83
- - Rollback procedure documented
428
+
429
+ - All 14 checklist sections verified with zero unchecked items
430
+ - RLS enforced on every public table with tested policies
431
+ - Key separation verified (anon client-side, service_role server-side only)
432
+ - Connection pooling via Supavisor (port 6543) for all application code
433
+ - Backups, PITR, monitoring, Edge Functions, Storage policies, indexes all verified
434
+ - Migrations applied cleanly via `npx supabase db push`
84
435
 
85
436
  ## Error Handling
86
- | Alert | Condition | Severity |
87
- |-------|-----------|----------|
88
- | API Down | 5xx errors > 10/min | P1 |
89
- | High Latency | p99 > 5000ms | P2 |
90
- | Rate Limited | 429 errors > 5/min | P2 |
91
- | Auth Failures | 401/403 errors > 0 | P1 |
437
+
438
+ | Issue | Cause | Solution |
439
+ |-------|-------|----------|
440
+ | `403 Forbidden` on all API calls | RLS enabled but no policies created | Add SELECT/INSERT/UPDATE/DELETE policies for each role |
441
+ | `429 Too Many Requests` | Plan rate limit exceeded | Upgrade plan or implement client-side backoff with retry |
442
+ | Connection timeout under load | Using direct connection in serverless | Switch to pooled connection string (port 6543) |
443
+ | Auth emails not delivered | Default SMTP rate-limited | Configure custom SMTP provider (SendGrid, Resend, Postmark) |
444
+ | `PGRST301` permission denied | Service role key used where anon expected | Check client initialization — use anon key for client-side |
445
+ | Edge Function cold starts | First invocation after idle period | Pre-warm with scheduled pings or accept ~200ms cold start |
446
+ | Storage upload fails | Missing bucket policy or size limit exceeded | Add INSERT policy and check `file_size_limit` on bucket |
447
+ | Slow queries after launch | Missing indexes on filter/join columns | Run Performance Advisor and add indexes per Step 12 |
448
+ | Migration conflicts | Manual Dashboard edits diverged from migration files | Run `npx supabase db diff` to capture drift, then commit |
92
449
 
93
450
  ## Examples
94
451
 
95
- ### Health Check Implementation
452
+ ### Client Setup (Next.js)
453
+
96
454
  ```typescript
97
- async function healthCheck(): Promise<{ status: string; supabase: any }> {
98
- const start = Date.now();
99
- try {
100
- await supabaseClient.ping();
101
- return { status: 'healthy', supabase: { connected: true, latencyMs: Date.now() - start } };
102
- } catch (error) {
103
- return { status: 'degraded', supabase: { connected: false, latencyMs: Date.now() - start } };
104
- }
105
- }
455
+ // lib/supabase/client.ts browser (anon key)
456
+ import { createClient } from '@supabase/supabase-js';
457
+ export const supabase = createClient<Database>(
458
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
459
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
460
+ );
461
+
462
+ // lib/supabase/server.ts — server only (service role)
463
+ export const supabaseAdmin = createClient<Database>(
464
+ process.env.SUPABASE_URL!,
465
+ process.env.SUPABASE_SERVICE_ROLE_KEY!,
466
+ { auth: { autoRefreshToken: false, persistSession: false } }
467
+ );
468
+ ```
469
+
470
+ ### RLS Policy Pattern
471
+
472
+ ```sql
473
+ ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY;
474
+ CREATE POLICY "Public read published" ON public.posts
475
+ FOR SELECT USING (status = 'published');
476
+ CREATE POLICY "Authors manage own" ON public.posts
477
+ FOR ALL USING (auth.uid() = author_id)
478
+ WITH CHECK (auth.uid() = author_id);
106
479
  ```
107
480
 
108
- ### Immediate Rollback
481
+ ### Rollback
482
+
109
483
  ```bash
110
- kubectl rollout undo deployment/supabase-integration
111
- kubectl rollout status deployment/supabase-integration
484
+ npx supabase migration new rollback_bad_change # Create reversal SQL
485
+ npx supabase db push # Apply rollback
486
+ # For data: Dashboard > Database > Backups > PITR
487
+ # For app: vercel rollback / netlify deploy --prod
112
488
  ```
113
489
 
490
+ For complete examples including health checks, storage policies, and Edge Functions, see [examples.md](references/examples.md).
491
+
114
492
  ## Resources
115
- - [Supabase Status](https://status.supabase.com)
116
- - [Supabase Support](https://supabase.com/docs/support)
493
+
494
+ - [Going to Production](https://supabase.com/docs/guides/deployment/going-into-prod) — Official production checklist
495
+ - [Maturity Model](https://supabase.com/docs/guides/deployment/maturity-model) — Project lifecycle stages
496
+ - [Shared Responsibility Model](https://supabase.com/docs/guides/deployment/shared-responsibility-model) — What Supabase manages vs. what you manage
497
+ - [Performance Advisor](https://supabase.com/docs/guides/database/inspect) — Built-in query analysis
498
+ - [Connection Pooling](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler) — Supavisor configuration
499
+ - [RLS Guide](https://supabase.com/docs/guides/database/postgres/row-level-security) — Policy patterns and examples
500
+ - [Edge Functions](https://supabase.com/docs/guides/functions) — Serverless Deno functions
501
+ - [Storage](https://supabase.com/docs/guides/storage) — File storage with policies
502
+ - [`@supabase/supabase-js` Reference](https://supabase.com/docs/reference/javascript/introduction) — Client SDK docs
117
503
 
118
504
  ## Next Steps
119
- For version upgrades, see `supabase-upgrade-migration`.
505
+
506
+ - For SDK version upgrades, see `supabase-upgrade-migration`
507
+ - For load testing before launch, see `supabase-load-scale`
508
+ - For monitoring in production, see `supabase-monitoring`
509
+ - For Edge Function patterns, see `supabase-edge-functions`
@@ -0,0 +1,63 @@
1
+ # Error Handling Reference
2
+
3
+ ## Production Error Catalog
4
+
5
+ | Error | HTTP Status | Cause | Solution |
6
+ |-------|------------|-------|----------|
7
+ | `403 Forbidden` | 403 | RLS enabled but no policies created | Add SELECT/INSERT/UPDATE/DELETE policies for each role |
8
+ | `429 Too Many Requests` | 429 | Plan rate limit exceeded | Upgrade plan or implement client-side exponential backoff |
9
+ | Connection timeout | — | Direct connection in serverless | Switch to pooled connection string (Supavisor port 6543) |
10
+ | `PGRST301` permission denied | 401 | Service role key used where anon expected | Verify client uses anon key for client-side, service_role for server only |
11
+ | Auth emails not delivered | — | Default SMTP rate-limited (4/hour free) | Configure custom SMTP: SendGrid, Resend, or Postmark |
12
+ | Edge Function cold start | — | First invocation after idle period | Pre-warm with scheduled pings or accept ~200ms delay |
13
+ | Storage upload fails | 400/403 | Missing bucket policy or size limit exceeded | Add INSERT policy on `storage.objects` and check `file_size_limit` |
14
+ | Slow queries | — | Missing indexes on filter/join columns | Run Performance Advisor, add indexes per foreign keys and WHERE clauses |
15
+ | Migration conflicts | — | Manual Dashboard edits diverged from files | Run `npx supabase db diff` to capture drift, commit as migration |
16
+ | Realtime disconnects | — | Concurrent connection limit exceeded per tier | Reduce subscriptions or upgrade plan tier |
17
+
18
+ ## Alert Thresholds
19
+
20
+ | Alert | Condition | Severity | Action |
21
+ |-------|-----------|----------|--------|
22
+ | API Down | 5xx errors > 10/min | P1 — Critical | Check Supabase status page, verify Edge Functions, check DB connections |
23
+ | High Latency | p99 > 5000ms | P2 — Warning | Run Performance Advisor, check missing indexes, verify connection pooling |
24
+ | Rate Limited | 429 errors > 5/min | P2 — Warning | Implement backoff, consider plan upgrade, audit request patterns |
25
+ | Auth Failures | 401/403 errors spike | P1 — Critical | Check RLS policies, verify JWT expiry, audit auth provider settings |
26
+ | Pool Exhaustion | Active connections > 80% pool | P1 — Critical | Switch to Supavisor pooled connection, reduce direct connections |
27
+ | Storage Quota | Usage > 80% of plan limit | P3 — Info | Clean unused files, upgrade plan, implement lifecycle policies |
28
+
29
+ ## Supabase Error Code Reference
30
+
31
+ ```typescript
32
+ // Common Supabase error shapes
33
+ interface SupabaseError {
34
+ message: string;
35
+ details: string | null;
36
+ hint: string | null;
37
+ code: string; // PostgreSQL error code
38
+ }
39
+
40
+ // Handle errors in application code
41
+ const { data, error } = await supabase.from('posts').select('*');
42
+ if (error) {
43
+ switch (error.code) {
44
+ case '42501': // insufficient_privilege — RLS blocking
45
+ console.error('RLS policy missing or too restrictive');
46
+ break;
47
+ case '23505': // unique_violation
48
+ console.error('Duplicate record:', error.details);
49
+ break;
50
+ case '23503': // foreign_key_violation
51
+ console.error('Referenced record does not exist');
52
+ break;
53
+ case '57014': // statement_timeout
54
+ console.error('Query timed out — add index or optimize');
55
+ break;
56
+ default:
57
+ console.error('Supabase error:', error.message);
58
+ }
59
+ }
60
+ ```
61
+
62
+ ---
63
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*