@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,203 +1,525 @@
1
1
  ---
2
2
  name: supabase-incident-runbook
3
- description: |
4
- Execute Supabase incident response procedures with triage, mitigation, and postmortem.
5
- Use when responding to Supabase-related outages, investigating errors,
6
- or running post-incident reviews for Supabase integration failures.
7
- Trigger with phrases like "supabase incident", "supabase outage",
8
- "supabase down", "supabase on-call", "supabase emergency", "supabase broken".
9
- allowed-tools: Read, Grep, Bash(kubectl:*), Bash(curl:*)
3
+ description: 'Execute Supabase incident response: dashboard health checks, connection
4
+ pool status,
5
+
6
+ pg_stat_activity queries, RLS debugging, Edge Function logs, storage health, and
7
+ escalation.
8
+
9
+ Use when responding to Supabase outages, investigating production errors, debugging
10
+
11
+ connection issues, or preparing evidence for Supabase support escalation.
12
+
13
+ Trigger: "supabase incident", "supabase outage", "supabase down", "supabase on-call",
14
+
15
+ "supabase emergency", "supabase broken", "supabase connection issues".
16
+
17
+ '
18
+ allowed-tools: Read, Grep, Bash(npx supabase:*), Bash(supabase:*), Bash(curl:*), Bash(psql:*)
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
+ - incident-response
26
+ - debugging
27
+ - operations
28
+ - runbook
29
+ compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
13
30
  ---
14
-
15
31
  # Supabase Incident Runbook
16
32
 
17
33
  ## Overview
18
- Rapid incident response procedures for Supabase-related outages.
34
+
35
+ When a Supabase-backed application experiences failures, you need a structured response: verify the Supabase platform status, check your connection pool, inspect `pg_stat_activity` for stuck queries, debug RLS policies that silently filter data, review Edge Function execution logs, verify storage bucket health, and escalate to Supabase support with a complete evidence bundle. This runbook covers every layer from the SDK client through the database to platform services.
36
+
37
+ **When to use:** Production errors involving Supabase, degraded API response times, connection pool exhaustion, silent data filtering from RLS, Edge Function cold start failures, or storage upload/download errors.
19
38
 
20
39
  ## Prerequisites
21
- - Access to Supabase dashboard and status page
22
- - kubectl access to production cluster
23
- - Prometheus/Grafana access
24
- - Communication channels (Slack, PagerDuty)
25
40
 
26
- ## Severity Levels
41
+ - Supabase project with dashboard access at [supabase.com/dashboard](https://supabase.com/dashboard)
42
+ - `@supabase/supabase-js` v2+ installed in your project
43
+ - Supabase CLI installed for Edge Function log access
44
+ - Direct database connection string (for `psql` diagnostics)
45
+ - Access to [status.supabase.com](https://status.supabase.com) for platform health
27
46
 
28
- | Level | Definition | Response Time | Examples |
29
- |-------|------------|---------------|----------|
30
- | P1 | Complete outage | < 15 min | Supabase API unreachable |
31
- | P2 | Degraded service | < 1 hour | High latency, partial failures |
32
- | P3 | Minor impact | < 4 hours | Webhook delays, non-critical errors |
33
- | P4 | No user impact | Next business day | Monitoring gaps |
47
+ ## Instructions
34
48
 
35
- ## Quick Triage
49
+ ### Step 1: Triage — Platform vs. Application
36
50
 
37
- ```bash
38
- # 1. Check Supabase status
39
- curl -s https://status.supabase.com | jq
51
+ Determine whether the issue is a Supabase platform incident or an application-level bug. Check platform status first, then verify your SDK client connectivity.
40
52
 
41
- # 2. Check our integration health
42
- curl -s https://api.yourapp.com/health | jq '.services.supabase'
53
+ **Check Supabase platform status:**
43
54
 
44
- # 3. Check error rate (last 5 min)
45
- curl -s localhost:9090/api/v1/query?query=rate(supabase_errors_total[5m])
55
+ ```bash
56
+ # Check official status page
57
+ curl -sf https://status.supabase.com/api/v2/status.json | jq '{
58
+ indicator: .status.indicator,
59
+ description: .status.description
60
+ }'
61
+ # Expected: { "indicator": "none", "description": "All Systems Operational" }
62
+
63
+ # Check for active incidents
64
+ curl -sf https://status.supabase.com/api/v2/incidents/unresolved.json | jq '.incidents[] | {
65
+ name: .name,
66
+ status: .status,
67
+ impact: .impact,
68
+ created_at: .created_at
69
+ }'
70
+ ```
46
71
 
47
- # 4. Recent error logs
48
- kubectl logs -l app=supabase-integration --since=5m | grep -i error | tail -20
72
+ **Verify SDK client connectivity from your application:**
73
+
74
+ ```typescript
75
+ import { createClient } from '@supabase/supabase-js';
76
+
77
+ const supabase = createClient(
78
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
79
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
80
+ );
81
+
82
+ // Quick health check — select 1 from a small table
83
+ async function healthCheck(): Promise<{
84
+ status: 'healthy' | 'degraded' | 'down';
85
+ latencyMs: number;
86
+ error?: string;
87
+ }> {
88
+ const start = performance.now();
89
+ try {
90
+ const { data, error } = await supabase
91
+ .from('_health_check')
92
+ .select('id')
93
+ .limit(1)
94
+ .maybeSingle();
95
+
96
+ const latencyMs = Math.round(performance.now() - start);
97
+
98
+ if (error) {
99
+ return { status: 'degraded', latencyMs, error: error.message };
100
+ }
101
+
102
+ return {
103
+ status: latencyMs > 2000 ? 'degraded' : 'healthy',
104
+ latencyMs,
105
+ };
106
+ } catch (err) {
107
+ return {
108
+ status: 'down',
109
+ latencyMs: Math.round(performance.now() - start),
110
+ error: err instanceof Error ? err.message : 'Unknown error',
111
+ };
112
+ }
113
+ }
114
+
115
+ // Create a minimal health check table (run once)
116
+ // CREATE TABLE _health_check (id int PRIMARY KEY DEFAULT 1);
117
+ // INSERT INTO _health_check VALUES (1);
118
+ // ALTER TABLE _health_check ENABLE ROW LEVEL SECURITY;
119
+ // CREATE POLICY "allow_anon_read" ON _health_check FOR SELECT USING (true);
49
120
  ```
50
121
 
51
- ## Decision Tree
122
+ **Decision tree:**
52
123
 
53
124
  ```
54
- Supabase API returning errors?
55
- ├─ YES: Is status.supabase.com showing incident?
56
- │ ├─ YES → Wait for Supabase to resolve. Enable fallback.
57
- └─ NO Our integration issue. Check credentials, config.
58
- └─ NO: Is our service healthy?
59
- ├─ YESLikely resolved or intermittent. Monitor.
60
- └─ NO Our infrastructure issue. Check pods, memory, network.
125
+ Is status.supabase.com showing an incident?
126
+ ├─ YES Supabase platform issue
127
+ │ ├─ Enable fallback/cache layer
128
+ ├─ Monitor status page for resolution
129
+ └─ Skip to Step 3 for connection pool protection
130
+ └─ NOApplication-level issue
131
+ ├─ Does healthCheck() return 'healthy'?
132
+ │ ├─ YES → Issue is in your queries/RLS/Edge Functions → Step 2
133
+ │ └─ NO → Connection or auth issue → Step 2 + Step 3
134
+ └─ Check error codes: 401=auth, 429=rate limit, 500=server error
61
135
  ```
62
136
 
63
- ## Immediate Actions by Error Type
137
+ ### Step 2: Database Diagnostics with pg_stat_activity
64
138
 
65
- ### 401/403 - Authentication
66
- ```bash
67
- # Verify API key is set
68
- kubectl get secret supabase-secrets -o jsonpath='{.data.api-key}' | base64 -d
139
+ Connect directly to the database to inspect active connections, find stuck queries, and detect connection leaks. These queries run via `psql` or the Supabase SQL Editor.
69
140
 
70
- # Check if key was rotated
71
- # → Verify in Supabase dashboard
141
+ **Connection pool status:**
72
142
 
73
- # Remediation: Update secret and restart pods
74
- kubectl create secret generic supabase-secrets --from-literal=api-key=NEW_KEY --dry-run=client -o yaml | kubectl apply -f -
75
- kubectl rollout restart deployment/supabase-integration
76
- ```
143
+ ```sql
144
+ -- Current connections grouped by state
145
+ SELECT state, count(*) AS connections,
146
+ max(extract(epoch FROM age(now(), state_change)))::int AS max_idle_seconds
147
+ FROM pg_stat_activity
148
+ WHERE datname = current_database()
149
+ GROUP BY state
150
+ ORDER BY connections DESC;
77
151
 
78
- ### 429 - Rate Limited
79
- ```bash
80
- # Check rate limit headers
81
- curl -v https://api.supabase.com 2>&1 | grep -i rate
152
+ -- Expected healthy output:
153
+ -- state | connections | max_idle_seconds
154
+ -- idle | 3 | 12
155
+ -- active | 1 | 0
156
+ -- | 2 | (null) ← background workers
82
157
 
83
- # Enable request queuing
84
- kubectl set env deployment/supabase-integration RATE_LIMIT_MODE=queue
158
+ -- WARNING: If idle > 20 or idle_in_transaction > 0, you have a leak
159
+ ```
85
160
 
86
- # Long-term: Contact Supabase for limit increase
161
+ **Find long-running and stuck queries:**
162
+
163
+ ```sql
164
+ -- Queries running longer than 10 seconds
165
+ SELECT pid, usename, state,
166
+ age(now(), query_start)::text AS duration,
167
+ wait_event_type, wait_event,
168
+ left(query, 120) AS query_preview
169
+ FROM pg_stat_activity
170
+ WHERE state = 'active'
171
+ AND query NOT LIKE '%pg_stat_activity%'
172
+ AND age(now(), query_start) > interval '10 seconds'
173
+ ORDER BY query_start;
174
+
175
+ -- Idle-in-transaction connections (connection leak indicator)
176
+ SELECT pid, usename,
177
+ age(now(), state_change)::text AS idle_duration,
178
+ left(query, 100) AS last_query
179
+ FROM pg_stat_activity
180
+ WHERE state = 'idle in transaction'
181
+ ORDER BY state_change;
182
+
183
+ -- Kill a specific stuck query (use with caution)
184
+ -- SELECT pg_cancel_backend(<pid>); -- graceful cancel
185
+ -- SELECT pg_terminate_backend(<pid>); -- force kill
87
186
  ```
88
187
 
89
- ### 500/503 - Supabase Errors
90
- ```bash
91
- # Enable graceful degradation
92
- kubectl set env deployment/supabase-integration SUPABASE_FALLBACK=true
188
+ **Check connection limits:**
93
189
 
94
- # Notify users of degraded service
95
- # Update status page
190
+ ```sql
191
+ -- Are we near the connection limit?
192
+ SELECT
193
+ max_conn,
194
+ used,
195
+ max_conn - used AS available,
196
+ round(100.0 * used / max_conn, 1) AS pct_used
197
+ FROM (SELECT count(*) AS used FROM pg_stat_activity) t,
198
+ (SELECT setting::int AS max_conn FROM pg_settings WHERE name = 'max_connections') s;
96
199
 
97
- # Monitor Supabase status for resolution
200
+ -- If pct_used > 80%, you need connection pooling via Supavisor
201
+ -- Dashboard → Project Settings → Database → Connection Pooling
98
202
  ```
99
203
 
100
- ## Communication Templates
101
-
102
- ### Internal (Slack)
103
- ```
104
- 🔴 P1 INCIDENT: Supabase Integration
105
- Status: INVESTIGATING
106
- Impact: [Describe user impact]
107
- Current action: [What you're doing]
108
- Next update: [Time]
109
- Incident commander: @[name]
204
+ **Application-side connection monitoring:**
205
+
206
+ ```typescript
207
+ import { createClient } from '@supabase/supabase-js';
208
+
209
+ const supabase = createClient(
210
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
211
+ process.env.SUPABASE_SERVICE_ROLE_KEY!,
212
+ { auth: { autoRefreshToken: false, persistSession: false } }
213
+ );
214
+
215
+ // Monitor connection health from the application
216
+ async function getConnectionStats() {
217
+ const { data, error } = await supabase.rpc('get_connection_stats');
218
+ if (error) throw error;
219
+ return data;
220
+ }
221
+
222
+ // Create this function in your database:
223
+ // CREATE OR REPLACE FUNCTION get_connection_stats()
224
+ // RETURNS json AS $$
225
+ // SELECT json_build_object(
226
+ // 'active', (SELECT count(*) FROM pg_stat_activity WHERE state = 'active'),
227
+ // 'idle', (SELECT count(*) FROM pg_stat_activity WHERE state = 'idle'),
228
+ // 'idle_in_tx', (SELECT count(*) FROM pg_stat_activity WHERE state = 'idle in transaction'),
229
+ // 'total', (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()),
230
+ // 'max', (SELECT setting::int FROM pg_settings WHERE name = 'max_connections')
231
+ // );
232
+ // $$ LANGUAGE sql SECURITY DEFINER;
110
233
  ```
111
234
 
112
- ### External (Status Page)
113
- ```
114
- Supabase Integration Issue
235
+ ### Step 3: RLS Debugging, Edge Functions, and Storage
115
236
 
116
- We're experiencing issues with our Supabase integration.
117
- Some users may experience [specific impact].
237
+ Debug silent data filtering from Row Level Security policies, inspect Edge Function execution, and verify storage bucket health.
118
238
 
119
- We're actively investigating and will provide updates.
239
+ **RLS policy debugging:**
120
240
 
121
- Last updated: [timestamp]
122
- ```
241
+ ```sql
242
+ -- List all RLS policies on a table
243
+ SELECT policyname, cmd, permissive,
244
+ pg_get_expr(qual, polrelid) AS using_expression,
245
+ pg_get_expr(with_check, polrelid) AS with_check_expression
246
+ FROM pg_policy
247
+ JOIN pg_class ON pg_class.oid = polrelid
248
+ WHERE relname = 'your_table_name';
123
249
 
124
- ## Post-Incident
250
+ -- Test as a specific user (simulates their JWT in SQL Editor)
251
+ SET request.jwt.claim.sub = 'target-user-uuid';
252
+ SET request.jwt.claim.role = 'authenticated';
125
253
 
126
- ### Evidence Collection
127
- ```bash
128
- # Generate debug bundle
129
- ./scripts/supabase-debug-bundle.sh
254
+ -- Run the query that's failing
255
+ SELECT * FROM your_table_name WHERE user_id = 'target-user-uuid';
256
+ -- If empty but data exists → RLS is filtering incorrectly
257
+
258
+ -- Verify what auth.uid() resolves to
259
+ SELECT auth.uid();
260
+ SELECT auth.jwt();
130
261
 
131
- # Export relevant logs
132
- kubectl logs -l app=supabase-integration --since=1h > incident-logs.txt
262
+ -- Compare with service role (bypasses RLS)
263
+ -- Use service_role key in createClient to confirm data exists
133
264
 
134
- # Capture metrics
135
- curl "localhost:9090/api/v1/query_range?query=supabase_errors_total&start=2h" > metrics.json
265
+ -- Reset after testing
266
+ RESET request.jwt.claim.sub;
267
+ RESET request.jwt.claim.role;
136
268
  ```
137
269
 
138
- ### Postmortem Template
139
- ```markdown
140
- ## Incident: Supabase [Error Type]
141
- **Date:** YYYY-MM-DD
142
- **Duration:** X hours Y minutes
143
- **Severity:** P[1-4]
270
+ **RLS debugging from the SDK:**
144
271
 
145
- ### Summary
146
- [1-2 sentence description]
272
+ ```typescript
273
+ import { createClient } from '@supabase/supabase-js';
147
274
 
148
- ### Timeline
149
- - HH:MM - [Event]
150
- - HH:MM - [Event]
275
+ // Anon client — respects RLS
276
+ const anonClient = createClient(url, anonKey);
151
277
 
152
- ### Root Cause
153
- [Technical explanation]
278
+ // Service role client — bypasses RLS
279
+ const adminClient = createClient(url, serviceRoleKey, {
280
+ auth: { autoRefreshToken: false, persistSession: false },
281
+ });
154
282
 
155
- ### Impact
156
- - Users affected: N
157
- - Revenue impact: $X
283
+ async function debugRLS(table: string, userId: string) {
284
+ // Query with RLS (what the user sees)
285
+ const { data: rlsData, error: rlsError } = await anonClient
286
+ .from(table)
287
+ .select('*')
288
+ .eq('user_id', userId);
158
289
 
159
- ### Action Items
160
- - [ ] [Preventive measure] - Owner - Due date
290
+ // Query without RLS (what actually exists)
291
+ const { data: adminData, error: adminError } = await adminClient
292
+ .from(table)
293
+ .select('*')
294
+ .eq('user_id', userId);
295
+
296
+ console.log('With RLS:', rlsData?.length ?? 0, 'rows', rlsError?.message ?? 'OK');
297
+ console.log('Without RLS:', adminData?.length ?? 0, 'rows', adminError?.message ?? 'OK');
298
+
299
+ if ((adminData?.length ?? 0) > (rlsData?.length ?? 0)) {
300
+ console.warn('RLS is filtering rows — check policies on', table);
301
+ }
302
+ }
161
303
  ```
162
304
 
163
- ## Instructions
305
+ **Edge Function log inspection:**
164
306
 
165
- ### Step 1: Quick Triage
166
- Run the triage commands to identify the issue source.
307
+ ```text
308
+ # View recent Edge Function logs
309
+ npx supabase functions logs my-function --project-ref <project-ref>
167
310
 
168
- ### Step 2: Follow Decision Tree
169
- Determine if the issue is Supabase-side or internal.
311
+ # Tail logs in real-time during debugging
312
+ npx supabase functions serve my-function --debug --env-file .env.local
170
313
 
171
- ### Step 3: Execute Immediate Actions
172
- Apply the appropriate remediation for the error type.
314
+ # Check function deployment status
315
+ npx supabase functions list --project-ref <project-ref>
173
316
 
174
- ### Step 4: Communicate Status
175
- Update internal and external stakeholders.
317
+ # Common Edge Function issues:
318
+ # - Cold starts > 1s: function needs warm-up or is too large
319
+ # - WORKER_LIMIT error: function exceeded memory/CPU
320
+ # - ImportError: missing dependency in import_map.json
321
+ ```
322
+
323
+ **Edge Function health check from SDK:**
324
+
325
+ ```typescript
326
+ import { createClient } from '@supabase/supabase-js';
327
+
328
+ const supabase = createClient(url, anonKey);
329
+
330
+ async function checkEdgeFunction(functionName: string) {
331
+ const start = performance.now();
332
+ const { data, error } = await supabase.functions.invoke(functionName, {
333
+ body: { action: 'health-check' },
334
+ });
335
+ const duration = Math.round(performance.now() - start);
336
+
337
+ console.log(`Edge Function "${functionName}":`, {
338
+ status: error ? 'error' : 'ok',
339
+ durationMs: duration,
340
+ coldStart: duration > 1000,
341
+ error: error?.message,
342
+ });
343
+ }
344
+ ```
345
+
346
+ **Storage bucket health:**
347
+
348
+ ```typescript
349
+ import { createClient } from '@supabase/supabase-js';
350
+
351
+ const supabase = createClient(url, serviceRoleKey, {
352
+ auth: { autoRefreshToken: false, persistSession: false },
353
+ });
354
+
355
+ async function checkStorageHealth() {
356
+ // List all buckets
357
+ const { data: buckets, error: listError } = await supabase.storage.listBuckets();
358
+ if (listError) {
359
+ console.error('Cannot list buckets:', listError.message);
360
+ return;
361
+ }
362
+
363
+ for (const bucket of buckets ?? []) {
364
+ // Try listing files in each bucket
365
+ const { data: files, error: filesError } = await supabase.storage
366
+ .from(bucket.name)
367
+ .list('', { limit: 1 });
368
+
369
+ console.log(`Bucket "${bucket.name}":`, {
370
+ public: bucket.public,
371
+ accessible: !filesError,
372
+ error: filesError?.message,
373
+ });
374
+ }
375
+
376
+ // Test upload/download cycle
377
+ const testFile = new Blob(['health-check'], { type: 'text/plain' });
378
+ const testPath = `_health_check/${Date.now()}.txt`;
379
+
380
+ const { error: uploadError } = await supabase.storage
381
+ .from('test-bucket')
382
+ .upload(testPath, testFile);
383
+
384
+ if (!uploadError) {
385
+ await supabase.storage.from('test-bucket').remove([testPath]);
386
+ console.log('Storage upload/download: OK');
387
+ } else {
388
+ console.error('Storage upload failed:', uploadError.message);
389
+ }
390
+ }
391
+ ```
176
392
 
177
393
  ## Output
178
- - Issue identified and categorized
179
- - Remediation applied
180
- - Stakeholders notified
181
- - Evidence collected for postmortem
394
+
395
+ After running this incident runbook, you will have:
396
+
397
+ - **Platform status assessment** — confirmed whether the issue is Supabase-side or application-side
398
+ - **SDK health check** — latency measurement and connectivity verification via `createClient`
399
+ - **Connection pool analysis** — `pg_stat_activity` showing active, idle, and leaked connections
400
+ - **Long-running query identification** — stuck queries with PIDs ready for cancellation
401
+ - **RLS policy diagnosis** — side-by-side comparison of anon vs. service role query results
402
+ - **Edge Function status** — deployment status, cold start detection, and log inspection
403
+ - **Storage health report** — bucket accessibility and upload/download verification
404
+ - **Evidence bundle** — complete diagnostic data for Supabase support escalation
182
405
 
183
406
  ## Error Handling
184
- | Issue | Cause | Solution |
407
+
408
+ | Error | Cause | Solution |
185
409
  |-------|-------|----------|
186
- | Can't reach status page | Network issue | Use mobile or VPN |
187
- | kubectl fails | Auth expired | Re-authenticate |
188
- | Metrics unavailable | Prometheus down | Check backup metrics |
189
- | Secret rotation fails | Permission denied | Escalate to admin |
410
+ | `FetchError: request failed` | Supabase API unreachable | Check status.supabase.com; verify network/DNS |
411
+ | `connection refused` on port 5432 | Direct DB access blocked or wrong credentials | Use pooler URL (port 6543) or check dashboard connection strings |
412
+ | `too many clients already` | Connection pool exhausted | Kill idle-in-transaction connections; enable Supavisor pooling |
413
+ | `permission denied for table` | RLS blocking or wrong role | Check policies with `pg_policy`; verify JWT claims |
414
+ | `WORKER_LIMIT` in Edge Function | Memory/CPU exceeded | Reduce function payload size; optimize imports |
415
+ | `JWT expired` | Token not refreshing | Verify `autoRefreshToken: true` in `createClient` options |
416
+ | `storage/object-not-found` | File deleted or wrong path | Check bucket policies; verify path with service role client |
417
+ | `rate limit exceeded` (429) | Too many API requests | Implement exponential backoff; contact Supabase for limit increase |
190
418
 
191
419
  ## Examples
192
420
 
193
- ### One-Line Health Check
194
- ```bash
195
- curl -sf https://api.yourapp.com/health | jq '.services.supabase.status' || echo "UNHEALTHY"
421
+ **Example 1 Quick triage script:**
422
+
423
+ ```typescript
424
+ import { createClient } from '@supabase/supabase-js';
425
+
426
+ async function triageSupabase() {
427
+ const supabase = createClient(
428
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
429
+ process.env.SUPABASE_SERVICE_ROLE_KEY!,
430
+ { auth: { autoRefreshToken: false, persistSession: false } }
431
+ );
432
+
433
+ // 1. Database connectivity
434
+ const { error: dbError } = await supabase.from('_health_check').select('id').limit(1);
435
+ console.log('Database:', dbError ? `ERROR: ${dbError.message}` : 'OK');
436
+
437
+ // 2. Auth service
438
+ const { data: authData, error: authError } = await supabase.auth.getSession();
439
+ console.log('Auth service:', authError ? `ERROR: ${authError.message}` : 'OK');
440
+
441
+ // 3. Storage service
442
+ const { error: storageError } = await supabase.storage.listBuckets();
443
+ console.log('Storage:', storageError ? `ERROR: ${storageError.message}` : 'OK');
444
+
445
+ // 4. Realtime service
446
+ const channel = supabase.channel('health');
447
+ channel.subscribe((status) => {
448
+ console.log('Realtime:', status);
449
+ channel.unsubscribe();
450
+ });
451
+ }
452
+ ```
453
+
454
+ **Example 2 — Connection leak detector:**
455
+
456
+ ```sql
457
+ -- Run this during an incident to find leaked connections
458
+ WITH connection_summary AS (
459
+ SELECT usename, state,
460
+ count(*) AS conn_count,
461
+ max(age(now(), state_change)) AS max_age
462
+ FROM pg_stat_activity
463
+ WHERE datname = current_database()
464
+ GROUP BY usename, state
465
+ )
466
+ SELECT usename, state, conn_count,
467
+ max_age::text AS max_idle_time,
468
+ CASE
469
+ WHEN state = 'idle in transaction' THEN 'LEAK - kill these'
470
+ WHEN state = 'idle' AND max_age > interval '10 minutes' THEN 'STALE - review'
471
+ ELSE 'OK'
472
+ END AS assessment
473
+ FROM connection_summary
474
+ ORDER BY conn_count DESC;
475
+ ```
476
+
477
+ **Example 3 — Escalation evidence bundle:**
478
+
479
+ ```typescript
480
+ import { createClient } from '@supabase/supabase-js';
481
+
482
+ async function buildEvidenceBundle() {
483
+ const supabase = createClient(url, serviceRoleKey, {
484
+ auth: { autoRefreshToken: false, persistSession: false },
485
+ });
486
+
487
+ const evidence = {
488
+ timestamp: new Date().toISOString(),
489
+ projectRef: process.env.SUPABASE_PROJECT_REF,
490
+ symptoms: [],
491
+ diagnostics: {},
492
+ };
493
+
494
+ // Collect connection stats
495
+ const { data: connStats } = await supabase.rpc('get_connection_stats');
496
+ evidence.diagnostics['connections'] = connStats;
497
+
498
+ // Collect recent errors from your error tracking
499
+ evidence.symptoms.push('Describe the user-facing symptoms here');
500
+
501
+ // Include request IDs from failed API calls
502
+ // The x-request-id header from Supabase responses identifies specific requests
503
+
504
+ console.log('Evidence bundle for Supabase support:');
505
+ console.log(JSON.stringify(evidence, null, 2));
506
+ // Submit at:
507
+ }
196
508
  ```
197
509
 
198
510
  ## Resources
511
+
199
512
  - [Supabase Status Page](https://status.supabase.com)
200
- - [Supabase Support](https://support.supabase.com)
513
+ - Supabase Support Portal
514
+ - [Database Health — Supabase Docs](https://supabase.com/docs/guides/database/inspect)
515
+ - [RLS Debugging — Supabase Docs](https://supabase.com/docs/guides/troubleshooting/rls-simplified-BJTcS8)
516
+ - [Edge Functions Logs — Supabase Docs](https://supabase.com/docs/guides/functions/logging)
517
+ - [Connection Pooling with Supavisor](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler)
518
+ - [pg_stat_activity — PostgreSQL Docs](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW)
201
519
 
202
520
  ## Next Steps
203
- For data handling, see `supabase-data-handling`.
521
+
522
+ - For GDPR compliance and data handling, see `supabase-data-handling`
523
+ - For performance tuning and query optimization, see `supabase-performance-tuning`
524
+ - For observability and monitoring setup, see `supabase-observability`
525
+ - For common error patterns and fixes, see `supabase-common-errors`
@@ -0,0 +1,11 @@
1
+ # Error Handling Reference
2
+
3
+ | Issue | Cause | Solution |
4
+ |-------|-------|----------|
5
+ | Can't reach status page | Network issue | Use mobile or VPN |
6
+ | kubectl fails | Auth expired | Re-authenticate |
7
+ | Metrics unavailable | Prometheus down | Check backup metrics |
8
+ | Secret rotation fails | Permission denied | Escalate to admin |
9
+
10
+ ---
11
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*