@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,261 +1,465 @@
1
1
  ---
2
2
  name: supabase-advanced-troubleshooting
3
- description: |
4
- Apply Supabase advanced debugging techniques for hard-to-diagnose issues.
5
- Use when standard troubleshooting fails, investigating complex race conditions,
6
- or preparing evidence bundles for Supabase support escalation.
7
- Trigger with phrases like "supabase hard bug", "supabase mystery error",
8
- "supabase impossible to debug", "difficult supabase issue", "supabase deep debug".
9
- allowed-tools: Read, Grep, Bash(kubectl:*), Bash(curl:*), Bash(tcpdump:*)
10
- version: 1.0.0
11
- license: MIT
12
- author: Jeremy Longshore <jeremy@intentsolutions.io>
13
- ---
3
+ description: 'Deep Supabase diagnostics: pg_stat_statements for slow queries, lock
4
+ debugging with
14
5
 
15
- # Supabase Advanced Troubleshooting
16
-
17
- ## Overview
18
- Deep debugging techniques for complex Supabase issues that resist standard troubleshooting.
19
-
20
- ## Prerequisites
21
- - Access to production logs and metrics
22
- - kubectl access to clusters
23
- - Network capture tools available
24
- - Understanding of distributed tracing
6
+ pg_locks, connection leak detection, RLS policy conflicts, Edge Function cold starts,
25
7
 
26
- ## Evidence Collection Framework
8
+ and Realtime connection drop analysis.
27
9
 
28
- ### Comprehensive Debug Bundle
29
- ```bash
30
- #!/bin/bash
31
- # advanced-supabase-debug.sh
10
+ Use when standard troubleshooting fails, investigating performance regressions,
11
+ debugging
32
12
 
33
- BUNDLE="supabase-advanced-debug-$(date +%Y%m%d-%H%M%S)"
34
- mkdir -p "$BUNDLE"/{logs,metrics,network,config,traces}
13
+ race conditions, or building evidence for Supabase support escalation.
35
14
 
36
- # 1. Extended logs (1 hour window)
37
- kubectl logs -l app=supabase-integration --since=1h > "$BUNDLE/logs/pods.log"
38
- journalctl -u supabase-service --since "1 hour ago" > "$BUNDLE/logs/system.log"
15
+ Trigger: "supabase deep debug", "supabase slow query", "supabase lock contention",
39
16
 
40
- # 2. Metrics dump
41
- curl -s localhost:9090/api/v1/query?query=supabase_requests_total > "$BUNDLE/metrics/requests.json"
42
- curl -s localhost:9090/api/v1/query?query=supabase_errors_total > "$BUNDLE/metrics/errors.json"
17
+ "supabase connection leak", "supabase RLS conflict", "supabase cold start".
43
18
 
44
- # 3. Network capture (30 seconds)
45
- timeout 30 tcpdump -i any port 443 -w "$BUNDLE/network/capture.pcap" &
46
-
47
- # 4. Distributed traces
48
- curl -s localhost:16686/api/traces?service=supabase > "$BUNDLE/traces/jaeger.json"
49
-
50
- # 5. Configuration state
51
- kubectl get cm supabase-config -o yaml > "$BUNDLE/config/configmap.yaml"
52
- kubectl get secret supabase-secrets -o yaml > "$BUNDLE/config/secrets-redacted.yaml"
53
-
54
- tar -czf "$BUNDLE.tar.gz" "$BUNDLE"
55
- echo "Advanced debug bundle: $BUNDLE.tar.gz"
56
- ```
57
-
58
- ## Systematic Isolation
59
-
60
- ### Layer-by-Layer Testing
19
+ '
20
+ allowed-tools: Read, Grep, Bash(npx supabase:*), Bash(supabase:*), Bash(curl:*), Bash(psql:*)
21
+ version: 1.0.0
22
+ license: MIT
23
+ author: Jeremy Longshore <jeremy@intentsolutions.io>
24
+ tags:
25
+ - saas
26
+ - supabase
27
+ - debugging
28
+ - advanced
29
+ - performance
30
+ - troubleshooting
31
+ compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
32
+ ---
33
+ # Supabase Advanced Troubleshooting
61
34
 
62
- ```typescript
63
- // Test each layer independently
64
- async function diagnoseSupabaseIssue(): Promise<DiagnosisReport> {
65
- const results: DiagnosisResult[] = [];
35
+ ## Overview
66
36
 
67
- // Layer 1: Network connectivity
68
- results.push(await testNetworkConnectivity());
37
+ When basic debugging does not reveal the root cause, you need deep PostgreSQL diagnostics: `pg_stat_statements` to find the slowest queries by cumulative execution time, `pg_locks` to detect lock contention and deadlocks, `pg_stat_activity` to find connection leaks, RLS policy conflict analysis to diagnose silent data filtering, Edge Function cold start profiling, and Realtime channel drop investigation. This skill covers every advanced diagnostic technique with real SQL queries and `createClient` from `@supabase/supabase-js`.
69
38
 
70
- // Layer 2: DNS resolution
71
- results.push(await testDNSResolution('api.supabase.com'));
39
+ **When to use:** Slow query investigation, lock contention causing timeouts, connection pool exhaustion from leaks, RLS policies that silently filter or conflict, Edge Functions with unpredictable latency, or Realtime subscriptions that disconnect intermittently.
72
40
 
73
- // Layer 3: TLS handshake
74
- results.push(await testTLSHandshake('api.supabase.com'));
41
+ ## Prerequisites
75
42
 
76
- // Layer 4: Authentication
77
- results.push(await testAuthentication());
43
+ - Supabase project with `pg_stat_statements` extension enabled
44
+ - Direct database access via SQL Editor or `psql`
45
+ - `@supabase/supabase-js` v2+ installed in your project
46
+ - Supabase CLI for Edge Function logs
47
+ - Familiarity with PostgreSQL system catalogs
78
48
 
79
- // Layer 5: API response
80
- results.push(await testAPIResponse());
49
+ ## Instructions
81
50
 
82
- // Layer 6: Response parsing
83
- results.push(await testResponseParsing());
51
+ ### Step 1: pg_stat_statements and Slow Query Analysis
52
+
53
+ Enable and query `pg_stat_statements` to find the most expensive queries by total execution time, calls, and rows processed.
54
+
55
+ **Enable the extension and query slow queries:**
56
+
57
+ ```sql
58
+ -- Enable pg_stat_statements (run once)
59
+ CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
60
+
61
+ -- Top 10 slowest queries by total execution time
62
+ SELECT
63
+ queryid,
64
+ calls,
65
+ round(total_exec_time::numeric, 2) AS total_ms,
66
+ round(mean_exec_time::numeric, 2) AS avg_ms,
67
+ round(max_exec_time::numeric, 2) AS max_ms,
68
+ rows AS total_rows,
69
+ round(100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0), 2) AS cache_hit_pct,
70
+ left(query, 150) AS query_preview
71
+ FROM pg_stat_statements
72
+ WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user)
73
+ ORDER BY total_exec_time DESC
74
+ LIMIT 10;
75
+
76
+ -- Top queries by frequency (most called)
77
+ SELECT
78
+ queryid,
79
+ calls,
80
+ round(mean_exec_time::numeric, 2) AS avg_ms,
81
+ rows / nullif(calls, 0) AS rows_per_call,
82
+ left(query, 150) AS query_preview
83
+ FROM pg_stat_statements
84
+ WHERE calls > 100
85
+ ORDER BY calls DESC
86
+ LIMIT 10;
87
+
88
+ -- Queries with poor cache hit ratio (reading from disk)
89
+ SELECT
90
+ queryid,
91
+ calls,
92
+ shared_blks_hit,
93
+ shared_blks_read,
94
+ round(100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0), 2) AS cache_hit_pct,
95
+ left(query, 150) AS query_preview
96
+ FROM pg_stat_statements
97
+ WHERE shared_blks_read > 100
98
+ ORDER BY shared_blks_read DESC
99
+ LIMIT 10;
100
+
101
+ -- Reset statistics after optimization (to measure improvement)
102
+ -- SELECT pg_stat_statements_reset();
103
+ ```
84
104
 
85
- return { results, firstFailure: results.find(r => !r.success) };
86
- }
105
+ **EXPLAIN ANALYZE for specific slow queries:**
106
+
107
+ ```sql
108
+ -- Run EXPLAIN ANALYZE on the suspicious query
109
+ EXPLAIN (ANALYZE, BUFFERS, TIMING, FORMAT TEXT)
110
+ SELECT p.*, count(o.id) AS order_count
111
+ FROM profiles p
112
+ LEFT JOIN orders o ON o.user_id = p.id
113
+ WHERE p.created_at > now() - interval '30 days'
114
+ GROUP BY p.id
115
+ ORDER BY order_count DESC
116
+ LIMIT 50;
117
+
118
+ -- What to look for in the output:
119
+ -- 1. Seq Scan on large table → needs an index
120
+ -- 2. Nested Loop with high actual rows → consider Hash Join
121
+ -- 3. Sort with "Sort Method: external merge" → increase work_mem or add index
122
+ -- 4. Buffers read >> shared hit → data not cached, optimize query or increase shared_buffers
123
+
124
+ -- Create a targeted index based on EXPLAIN output
125
+ CREATE INDEX CONCURRENTLY idx_profiles_created_at
126
+ ON profiles(created_at DESC);
127
+
128
+ CREATE INDEX CONCURRENTLY idx_orders_user_id
129
+ ON orders(user_id);
87
130
  ```
88
131
 
89
- ### Minimal Reproduction
132
+ **Monitor query performance from the SDK:**
90
133
 
91
134
  ```typescript
92
- // Strip down to absolute minimum
93
- async function minimalRepro(): Promise<void> {
94
- // 1. Fresh client, no customization
95
- const client = new SupabaseClient({
96
- apiKey: process.env.SUPABASE_API_KEY!,
97
- });
135
+ import { createClient } from '@supabase/supabase-js';
136
+
137
+ const supabase = createClient(
138
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
139
+ process.env.SUPABASE_SERVICE_ROLE_KEY!,
140
+ { auth: { autoRefreshToken: false, persistSession: false } }
141
+ );
142
+
143
+ // Wrapper that measures and logs query performance
144
+ async function timedQuery<T>(
145
+ label: string,
146
+ queryFn: () => Promise<{ data: T | null; error: any }>
147
+ ): Promise<T | null> {
148
+ const start = performance.now();
149
+ const { data, error } = await queryFn();
150
+ const duration = Math.round(performance.now() - start);
151
+
152
+ if (duration > 500) {
153
+ console.warn(`[SLOW QUERY] ${label}: ${duration}ms`);
154
+ }
98
155
 
99
- // 2. Simplest possible call
100
- try {
101
- const result = await client.ping();
102
- console.log('Ping successful:', result);
103
- } catch (error) {
104
- console.error('Ping failed:', {
105
- message: error.message,
106
- code: error.code,
107
- stack: error.stack,
108
- });
156
+ if (error) {
157
+ console.error(`[QUERY ERROR] ${label}:`, error.message);
158
+ return null;
109
159
  }
160
+
161
+ return data;
110
162
  }
111
- ```
112
163
 
113
- ## Timing Analysis
164
+ // Usage
165
+ const profiles = await timedQuery('recent-profiles', () =>
166
+ supabase
167
+ .from('profiles')
168
+ .select('*, orders(count)')
169
+ .gte('created_at', new Date(Date.now() - 30 * 86400000).toISOString())
170
+ .order('created_at', { ascending: false })
171
+ .limit(50)
172
+ );
173
+ ```
114
174
 
115
- ```typescript
116
- class TimingAnalyzer {
117
- private timings: Map<string, number[]> = new Map();
118
-
119
- async measure<T>(label: string, fn: () => Promise<T>): Promise<T> {
120
- const start = performance.now();
121
- try {
122
- return await fn();
123
- } finally {
124
- const duration = performance.now() - start;
125
- const existing = this.timings.get(label) || [];
126
- existing.push(duration);
127
- this.timings.set(label, existing);
128
- }
129
- }
175
+ ### Step 2: Lock Debugging and Connection Leak Detection
176
+
177
+ Find blocked queries, detect lock contention, and identify connection leaks that exhaust the pool.
178
+
179
+ **Lock contention detection:**
180
+
181
+ ```sql
182
+ -- Find blocked queries and what's blocking them
183
+ SELECT
184
+ blocked.pid AS blocked_pid,
185
+ blocked.usename AS blocked_user,
186
+ age(now(), blocked.query_start)::text AS blocked_duration,
187
+ left(blocked.query, 100) AS blocked_query,
188
+ blocking.pid AS blocking_pid,
189
+ blocking.usename AS blocking_user,
190
+ left(blocking.query, 100) AS blocking_query,
191
+ bl.mode AS lock_mode
192
+ FROM pg_stat_activity blocked
193
+ JOIN pg_locks bl ON bl.pid = blocked.pid AND NOT bl.granted
194
+ JOIN pg_locks kl ON kl.locktype = bl.locktype
195
+ AND kl.database IS NOT DISTINCT FROM bl.database
196
+ AND kl.relation IS NOT DISTINCT FROM bl.relation
197
+ AND kl.page IS NOT DISTINCT FROM bl.page
198
+ AND kl.tuple IS NOT DISTINCT FROM bl.tuple
199
+ AND kl.pid != bl.pid
200
+ AND kl.granted
201
+ JOIN pg_stat_activity blocking ON blocking.pid = kl.pid
202
+ WHERE blocked.state = 'active';
203
+
204
+ -- Check all locks on a specific table
205
+ SELECT
206
+ l.locktype, l.mode, l.granted, l.pid,
207
+ a.usename, a.state,
208
+ age(now(), a.query_start)::text AS duration,
209
+ left(a.query, 80) AS query
210
+ FROM pg_locks l
211
+ JOIN pg_stat_activity a ON a.pid = l.pid
212
+ WHERE l.relation = 'orders'::regclass
213
+ ORDER BY l.granted, a.query_start;
214
+
215
+ -- Detect potential deadlocks
216
+ SELECT
217
+ l1.pid AS pid1, l2.pid AS pid2,
218
+ l1.mode AS lock1, l2.mode AS lock2,
219
+ l1.relation::regclass AS table1,
220
+ l2.relation::regclass AS table2
221
+ FROM pg_locks l1
222
+ JOIN pg_locks l2 ON l1.pid != l2.pid
223
+ AND l1.relation = l2.relation
224
+ AND NOT l1.granted AND l2.granted
225
+ WHERE l1.locktype = 'relation';
226
+ ```
130
227
 
131
- report(): TimingReport {
132
- const report: TimingReport = {};
133
- for (const [label, times] of this.timings) {
134
- report[label] = {
135
- count: times.length,
136
- min: Math.min(...times),
137
- max: Math.max(...times),
138
- avg: times.reduce((a, b) => a + b, 0) / times.length,
139
- p95: this.percentile(times, 95),
140
- };
141
- }
142
- return report;
143
- }
144
- }
228
+ **Connection leak detection:**
229
+
230
+ ```sql
231
+ -- Connections that have been idle for too long (likely leaks)
232
+ SELECT
233
+ pid, usename, client_addr, state,
234
+ age(now(), state_change)::text AS idle_time,
235
+ age(now(), backend_start)::text AS connection_age,
236
+ left(query, 100) AS last_query
237
+ FROM pg_stat_activity
238
+ WHERE state = 'idle'
239
+ AND age(now(), state_change) > interval '5 minutes'
240
+ AND datname = current_database()
241
+ ORDER BY state_change;
242
+
243
+ -- Connections stuck in "idle in transaction" (the worst kind of leak)
244
+ SELECT
245
+ pid, usename, client_addr,
246
+ age(now(), xact_start)::text AS transaction_duration,
247
+ age(now(), state_change)::text AS idle_in_tx_time,
248
+ left(query, 100) AS last_query
249
+ FROM pg_stat_activity
250
+ WHERE state = 'idle in transaction'
251
+ ORDER BY xact_start;
252
+
253
+ -- Connection usage by application/user
254
+ SELECT
255
+ usename,
256
+ client_addr,
257
+ state,
258
+ count(*) AS connections
259
+ FROM pg_stat_activity
260
+ WHERE datname = current_database()
261
+ GROUP BY usename, client_addr, state
262
+ ORDER BY connections DESC;
263
+
264
+ -- Kill leaked connections (batch)
265
+ -- SELECT pg_terminate_backend(pid)
266
+ -- FROM pg_stat_activity
267
+ -- WHERE state = 'idle in transaction'
268
+ -- AND age(now(), state_change) > interval '10 minutes';
145
269
  ```
146
270
 
147
- ## Memory and Resource Analysis
271
+ **Connection pool monitoring from the SDK:**
148
272
 
149
273
  ```typescript
150
- // Detect memory leaks in Supabase client usage
151
- const heapUsed: number[] = [];
152
-
153
- setInterval(() => {
154
- const usage = process.memoryUsage();
155
- heapUsed.push(usage.heapUsed);
156
-
157
- // Alert on sustained growth
158
- if (heapUsed.length > 60) { // 1 hour at 1/min
159
- const trend = heapUsed[59] - heapUsed[0];
160
- if (trend > 100 * 1024 * 1024) { // 100MB growth
161
- console.warn('Potential memory leak in supabase integration');
162
- }
274
+ import { createClient } from '@supabase/supabase-js';
275
+
276
+ const supabase = createClient(
277
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
278
+ process.env.SUPABASE_SERVICE_ROLE_KEY!,
279
+ { auth: { autoRefreshToken: false, persistSession: false } }
280
+ );
281
+
282
+ // Monitor connection pool health
283
+ async function checkConnectionPool() {
284
+ const { data, error } = await supabase.rpc('get_connection_health');
285
+ if (error) {
286
+ console.error('Connection health check failed:', error.message);
287
+ return;
163
288
  }
164
- }, 60000);
165
- ```
166
289
 
167
- ## Race Condition Detection
290
+ const health = data as {
291
+ active: number;
292
+ idle: number;
293
+ idle_in_transaction: number;
294
+ total: number;
295
+ max_connections: number;
296
+ };
168
297
 
169
- ```typescript
170
- // Detect concurrent access issues
171
- class SupabaseConcurrencyChecker {
172
- private inProgress: Set<string> = new Set();
298
+ const utilization = (health.total / health.max_connections) * 100;
173
299
 
174
- async execute<T>(key: string, fn: () => Promise<T>): Promise<T> {
175
- if (this.inProgress.has(key)) {
176
- console.warn(`Concurrent access detected for ${key}`);
177
- }
300
+ console.log('Connection pool:', {
301
+ ...health,
302
+ utilization: `${utilization.toFixed(1)}%`,
303
+ });
178
304
 
179
- this.inProgress.add(key);
180
- try {
181
- return await fn();
182
- } finally {
183
- this.inProgress.delete(key);
184
- }
305
+ if (health.idle_in_transaction > 0) {
306
+ console.warn(`WARNING: ${health.idle_in_transaction} idle-in-transaction connections (likely leaks)`);
307
+ }
308
+
309
+ if (utilization > 80) {
310
+ console.warn(`WARNING: Connection pool at ${utilization.toFixed(1)}% capacity`);
185
311
  }
186
312
  }
313
+
314
+ // Database function for the RPC call:
315
+ // CREATE OR REPLACE FUNCTION get_connection_health()
316
+ // RETURNS json AS $$
317
+ // SELECT json_build_object(
318
+ // 'active', (SELECT count(*) FROM pg_stat_activity WHERE state = 'active' AND datname = current_database()),
319
+ // 'idle', (SELECT count(*) FROM pg_stat_activity WHERE state = 'idle' AND datname = current_database()),
320
+ // 'idle_in_transaction', (SELECT count(*) FROM pg_stat_activity WHERE state = 'idle in transaction' AND datname = current_database()),
321
+ // 'total', (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()),
322
+ // 'max_connections', (SELECT setting::int FROM pg_settings WHERE name = 'max_connections')
323
+ // );
324
+ // $$ LANGUAGE sql SECURITY DEFINER;
187
325
  ```
188
326
 
189
- ## Support Escalation Template
327
+ ### Step 3: RLS Conflicts, Edge Function Cold Starts, and Realtime Drops
190
328
 
191
- ```markdown
192
- ## Supabase Support Escalation
329
+ See [RLS conflicts, Edge Function cold starts, and Realtime drops](references/rls-edge-functions-realtime.md) for RLS policy conflict analysis (SQL and SDK), Edge Function cold start profiling, Realtime channel monitoring, and publication configuration.
193
330
 
194
- **Severity:** P[1-4]
195
- **Request ID:** [from error response]
196
- **Timestamp:** [ISO 8601]
331
+ ## Output
197
332
 
198
- ### Issue Summary
199
- [One paragraph description]
333
+ After completing this skill, you will have:
200
334
 
201
- ### Steps to Reproduce
202
- 1. [Step 1]
203
- 2. [Step 2]
335
+ - **Slow query identification** — `pg_stat_statements` queries ranking by total time, frequency, and cache hit ratio
336
+ - **EXPLAIN ANALYZE proficiency** — reading execution plans and creating targeted indexes
337
+ - **Lock contention diagnosis** — blocked/blocking query pairs with lock modes
338
+ - **Connection leak detection** — idle and idle-in-transaction connections with kill commands
339
+ - **Connection pool monitoring** — SDK-based health check RPC with utilization alerts
340
+ - **RLS conflict analysis** — policy listing with permissive/restrictive classification and multi-level comparison
341
+ - **Edge Function profiling** — cold start vs warm invocation measurement
342
+ - **Realtime debugging** — channel state monitoring with system event logging
204
343
 
205
- ### Expected vs Actual
206
- - Expected: [behavior]
207
- - Actual: [behavior]
344
+ ## Error Handling
208
345
 
209
- ### Evidence Attached
210
- - [ ] Debug bundle (supabase-advanced-debug-*.tar.gz)
211
- - [ ] Minimal reproduction code
212
- - [ ] Timing analysis
213
- - [ ] Network capture (if relevant)
346
+ | Error | Cause | Solution |
347
+ |-------|-------|----------|
348
+ | `pg_stat_statements` not available | Extension not enabled | Run `CREATE EXTENSION pg_stat_statements;` |
349
+ | Seq Scan on large table | Missing index on filter column | Create index with `CREATE INDEX CONCURRENTLY` |
350
+ | `deadlock detected` | Circular lock dependency | Ensure consistent lock ordering across transactions |
351
+ | All connections in `idle in transaction` | Application not closing transactions | Add connection timeout; review ORM connection pool settings |
352
+ | RLS returns empty for authenticated user | JWT claims don't match policy | Check `auth.jwt()` output; verify `app_metadata` is set |
353
+ | Edge Function > 2s cold start | Large dependency bundle | Lazy-import heavy modules; reduce function size |
354
+ | Realtime `TIMED_OUT` | Network/firewall blocking WebSocket | Check port 443 is open; verify no proxy strips `Upgrade` header |
355
+ | `CHANNEL_ERROR` on subscribe | Table not in Realtime publication | Run `ALTER PUBLICATION supabase_realtime ADD TABLE ...` |
214
356
 
215
- ### Workarounds Attempted
216
- 1. [Workaround 1] - Result: [outcome]
217
- 2. [Workaround 2] - Result: [outcome]
218
- ```
357
+ ## Examples
219
358
 
220
- ## Instructions
359
+ **Example 1 — Quick performance audit:**
360
+
361
+ ```sql
362
+ -- Run this query to get a snapshot of database health
363
+ SELECT
364
+ 'Connections' AS metric,
365
+ count(*)::text AS value
366
+ FROM pg_stat_activity WHERE datname = current_database()
367
+ UNION ALL
368
+ SELECT 'Cache hit ratio',
369
+ round(100.0 * sum(heap_blks_hit) / nullif(sum(heap_blks_hit + heap_blks_read), 0), 2)::text || '%'
370
+ FROM pg_statio_user_tables
371
+ UNION ALL
372
+ SELECT 'Table bloat (dead tuples)',
373
+ sum(n_dead_tup)::text
374
+ FROM pg_stat_user_tables
375
+ UNION ALL
376
+ SELECT 'Longest running query',
377
+ coalesce(max(age(now(), query_start))::text, 'none')
378
+ FROM pg_stat_activity WHERE state = 'active' AND query NOT LIKE '%pg_stat%';
379
+ ```
221
380
 
222
- ### Step 1: Collect Evidence Bundle
223
- Run the comprehensive debug script to gather all relevant data.
381
+ **Example 2 Build a diagnostic bundle for support:**
224
382
 
225
- ### Step 2: Systematic Isolation
226
- Test each layer independently to identify the failure point.
383
+ ```typescript
384
+ import { createClient } from '@supabase/supabase-js';
385
+
386
+ const supabase = createClient(url, serviceRoleKey, {
387
+ auth: { autoRefreshToken: false, persistSession: false },
388
+ });
389
+
390
+ async function buildDiagnosticBundle() {
391
+ const bundle: Record<string, any> = {
392
+ timestamp: new Date().toISOString(),
393
+ projectRef: process.env.SUPABASE_PROJECT_REF,
394
+ };
395
+
396
+ // Connection stats
397
+ const { data: connHealth } = await supabase.rpc('get_connection_health');
398
+ bundle.connections = connHealth;
399
+
400
+ // Table sizes
401
+ const { data: tableSizes } = await supabase.rpc('get_table_sizes');
402
+ bundle.tableSizes = tableSizes;
403
+
404
+ // Recent errors from application logs
405
+ const { data: recentErrors } = await supabase
406
+ .from('error_logs')
407
+ .select('message, count, last_seen')
408
+ .order('last_seen', { ascending: false })
409
+ .limit(10);
410
+ bundle.recentErrors = recentErrors;
411
+
412
+ console.log(JSON.stringify(bundle, null, 2));
413
+ // Submit with your support ticket at https://supabase.com/dashboard/support
414
+ }
415
+ ```
227
416
 
228
- ### Step 3: Create Minimal Reproduction
229
- Strip down to the simplest failing case.
417
+ **Example 3 Automated slow query alert:**
230
418
 
231
- ### Step 4: Escalate with Evidence
232
- Use the support template with all collected evidence.
419
+ ```typescript
420
+ import { createClient } from '@supabase/supabase-js';
233
421
 
234
- ## Output
235
- - Comprehensive debug bundle collected
236
- - Failure layer identified
237
- - Minimal reproduction created
238
- - Support escalation submitted
422
+ const supabase = createClient(url, serviceRoleKey, {
423
+ auth: { autoRefreshToken: false, persistSession: false },
424
+ });
239
425
 
240
- ## Error Handling
241
- | Issue | Cause | Solution |
242
- |-------|-------|----------|
243
- | Can't reproduce | Race condition | Add timing analysis |
244
- | Intermittent failure | Timing-dependent | Increase sample size |
245
- | No useful logs | Missing instrumentation | Add debug logging |
246
- | Memory growth | Resource leak | Use heap profiling |
426
+ async function checkSlowQueries(thresholdMs = 1000) {
427
+ const { data: slowQueries } = await supabase.rpc('get_slow_queries', {
428
+ threshold_ms: thresholdMs,
429
+ });
247
430
 
248
- ## Examples
431
+ if (slowQueries && slowQueries.length > 0) {
432
+ console.warn(`Found ${slowQueries.length} queries averaging > ${thresholdMs}ms`);
433
+ for (const q of slowQueries) {
434
+ console.warn(` [${q.avg_ms}ms avg, ${q.calls} calls] ${q.query_preview}`);
435
+ }
436
+ }
437
+ }
249
438
 
250
- ### Quick Layer Test
251
- ```bash
252
- # Test each layer in sequence
253
- curl -v https://api.supabase.com/health 2>&1 | grep -E "(Connected|TLS|HTTP)"
439
+ // Database function:
440
+ // CREATE OR REPLACE FUNCTION get_slow_queries(threshold_ms numeric DEFAULT 1000)
441
+ // RETURNS TABLE(queryid bigint, avg_ms numeric, calls bigint, query_preview text) AS $$
442
+ // SELECT queryid, round(mean_exec_time::numeric, 2), calls, left(query, 150)
443
+ // FROM pg_stat_statements
444
+ // WHERE mean_exec_time > threshold_ms AND calls > 10
445
+ // ORDER BY mean_exec_time DESC LIMIT 10;
446
+ // $$ LANGUAGE sql SECURITY DEFINER;
254
447
  ```
255
448
 
256
449
  ## Resources
257
- - [Supabase Support Portal](https://support.supabase.com)
258
- - [Supabase Status Page](https://status.supabase.com)
450
+
451
+ - [pg_stat_statements PostgreSQL Docs](https://www.postgresql.org/docs/current/pgstatstatements.html)
452
+ - [EXPLAIN ANALYZE — PostgreSQL Docs](https://www.postgresql.org/docs/current/sql-explain.html)
453
+ - [Supabase Performance Advisor](https://supabase.com/docs/guides/database/inspect)
454
+ - [RLS Debugging — Supabase Docs](https://supabase.com/docs/guides/troubleshooting/rls-simplified-BJTcS8)
455
+ - [Edge Functions Logging — Supabase Docs](https://supabase.com/docs/guides/functions/logging)
456
+ - Realtime Debugging — Supabase Docs
457
+ - [pg_locks — PostgreSQL Docs](https://www.postgresql.org/docs/current/view-pg-locks.html)
458
+ - [Connection Pooling with Supavisor](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler)
259
459
 
260
460
  ## Next Steps
261
- For load testing, see `supabase-load-scale`.
461
+
462
+ - For load testing and scaling patterns, see `supabase-load-scale`
463
+ - For incident response procedures, see `supabase-incident-runbook`
464
+ - For performance tuning and index optimization, see `supabase-performance-tuning`
465
+ - For common error patterns and quick fixes, see `supabase-common-errors`