@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,244 +1,405 @@
1
1
  ---
2
2
  name: supabase-migration-deep-dive
3
- description: |
4
- Execute Supabase major re-architecture and migration strategies with strangler fig pattern.
5
- Use when migrating to or from Supabase, performing major version upgrades,
6
- or re-platforming existing integrations to Supabase.
7
- Trigger with phrases like "migrate supabase", "supabase migration",
8
- "switch to supabase", "supabase replatform", "supabase upgrade major".
9
- allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(node:*), Bash(kubectl:*)
3
+ description: 'Database migration patterns with Supabase CLI: npx supabase migration
4
+ new, zero-downtime
5
+
6
+ migrations, data backfill strategies, schema versioning, rollback strategies, and
7
+ type generation.
8
+
9
+ Use when creating database migrations, performing zero-downtime schema changes,
10
+ backfilling
11
+
12
+ data in production, managing schema versions, or planning rollback strategies.
13
+
14
+ Trigger: "supabase migration", "supabase schema change", "supabase zero downtime",
15
+
16
+ "supabase rollback", "supabase db push", "supabase migration new".
17
+
18
+ '
19
+ allowed-tools: Read, Write, Edit, Bash(npx supabase:*), Bash(supabase:*), Bash(psql:*),
20
+ Grep, Glob
10
21
  version: 1.0.0
11
22
  license: MIT
12
23
  author: Jeremy Longshore <jeremy@intentsolutions.io>
24
+ tags:
25
+ - saas
26
+ - supabase
27
+ - migration
28
+ - database
29
+ - schema
30
+ - zero-downtime
31
+ - rollback
32
+ compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
13
33
  ---
14
-
15
34
  # Supabase Migration Deep Dive
16
35
 
17
36
  ## Overview
18
- Comprehensive guide for migrating to or from Supabase, or major version upgrades.
37
+
38
+ Supabase migrations are SQL files managed by the CLI that track schema changes across environments. This skill covers the complete migration lifecycle: creating migrations with `npx supabase migration new`, writing zero-downtime schema changes that avoid table locks, backfilling data in batches, managing schema versioning across environments, planning rollback strategies, and regenerating TypeScript types after schema changes. Every pattern uses real Supabase CLI commands and `createClient` from `@supabase/supabase-js`.
39
+
40
+ **When to use:** Creating new database migrations, modifying production schemas without downtime, backfilling existing data after adding columns, managing migration history across dev/staging/production, rolling back failed migrations, or regenerating TypeScript types.
19
41
 
20
42
  ## Prerequisites
21
- - Current system documentation
22
- - Supabase SDK installed
23
- - Feature flag infrastructure
24
- - Rollback strategy tested
25
43
 
26
- ## Migration Types
44
+ - Supabase CLI installed: `npm install -g supabase` or `npx supabase --version`
45
+ - `@supabase/supabase-js` v2+ installed in your project
46
+ - Local Supabase running: `npx supabase start`
47
+ - Understanding of PostgreSQL DDL and transaction behavior
27
48
 
28
- | Type | Complexity | Duration | Risk |
29
- |------|-----------|----------|------|
30
- | Fresh install | Low | Days | Low |
31
- | From competitor | Medium | Weeks | Medium |
32
- | Major version | Medium | Weeks | Medium |
33
- | Full replatform | High | Months | High |
49
+ ## Instructions
50
+
51
+ ### Step 1: Create and Manage Migrations
34
52
 
35
- ## Pre-Migration Assessment
53
+ Use the Supabase CLI to create, test, and apply migrations. Each migration is a timestamped SQL file that runs in order.
54
+
55
+ **Create a new migration:**
36
56
 
37
- ### Step 1: Current State Analysis
38
57
  ```bash
39
- # Document current implementation
40
- find . -name "*.ts" -o -name "*.py" | xargs grep -l "supabase" > supabase-files.txt
58
+ # Create a migration file with a descriptive name
59
+ npx supabase migration new add_profiles_table
60
+ # Creates: supabase/migrations/20260322120000_add_profiles_table.sql
41
61
 
42
- # Count integration points
43
- wc -l supabase-files.txt
62
+ # List all migrations and their status
63
+ npx supabase migration list
44
64
 
45
- # Identify dependencies
46
- npm list | grep supabase
47
- pip freeze | grep supabase
65
+ # Check which migrations have been applied locally
66
+ npx supabase db reset --dry-run
48
67
  ```
49
68
 
50
- ### Step 2: Data Inventory
51
- ```typescript
52
- interface MigrationInventory {
53
- dataTypes: string[];
54
- recordCounts: Record<string, number>;
55
- dependencies: string[];
56
- integrationPoints: string[];
57
- customizations: string[];
58
- }
59
-
60
- async function assessSupabaseMigration(): Promise<MigrationInventory> {
61
- return {
62
- dataTypes: await getDataTypes(),
63
- recordCounts: await getRecordCounts(),
64
- dependencies: await analyzeDependencies(),
65
- integrationPoints: await findIntegrationPoints(),
66
- customizations: await documentCustomizations(),
67
- };
68
- }
69
+ **Write the migration SQL:**
70
+
71
+ ```sql
72
+ -- supabase/migrations/20260322120000_add_profiles_table.sql
73
+
74
+ -- Create the profiles table
75
+ CREATE TABLE public.profiles (
76
+ id uuid REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
77
+ email text UNIQUE NOT NULL,
78
+ full_name text,
79
+ avatar_url text,
80
+ bio text,
81
+ created_at timestamptz DEFAULT now(),
82
+ updated_at timestamptz DEFAULT now()
83
+ );
84
+
85
+ -- Enable RLS
86
+ ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
87
+
88
+ -- Create policies
89
+ CREATE POLICY "users_read_own_profile" ON public.profiles
90
+ FOR SELECT USING (auth.uid() = id);
91
+
92
+ CREATE POLICY "users_update_own_profile" ON public.profiles
93
+ FOR UPDATE USING (auth.uid() = id)
94
+ WITH CHECK (auth.uid() = id);
95
+
96
+ -- Create an index for email lookups
97
+ CREATE INDEX idx_profiles_email ON public.profiles(email);
98
+
99
+ -- Auto-create profile on user signup (trigger)
100
+ CREATE OR REPLACE FUNCTION public.handle_new_user()
101
+ RETURNS trigger AS $$
102
+ BEGIN
103
+ INSERT INTO public.profiles (id, email, full_name, avatar_url)
104
+ VALUES (
105
+ new.id,
106
+ new.email,
107
+ new.raw_user_meta_data ->> 'full_name',
108
+ new.raw_user_meta_data ->> 'avatar_url'
109
+ );
110
+ RETURN new;
111
+ END;
112
+ $$ LANGUAGE plpgsql SECURITY DEFINER;
113
+
114
+ CREATE TRIGGER on_auth_user_created
115
+ AFTER INSERT ON auth.users
116
+ FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
117
+
118
+ -- Updated_at trigger
119
+ CREATE OR REPLACE FUNCTION public.update_updated_at()
120
+ RETURNS trigger AS $$
121
+ BEGIN
122
+ new.updated_at = now();
123
+ RETURN new;
124
+ END;
125
+ $$ LANGUAGE plpgsql;
126
+
127
+ CREATE TRIGGER set_updated_at
128
+ BEFORE UPDATE ON public.profiles
129
+ FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();
69
130
  ```
70
131
 
71
- ## Migration Strategy: Strangler Fig Pattern
132
+ **Test the migration locally:**
72
133
 
134
+ ```bash
135
+ # Apply all migrations and seed data (destructive — resets local DB)
136
+ npx supabase db reset
137
+
138
+ # Run pgTAP tests if configured
139
+ npx supabase test db
140
+
141
+ # Verify the schema
142
+ npx supabase db lint
143
+
144
+ # Generate updated TypeScript types
145
+ npx supabase gen types typescript --local > lib/database.types.ts
73
146
  ```
74
- Phase 1: Parallel Run
75
- ┌─────────────┐ ┌─────────────┐
76
- │ Old │ │ New │
77
- │ System │ ──▶ │ Supabase │
78
- │ (100%) │ │ (0%) │
79
- └─────────────┘ └─────────────┘
80
-
81
- Phase 2: Gradual Shift
82
- ┌─────────────┐ ┌─────────────┐
83
- │ Old │ │ New │
84
- │ (50%) │ ──▶ │ (50%) │
85
- └─────────────┘ └─────────────┘
86
-
87
- Phase 3: Complete
88
- ┌─────────────┐ ┌─────────────┐
89
- │ Old │ │ New │
90
- │ (0%) │ ──▶ │ (100%) │
91
- └─────────────┘ └─────────────┘
147
+
148
+ **Apply migrations to remote environments:**
149
+
150
+ ```text
151
+ # Push to staging
152
+ npx supabase link --project-ref <staging-ref>
153
+ npx supabase db push
154
+ # Verify: npx supabase migration list --linked
155
+
156
+ # Push to production (same migration files)
157
+ npx supabase link --project-ref <prod-ref>
158
+ npx supabase db push
92
159
  ```
93
160
 
94
- ## Implementation Plan
161
+ ### Step 2: Zero-Downtime Migration Patterns
95
162
 
96
- ### Phase 1: Setup (Week 1-2)
97
- ```bash
98
- # Install Supabase SDK
99
- npm install @supabase/supabase-js
163
+ Production schema changes must avoid locking tables. These patterns ensure migrations complete without blocking reads or writes.
100
164
 
101
- # Configure credentials
102
- cp .env.example .env.supabase
103
- # Edit with new credentials
165
+ **Add a column (safe — no lock):**
104
166
 
105
- # Verify connectivity
106
- node -e "require('@supabase/supabase-js').ping()"
167
+ ```sql
168
+ -- supabase/migrations/20260323000000_add_status_column.sql
169
+
170
+ -- Adding a nullable column with a default does NOT lock the table in Postgres 11+
171
+ ALTER TABLE public.orders ADD COLUMN status text DEFAULT 'pending';
172
+
173
+ -- Create an index CONCURRENTLY (does not block writes)
174
+ -- NOTE: CONCURRENTLY cannot run inside a transaction block
175
+ -- Supabase migrations run each file in a transaction, so use a separate migration
107
176
  ```
108
177
 
109
- ### Phase 2: Adapter Layer (Week 3-4)
110
- ```typescript
111
- // src/adapters/supabase.ts
112
- interface ServiceAdapter {
113
- create(data: CreateInput): Promise<Resource>;
114
- read(id: string): Promise<Resource>;
115
- update(id: string, data: UpdateInput): Promise<Resource>;
116
- delete(id: string): Promise<void>;
117
- }
178
+ ```sql
179
+ -- supabase/migrations/20260323000001_add_status_index.sql
118
180
 
119
- class SupabaseAdapter implements ServiceAdapter {
120
- async create(data: CreateInput): Promise<Resource> {
121
- const supabaseData = this.transform(data);
122
- return supabaseClient.create(supabaseData);
123
- }
181
+ -- This migration must run outside a transaction for CONCURRENTLY
182
+ -- Add this comment at the top of the file:
183
+ -- supabase:disable-transaction
124
184
 
125
- private transform(data: CreateInput): SupabaseInput {
126
- // Map from old format to Supabase format
127
- }
128
- }
185
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_orders_status
186
+ ON public.orders(status);
129
187
  ```
130
188
 
131
- ### Phase 3: Data Migration (Week 5-6)
132
- ```typescript
133
- async function migrateSupabaseData(): Promise<MigrationResult> {
134
- const batchSize = 100;
135
- let processed = 0;
136
- let errors: MigrationError[] = [];
137
-
138
- for await (const batch of oldSystem.iterateBatches(batchSize)) {
139
- try {
140
- const transformed = batch.map(transform);
141
- await supabaseClient.batchCreate(transformed);
142
- processed += batch.length;
143
- } catch (error) {
144
- errors.push({ batch, error });
145
- }
146
-
147
- // Progress update
148
- console.log(`Migrated ${processed} records`);
149
- }
150
-
151
- return { processed, errors };
152
- }
189
+ **Rename a column (two-phase approach):**
190
+
191
+ ```sql
192
+ -- Phase 1: Add new column, backfill, update application code
193
+ -- supabase/migrations/20260324000000_add_display_name.sql
194
+
195
+ -- Add the new column
196
+ ALTER TABLE public.profiles ADD COLUMN display_name text;
197
+
198
+ -- Copy data from old column
199
+ UPDATE public.profiles SET display_name = full_name WHERE display_name IS NULL;
200
+
201
+ -- Create a trigger to keep both columns in sync during transition
202
+ CREATE OR REPLACE FUNCTION sync_name_columns()
203
+ RETURNS trigger AS $$
204
+ BEGIN
205
+ IF TG_OP = 'INSERT' OR NEW.full_name IS DISTINCT FROM OLD.full_name THEN
206
+ NEW.display_name = NEW.full_name;
207
+ END IF;
208
+ IF TG_OP = 'INSERT' OR NEW.display_name IS DISTINCT FROM OLD.display_name THEN
209
+ NEW.full_name = NEW.display_name;
210
+ END IF;
211
+ RETURN NEW;
212
+ END;
213
+ $$ LANGUAGE plpgsql;
214
+
215
+ CREATE TRIGGER sync_names
216
+ BEFORE INSERT OR UPDATE ON public.profiles
217
+ FOR EACH ROW EXECUTE FUNCTION sync_name_columns();
153
218
  ```
154
219
 
155
- ### Phase 4: Traffic Shift (Week 7-8)
156
- ```typescript
157
- // Feature flag controlled traffic split
158
- function getServiceAdapter(): ServiceAdapter {
159
- const supabasePercentage = getFeatureFlag('supabase_migration_percentage');
220
+ ```sql
221
+ -- Phase 2: After all application code uses display_name (deploy + verify)
222
+ -- supabase/migrations/20260325000000_drop_full_name.sql
160
223
 
161
- if (Math.random() * 100 < supabasePercentage) {
162
- return new SupabaseAdapter();
163
- }
224
+ -- Remove the sync trigger
225
+ DROP TRIGGER IF EXISTS sync_names ON public.profiles;
226
+ DROP FUNCTION IF EXISTS sync_name_columns();
164
227
 
165
- return new LegacyAdapter();
166
- }
228
+ -- Drop the old column
229
+ ALTER TABLE public.profiles DROP COLUMN full_name;
167
230
  ```
168
231
 
169
- ## Rollback Plan
232
+ **Change column type (safe approach):**
170
233
 
171
- ```bash
172
- # Immediate rollback
173
- kubectl set env deployment/app SUPABASE_ENABLED=false
174
- kubectl rollout restart deployment/app
234
+ ```sql
235
+ -- supabase/migrations/20260326000000_change_price_to_numeric.sql
236
+
237
+ -- DON'T DO THIS (locks table for the entire rewrite):
238
+ -- ALTER TABLE orders ALTER COLUMN price TYPE numeric(10,2);
239
+
240
+ -- SAFE: Add new column, backfill, swap
241
+ ALTER TABLE public.orders ADD COLUMN price_numeric numeric(10,2);
175
242
 
176
- # Data rollback (if needed)
177
- ./scripts/restore-from-backup.sh --date YYYY-MM-DD
243
+ -- Backfill in a separate migration or via application code
244
+ UPDATE public.orders SET price_numeric = price::numeric(10,2)
245
+ WHERE price_numeric IS NULL;
178
246
 
179
- # Verify rollback
180
- curl https://app.yourcompany.com/health | jq '.services.supabase'
247
+ -- After verifying all data is backfilled:
248
+ -- ALTER TABLE public.orders DROP COLUMN price;
249
+ -- ALTER TABLE public.orders RENAME COLUMN price_numeric TO price;
181
250
  ```
182
251
 
183
- ## Post-Migration Validation
252
+ **Verify zero-downtime from the SDK:**
184
253
 
185
254
  ```typescript
186
- async function validateSupabaseMigration(): Promise<ValidationReport> {
187
- const checks = [
188
- { name: 'Data count match', fn: checkDataCounts },
189
- { name: 'API functionality', fn: checkApiFunctionality },
190
- { name: 'Performance baseline', fn: checkPerformance },
191
- { name: 'Error rates', fn: checkErrorRates },
192
- ];
193
-
194
- const results = await Promise.all(
195
- checks.map(async c => ({ name: c.name, result: await c.fn() }))
196
- );
255
+ import { createClient } from '@supabase/supabase-js';
256
+
257
+ const supabase = createClient(
258
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
259
+ process.env.SUPABASE_SERVICE_ROLE_KEY!,
260
+ { auth: { autoRefreshToken: false, persistSession: false } }
261
+ );
262
+
263
+ // Run during migration to verify no downtime
264
+ async function migrationHealthCheck(tableName: string) {
265
+ const checks = [];
266
+
267
+ for (let i = 0; i < 10; i++) {
268
+ const start = performance.now();
269
+ const { error } = await supabase
270
+ .from(tableName)
271
+ .select('id')
272
+ .limit(1);
273
+
274
+ checks.push({
275
+ attempt: i + 1,
276
+ latencyMs: Math.round(performance.now() - start),
277
+ success: !error,
278
+ error: error?.message,
279
+ });
280
+
281
+ await new Promise((r) => setTimeout(r, 1000));
282
+ }
197
283
 
198
- return { checks: results, passed: results.every(r => r.result.success) };
284
+ const failures = checks.filter((c) => !c.success);
285
+ console.log(`Health check: ${checks.length - failures.length}/${checks.length} passed`);
286
+ if (failures.length > 0) {
287
+ console.warn('Failures:', failures);
288
+ }
199
289
  }
200
290
  ```
201
291
 
202
- ## Instructions
203
-
204
- ### Step 1: Assess Current State
205
- Document existing implementation and data inventory.
292
+ ### Step 3: Data Backfill, Versioning, and Rollback
206
293
 
207
- ### Step 2: Build Adapter Layer
208
- Create abstraction layer for gradual migration.
294
+ See [data backfill, versioning, and rollback](references/backfill-versioning-rollback.md) for batch backfill patterns with the SDK, schema versioning across environments, three rollback strategies (compensating migration, repair, feature flags), and type regeneration after migrations.
209
295
 
210
- ### Step 3: Migrate Data
211
- Run batch data migration with error handling.
296
+ ## Output
212
297
 
213
- ### Step 4: Shift Traffic
214
- Gradually route traffic to new Supabase integration.
298
+ After completing this skill, you will have:
215
299
 
216
- ## Output
217
- - Migration assessment complete
218
- - Adapter layer implemented
219
- - Data migrated successfully
220
- - Traffic fully shifted to Supabase
300
+ - **Migration creation workflow** — `npx supabase migration new` with descriptive SQL files and local testing
301
+ - **Zero-downtime patterns** — safe column additions, two-phase renames, concurrent index creation
302
+ - **Batch backfill** — SDK-based row-by-row updates with progress logging and rate limiting
303
+ - **Schema versioning** — `supabase migration list` and `db diff` for comparing environments
304
+ - **Rollback strategies** compensating migrations, `migration repair`, and feature-flagged schema changes
305
+ - **Type regeneration** — `supabase gen types typescript` after every schema change
306
+ - **Migration promotion** — `db push` workflow from local to staging to production
221
307
 
222
308
  ## Error Handling
223
- | Issue | Cause | Solution |
309
+
310
+ | Error | Cause | Solution |
224
311
  |-------|-------|----------|
225
- | Data mismatch | Transform errors | Validate transform logic |
226
- | Performance drop | No caching | Add caching layer |
227
- | Rollback triggered | Errors spiked | Reduce traffic percentage |
228
- | Validation failed | Missing data | Check batch processing |
312
+ | `migration has already been applied` | Re-running existing migration | Use `supabase migration list` to check status; never modify applied migrations |
313
+ | `cannot run inside a transaction block` | `CREATE INDEX CONCURRENTLY` in transaction | Add `-- supabase:disable-transaction` comment at top of migration file |
314
+ | `column does not exist` after migration | Migration not applied or types stale | Run `supabase db push` then `supabase gen types typescript` |
315
+ | `deadlock detected` during backfill | Concurrent updates on same rows | Reduce batch size; add retry logic with exponential backoff |
316
+ | `statement timeout` on large table | Migration takes longer than timeout | Increase `statement_timeout` in migration: `SET statement_timeout = '300s';` |
317
+ | `migration repair` failed | Wrong version number | Use exact version from `supabase migration list` (the timestamp prefix) |
318
+ | `db diff` shows unexpected changes | Schema drift from manual SQL Editor changes | Run `supabase db pull` to capture manual changes as a migration |
319
+ | Type mismatch after migration | Generated types don't match new schema | Delete `database.types.ts` and regenerate from `--local` or `--linked` |
229
320
 
230
321
  ## Examples
231
322
 
232
- ### Quick Migration Status
323
+ **Example 1 Complete migration workflow:**
324
+
325
+ ```text
326
+ # 1. Create migration
327
+ npx supabase migration new add_tags_to_projects
328
+
329
+ # 2. Write SQL
330
+ cat > supabase/migrations/20260322150000_add_tags_to_projects.sql << 'SQL'
331
+ ALTER TABLE public.projects ADD COLUMN tags text[] DEFAULT '{}';
332
+ CREATE INDEX idx_projects_tags ON public.projects USING GIN(tags);
333
+ SQL
334
+
335
+ # 3. Test locally
336
+ npx supabase db reset
337
+ npx supabase gen types typescript --local > lib/database.types.ts
338
+
339
+ # 4. Push to staging
340
+ npx supabase link --project-ref <staging-ref>
341
+ npx supabase db push
342
+
343
+ # 5. Push to production
344
+ npx supabase link --project-ref <prod-ref>
345
+ npx supabase db push
346
+ ```
347
+
348
+ **Example 2 — Backfill with progress tracking:**
349
+
233
350
  ```typescript
234
- const status = await validateSupabaseMigration();
235
- console.log(`Migration ${status.passed ? 'PASSED' : 'FAILED'}`);
236
- status.checks.forEach(c => console.log(` ${c.name}: ${c.result.success}`));
351
+ import { createClient } from '@supabase/supabase-js';
352
+
353
+ const supabase = createClient(url, serviceRoleKey, {
354
+ auth: { autoRefreshToken: false, persistSession: false },
355
+ });
356
+
357
+ // Backfill default tags for existing projects
358
+ const { count } = await supabase
359
+ .from('projects')
360
+ .select('*', { count: 'exact', head: true })
361
+ .is('tags', null);
362
+
363
+ console.log(`${count} projects need backfill`);
364
+
365
+ await backfillColumn('projects', 'tags', (row) => {
366
+ // Derive tags from project name and description
367
+ const tags: string[] = [];
368
+ if (row.name?.includes('API')) tags.push('api');
369
+ if (row.name?.includes('Web')) tags.push('web');
370
+ return tags.length > 0 ? tags : ['untagged'];
371
+ });
372
+ ```
373
+
374
+ **Example 3 — Safe enum migration:**
375
+
376
+ ```sql
377
+ -- supabase/migrations/20260328000000_add_order_status_enum.sql
378
+
379
+ -- DON'T: ALTER TYPE with new values inside a transaction
380
+ -- DO: Use text with CHECK constraint instead
381
+
382
+ ALTER TABLE public.orders
383
+ ADD CONSTRAINT chk_order_status
384
+ CHECK (status IN ('pending', 'processing', 'shipped', 'delivered', 'cancelled'));
385
+
386
+ -- To add a new status later, just drop and recreate the constraint:
387
+ -- ALTER TABLE public.orders DROP CONSTRAINT chk_order_status;
388
+ -- ALTER TABLE public.orders ADD CONSTRAINT chk_order_status
389
+ -- CHECK (status IN ('pending', 'processing', 'shipped', 'delivered', 'cancelled', 'refunded'));
237
390
  ```
238
391
 
239
392
  ## Resources
240
- - [Strangler Fig Pattern](https://martinfowler.com/bliki/StranglerFigApplication.html)
241
- - [Supabase Migration Guide](https://supabase.com/docs/migration)
242
393
 
243
- ## Flagship+ Skills
244
- For advanced troubleshooting, see `supabase-advanced-troubleshooting`.
394
+ - [Database Migrations — Supabase Docs](https://supabase.com/docs/guides/deployment/database-migrations)
395
+ - [Supabase CLI Migration Commands](https://supabase.com/docs/reference/cli/supabase-migration)
396
+ - [supabase db push — Supabase Docs](https://supabase.com/docs/reference/cli/supabase-db-push)
397
+ - [supabase gen types — Supabase Docs](https://supabase.com/docs/reference/cli/supabase-gen-types)
398
+ - [Zero-Downtime PostgreSQL Migrations](https://www.postgresql.org/docs/current/sql-altertable.html)
399
+ - [supabase db diff — Supabase Docs](https://supabase.com/docs/reference/cli/supabase-db-diff)
400
+
401
+ ## Next Steps
402
+
403
+ - For advanced troubleshooting after migrations, see `supabase-advanced-troubleshooting`
404
+ - For multi-environment migration promotion, see `supabase-multi-env-setup`
405
+ - For performance tuning after schema changes, see `supabase-performance-tuning`