@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
@@ -0,0 +1,11 @@
1
+ # Error Handling Reference
2
+
3
+ | Issue | Cause | Solution |
4
+ |-------|-------|----------|
5
+ | Can't reproduce | Race condition | Add timing analysis |
6
+ | Intermittent failure | Timing-dependent | Increase sample size |
7
+ | No useful logs | Missing instrumentation | Add debug logging |
8
+ | Memory growth | Resource leak | Use heap profiling |
9
+
10
+ ---
11
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*
@@ -0,0 +1,34 @@
1
+ # Evidence Collection Framework
2
+
3
+ ## Evidence Collection Framework
4
+
5
+ ### Comprehensive Debug Bundle
6
+
7
+ ```bash
8
+ #!/bin/bash
9
+ # advanced-supabase-debug.sh
10
+
11
+ BUNDLE="supabase-advanced-debug-$(date +%Y%m%d-%H%M%S)"
12
+ mkdir -p "$BUNDLE"/{logs,metrics,network,config,traces}
13
+
14
+ # 1. Extended logs (1 hour window)
15
+ kubectl logs -l app=supabase-integration --since=1h > "$BUNDLE/logs/pods.log"
16
+ journalctl -u supabase-service --since "1 hour ago" > "$BUNDLE/logs/system.log"
17
+
18
+ # 2. Metrics dump
19
+ curl -s localhost:9090/api/v1/query?query=supabase_requests_total > "$BUNDLE/metrics/requests.json"
20
+ curl -s localhost:9090/api/v1/query?query=supabase_errors_total > "$BUNDLE/metrics/errors.json"
21
+
22
+ # 3. Network capture (30 seconds)
23
+ timeout 30 tcpdump -i any port 443 -w "$BUNDLE/network/capture.pcap" &
24
+
25
+ # 4. Distributed traces
26
+ curl -s localhost:16686/api/traces?service=supabase > "$BUNDLE/traces/jaeger.json"
27
+
28
+ # 5. Configuration state
29
+ kubectl get cm supabase-config -o yaml > "$BUNDLE/config/configmap.yaml"
30
+ kubectl get secret supabase-secrets -o yaml > "$BUNDLE/config/secrets-redacted.yaml"
31
+
32
+ tar -czf "$BUNDLE.tar.gz" "$BUNDLE"
33
+ echo "Advanced debug bundle: $BUNDLE.tar.gz"
34
+ ```
@@ -0,0 +1,11 @@
1
+ ## Examples
2
+
3
+ ### Quick Layer Test
4
+
5
+ ```bash
6
+ # Test each layer in sequence
7
+ curl -v https://api.supabase.com/health 2>&1 | grep -E "(Connected|TLS|HTTP)"
8
+ ```
9
+
10
+ ---
11
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*
@@ -0,0 +1,363 @@
1
+ # RLS Conflicts, Edge Function Cold Starts, and Realtime Drops
2
+
3
+ Diagnose RLS policy conflicts that cause unexpected access patterns, profile Edge Function cold starts, and investigate Realtime connection drops.
4
+
5
+ **RLS policy conflict analysis:**
6
+
7
+ ```sql
8
+ -- List ALL policies on a table to find conflicts
9
+ SELECT
10
+ pol.polname AS policy_name,
11
+ CASE pol.polcmd
12
+ WHEN 'r' THEN 'SELECT'
13
+ WHEN 'a' THEN 'INSERT'
14
+ WHEN 'w' THEN 'UPDATE'
15
+ WHEN 'd' THEN 'DELETE'
16
+ WHEN '*' THEN 'ALL'
17
+ END AS command,
18
+ CASE pol.polpermissive
19
+ WHEN true THEN 'PERMISSIVE'
20
+ ELSE 'RESTRICTIVE'
21
+ END AS type,
22
+ pg_get_expr(pol.polqual, pol.polrelid) AS using_clause,
23
+ pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check_clause,
24
+ ARRAY(SELECT rolname FROM pg_roles WHERE oid = ANY(pol.polroles)) AS applies_to_roles
25
+ FROM pg_policy pol
26
+ JOIN pg_class cls ON cls.oid = pol.polrelid
27
+ WHERE cls.relname = 'your_table_name'
28
+ ORDER BY pol.polcmd, pol.polpermissive DESC;
29
+
30
+ -- Common conflict: PERMISSIVE policies are OR'd together
31
+ -- If you have two SELECT policies, a row is visible if EITHER matches
32
+ -- RESTRICTIVE policies are AND'd — all must pass
33
+
34
+ -- Test a specific user's access
35
+ SET request.jwt.claim.sub = 'user-uuid';
36
+ SET request.jwt.claim.role = 'authenticated';
37
+ SET request.jwt.claims = '{"sub": "user-uuid", "role": "authenticated", "app_metadata": {"role": "editor", "org_id": "org-123"}}';
38
+
39
+ -- Check what they can see
40
+ SELECT count(*) FROM your_table_name;
41
+
42
+ -- Check the auth functions
43
+ SELECT auth.uid(), auth.jwt(), auth.role();
44
+
45
+ RESET ALL;
46
+ ```
47
+
48
+ **RLS conflict debugging from the SDK:**
49
+
50
+ ```typescript
51
+ import { createClient } from '@supabase/supabase-js';
52
+
53
+ // Compare results across permission levels
54
+ async function debugRLSConflict(table: string, filters: Record<string, string>) {
55
+ const anonClient = createClient(url, anonKey);
56
+ const authedClient = createClient(url, anonKey);
57
+ const adminClient = createClient(url, serviceRoleKey, {
58
+ auth: { autoRefreshToken: false, persistSession: false },
59
+ });
60
+
61
+ // Sign in as a test user
62
+ await authedClient.auth.signInWithPassword({
63
+ email: 'test@example.com',
64
+ password: 'test-password',
65
+ });
66
+
67
+ let query = (client: any) => {
68
+ let q = client.from(table).select('*', { count: 'exact' });
69
+ for (const [key, value] of Object.entries(filters)) {
70
+ q = q.eq(key, value);
71
+ }
72
+ return q;
73
+ };
74
+
75
+ const [anonResult, authedResult, adminResult] = await Promise.all([
76
+ query(anonClient),
77
+ query(authedClient),
78
+ query(adminClient),
79
+ ]);
80
+
81
+ console.log(`RLS debug for "${table}":`, {
82
+ anon: { count: anonResult.count, error: anonResult.error?.message },
83
+ authenticated: { count: authedResult.count, error: authedResult.error?.message },
84
+ admin: { count: adminResult.count, error: adminResult.error?.message },
85
+ });
86
+
87
+ if (adminResult.count !== authedResult.count) {
88
+ console.warn(
89
+ `RLS filtering: admin sees ${adminResult.count} rows, user sees ${authedResult.count}`
90
+ );
91
+ }
92
+ }
93
+ ```
94
+
95
+ **Edge Function cold start profiling:**
96
+
97
+ ```typescript
98
+ import { createClient } from '@supabase/supabase-js';
99
+
100
+ const supabase = createClient(url, anonKey);
101
+
102
+ // Measure cold start vs warm invocation times
103
+ async function profileEdgeFunction(
104
+ functionName: string,
105
+ iterations = 5,
106
+ coldStartDelayMs = 60000
107
+ ) {
108
+ const results: { iteration: number; durationMs: number; isColdStart: boolean }[] = [];
109
+
110
+ for (let i = 0; i < iterations; i++) {
111
+ // Wait before first call to ensure cold start
112
+ if (i === 0) {
113
+ console.log(`Waiting ${coldStartDelayMs / 1000}s for cold start...`);
114
+ await new Promise((r) => setTimeout(r, coldStartDelayMs));
115
+ }
116
+
117
+ const start = performance.now();
118
+ const { data, error } = await supabase.functions.invoke(functionName, {
119
+ body: { action: 'ping', timestamp: Date.now() },
120
+ });
121
+ const duration = Math.round(performance.now() - start);
122
+
123
+ results.push({
124
+ iteration: i + 1,
125
+ durationMs: duration,
126
+ isColdStart: i === 0 || duration > 1000,
127
+ });
128
+
129
+ console.log(`Invocation ${i + 1}: ${duration}ms ${i === 0 ? '(cold start)' : '(warm)'}`);
130
+ }
131
+
132
+ const coldStarts = results.filter((r) => r.isColdStart);
133
+ const warmStarts = results.filter((r) => !r.isColdStart);
134
+
135
+ console.log('Summary:', {
136
+ coldStartAvgMs: coldStarts.length > 0
137
+ ? Math.round(coldStarts.reduce((s, r) => s + r.durationMs, 0) / coldStarts.length)
138
+ : 'N/A',
139
+ warmStartAvgMs: warmStarts.length > 0
140
+ ? Math.round(warmStarts.reduce((s, r) => s + r.durationMs, 0) / warmStarts.length)
141
+ : 'N/A',
142
+ });
143
+ }
144
+ ```
145
+
146
+ ```bash
147
+ # Check Edge Function logs for cold start indicators
148
+ npx supabase functions logs my-function --project-ref <ref> 2>&1 | head -50
149
+
150
+ # Look for patterns:
151
+ # - First invocation after deploy: high latency
152
+ # - "Worker booted" or "Isolate created" messages
153
+ # - Memory/CPU spikes on first request
154
+
155
+ # Reduce cold starts:
156
+ # 1. Minimize imports (lazy-load heavy dependencies)
157
+ # 2. Keep function payload small
158
+ # 3. Use scheduled warm-up pings via pg_cron
159
+ ```
160
+
161
+ **Realtime connection drop investigation:**
162
+
163
+ ```typescript
164
+ import { createClient } from '@supabase/supabase-js';
165
+
166
+ const supabase = createClient(url, anonKey);
167
+
168
+ // Debug Realtime connection stability
169
+ function monitorRealtimeChannel(table: string) {
170
+ const channel = supabase
171
+ .channel(`debug-${table}`)
172
+ .on('system', {}, (payload) => {
173
+ console.log(`[SYSTEM] ${new Date().toISOString()}:`, payload);
174
+ // Watch for: CHANNEL_ERROR, TIMED_OUT, TOKEN_EXPIRED
175
+ })
176
+ .on(
177
+ 'postgres_changes',
178
+ { event: '*', schema: 'public', table },
179
+ (payload) => {
180
+ console.log(`[CHANGE] ${payload.eventType}:`, payload.new);
181
+ }
182
+ )
183
+ .subscribe((status, err) => {
184
+ console.log(`[STATUS] ${new Date().toISOString()}: ${status}`, err ?? '');
185
+
186
+ if (status === 'CHANNEL_ERROR') {
187
+ console.error('Channel error — will auto-reconnect');
188
+ }
189
+ if (status === 'TIMED_OUT') {
190
+ console.error('Connection timed out — check network/firewall');
191
+ }
192
+ });
193
+
194
+ // Monitor connection health periodically
195
+ const healthInterval = setInterval(() => {
196
+ const state = channel.state;
197
+ console.log(`[HEALTH] Channel state: ${state}`);
198
+ if (state !== 'joined') {
199
+ console.warn(`[HEALTH] Channel not joined, current state: ${state}`);
200
+ }
201
+ }, 30000);
202
+
203
+ return {
204
+ channel,
205
+ stop: () => {
206
+ clearInterval(healthInterval);
207
+ channel.unsubscribe();
208
+ },
209
+ };
210
+ }
211
+ ```
212
+
213
+ ```sql
214
+ -- Verify table is in the Realtime publication
215
+ SELECT schemaname, tablename
216
+ FROM pg_publication_tables
217
+ WHERE pubname = 'supabase_realtime'
218
+ ORDER BY tablename;
219
+
220
+ -- Add a missing table to the publication
221
+ ALTER PUBLICATION supabase_realtime ADD TABLE public.your_table;
222
+
223
+ -- Check Realtime connection limits
224
+ -- Supabase free plan: 200 concurrent connections
225
+ -- Pro plan: 500 concurrent connections
226
+ -- You can check current count in the Supabase dashboard → Realtime → Connections
227
+ ```
228
+
229
+ ## Output
230
+
231
+ After completing this skill, you will have:
232
+
233
+ - **Slow query identification** — `pg_stat_statements` queries ranking by total time, frequency, and cache hit ratio
234
+ - **EXPLAIN ANALYZE proficiency** — reading execution plans and creating targeted indexes
235
+ - **Lock contention diagnosis** — blocked/blocking query pairs with lock modes
236
+ - **Connection leak detection** — idle and idle-in-transaction connections with kill commands
237
+ - **Connection pool monitoring** — SDK-based health check RPC with utilization alerts
238
+ - **RLS conflict analysis** — policy listing with permissive/restrictive classification and multi-level comparison
239
+ - **Edge Function profiling** — cold start vs warm invocation measurement
240
+ - **Realtime debugging** — channel state monitoring with system event logging
241
+
242
+ ## Error Handling
243
+
244
+ | Error | Cause | Solution |
245
+ |-------|-------|----------|
246
+ | `pg_stat_statements` not available | Extension not enabled | Run `CREATE EXTENSION pg_stat_statements;` |
247
+ | Seq Scan on large table | Missing index on filter column | Create index with `CREATE INDEX CONCURRENTLY` |
248
+ | `deadlock detected` | Circular lock dependency | Ensure consistent lock ordering across transactions |
249
+ | All connections in `idle in transaction` | Application not closing transactions | Add connection timeout; review ORM connection pool settings |
250
+ | RLS returns empty for authenticated user | JWT claims don't match policy | Check `auth.jwt()` output; verify `app_metadata` is set |
251
+ | Edge Function > 2s cold start | Large dependency bundle | Lazy-import heavy modules; reduce function size |
252
+ | Realtime `TIMED_OUT` | Network/firewall blocking WebSocket | Check port 443 is open; verify no proxy strips `Upgrade` header |
253
+ | `CHANNEL_ERROR` on subscribe | Table not in Realtime publication | Run `ALTER PUBLICATION supabase_realtime ADD TABLE ...` |
254
+
255
+ ## Examples
256
+
257
+ **Example 1 — Quick performance audit:**
258
+
259
+ ```sql
260
+ -- Run this query to get a snapshot of database health
261
+ SELECT
262
+ 'Connections' AS metric,
263
+ count(*)::text AS value
264
+ FROM pg_stat_activity WHERE datname = current_database()
265
+ UNION ALL
266
+ SELECT 'Cache hit ratio',
267
+ round(100.0 * sum(heap_blks_hit) / nullif(sum(heap_blks_hit + heap_blks_read), 0), 2)::text || '%'
268
+ FROM pg_statio_user_tables
269
+ UNION ALL
270
+ SELECT 'Table bloat (dead tuples)',
271
+ sum(n_dead_tup)::text
272
+ FROM pg_stat_user_tables
273
+ UNION ALL
274
+ SELECT 'Longest running query',
275
+ coalesce(max(age(now(), query_start))::text, 'none')
276
+ FROM pg_stat_activity WHERE state = 'active' AND query NOT LIKE '%pg_stat%';
277
+ ```
278
+
279
+ **Example 2 — Build a diagnostic bundle for support:**
280
+
281
+ ```typescript
282
+ import { createClient } from '@supabase/supabase-js';
283
+
284
+ const supabase = createClient(url, serviceRoleKey, {
285
+ auth: { autoRefreshToken: false, persistSession: false },
286
+ });
287
+
288
+ async function buildDiagnosticBundle() {
289
+ const bundle: Record<string, any> = {
290
+ timestamp: new Date().toISOString(),
291
+ projectRef: process.env.SUPABASE_PROJECT_REF,
292
+ };
293
+
294
+ // Connection stats
295
+ const { data: connHealth } = await supabase.rpc('get_connection_health');
296
+ bundle.connections = connHealth;
297
+
298
+ // Table sizes
299
+ const { data: tableSizes } = await supabase.rpc('get_table_sizes');
300
+ bundle.tableSizes = tableSizes;
301
+
302
+ // Recent errors from application logs
303
+ const { data: recentErrors } = await supabase
304
+ .from('error_logs')
305
+ .select('message, count, last_seen')
306
+ .order('last_seen', { ascending: false })
307
+ .limit(10);
308
+ bundle.recentErrors = recentErrors;
309
+
310
+ console.log(JSON.stringify(bundle, null, 2));
311
+ // Submit with your support ticket at https://supabase.com/dashboard/support
312
+ }
313
+ ```
314
+
315
+ **Example 3 — Automated slow query alert:**
316
+
317
+ ```typescript
318
+ import { createClient } from '@supabase/supabase-js';
319
+
320
+ const supabase = createClient(url, serviceRoleKey, {
321
+ auth: { autoRefreshToken: false, persistSession: false },
322
+ });
323
+
324
+ async function checkSlowQueries(thresholdMs = 1000) {
325
+ const { data: slowQueries } = await supabase.rpc('get_slow_queries', {
326
+ threshold_ms: thresholdMs,
327
+ });
328
+
329
+ if (slowQueries && slowQueries.length > 0) {
330
+ console.warn(`Found ${slowQueries.length} queries averaging > ${thresholdMs}ms`);
331
+ for (const q of slowQueries) {
332
+ console.warn(` [${q.avg_ms}ms avg, ${q.calls} calls] ${q.query_preview}`);
333
+ }
334
+ }
335
+ }
336
+
337
+ // Database function:
338
+ // CREATE OR REPLACE FUNCTION get_slow_queries(threshold_ms numeric DEFAULT 1000)
339
+ // RETURNS TABLE(queryid bigint, avg_ms numeric, calls bigint, query_preview text) AS $$
340
+ // SELECT queryid, round(mean_exec_time::numeric, 2), calls, left(query, 150)
341
+ // FROM pg_stat_statements
342
+ // WHERE mean_exec_time > threshold_ms AND calls > 10
343
+ // ORDER BY mean_exec_time DESC LIMIT 10;
344
+ // $$ LANGUAGE sql SECURITY DEFINER;
345
+ ```
346
+
347
+ ## Resources
348
+
349
+ - [pg_stat_statements — PostgreSQL Docs](https://www.postgresql.org/docs/current/pgstatstatements.html)
350
+ - [EXPLAIN ANALYZE — PostgreSQL Docs](https://www.postgresql.org/docs/current/sql-explain.html)
351
+ - [Supabase Performance Advisor](https://supabase.com/docs/guides/database/inspect)
352
+ - [RLS Debugging — Supabase Docs](https://supabase.com/docs/guides/troubleshooting/rls-simplified-BJTcS8)
353
+ - [Edge Functions Logging — Supabase Docs](https://supabase.com/docs/guides/functions/logging)
354
+ - Realtime Debugging — Supabase Docs
355
+ - [pg_locks — PostgreSQL Docs](https://www.postgresql.org/docs/current/view-pg-locks.html)
356
+ - [Connection Pooling with Supavisor](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler)
357
+
358
+ ## Next Steps
359
+
360
+ - For load testing and scaling patterns, see `supabase-load-scale`
361
+ - For incident response procedures, see `supabase-incident-runbook`
362
+ - For performance tuning and index optimization, see `supabase-performance-tuning`
363
+ - For common error patterns and quick fixes, see `supabase-common-errors`
@@ -0,0 +1,56 @@
1
+ # Systematic Isolation
2
+
3
+ ## Systematic Isolation
4
+
5
+ ### Layer-by-Layer Testing
6
+
7
+ ```typescript
8
+ // Test each layer independently
9
+ async function diagnoseSupabaseIssue(): Promise<DiagnosisReport> {
10
+ const results: DiagnosisResult[] = [];
11
+
12
+ // Layer 1: Network connectivity
13
+ results.push(await testNetworkConnectivity());
14
+
15
+ // Layer 2: DNS resolution
16
+ results.push(await testDNSResolution('api.supabase.com'));
17
+
18
+ // Layer 3: TLS handshake
19
+ results.push(await testTLSHandshake('api.supabase.com'));
20
+
21
+ // Layer 4: Authentication
22
+ results.push(await testAuthentication());
23
+
24
+ // Layer 5: API response
25
+ results.push(await testAPIResponse());
26
+
27
+ // Layer 6: Response parsing
28
+ results.push(await testResponseParsing());
29
+
30
+ return { results, firstFailure: results.find(r => !r.success) };
31
+ }
32
+ ```
33
+
34
+ ### Minimal Reproduction
35
+
36
+ ```typescript
37
+ // Strip down to absolute minimum
38
+ async function minimalRepro(): Promise<void> {
39
+ // 1. Fresh client, no customization
40
+ const client = new SupabaseClient({
41
+ apiKey: process.env.SUPABASE_API_KEY!,
42
+ });
43
+
44
+ // 2. Simplest possible call
45
+ try {
46
+ const result = await client.ping();
47
+ console.log('Ping successful:', result);
48
+ } catch (error) {
49
+ console.error('Ping failed:', {
50
+ message: error.message,
51
+ code: error.code,
52
+ stack: error.stack,
53
+ });
54
+ }
55
+ }
56
+ ```
@@ -0,0 +1,35 @@
1
+ # Timing Analysis
2
+
3
+ ## Timing Analysis
4
+
5
+ ```typescript
6
+ class TimingAnalyzer {
7
+ private timings: Map<string, number[]> = new Map();
8
+
9
+ async measure<T>(label: string, fn: () => Promise<T>): Promise<T> {
10
+ const start = performance.now();
11
+ try {
12
+ return await fn();
13
+ } finally {
14
+ const duration = performance.now() - start;
15
+ const existing = this.timings.get(label) || [];
16
+ existing.push(duration);
17
+ this.timings.set(label, existing);
18
+ }
19
+ }
20
+
21
+ report(): TimingReport {
22
+ const report: TimingReport = {};
23
+ for (const [label, times] of this.timings) {
24
+ report[label] = {
25
+ count: times.length,
26
+ min: Math.min(...times),
27
+ max: Math.max(...times),
28
+ avg: times.reduce((a, b) => a + b, 0) / times.length,
29
+ p95: this.percentile(times, 95),
30
+ };
31
+ }
32
+ return report;
33
+ }
34
+ }
35
+ ```