@intentsolutionsio/vercel-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 (124) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +67 -44
  3. package/package.json +4 -4
  4. package/skills/vercel-advanced-troubleshooting/SKILL.md +185 -195
  5. package/skills/vercel-advanced-troubleshooting/references/errors.md +11 -0
  6. package/skills/vercel-advanced-troubleshooting/references/evidence-collection-framework.md +34 -0
  7. package/skills/vercel-advanced-troubleshooting/references/examples.md +11 -0
  8. package/skills/vercel-advanced-troubleshooting/references/systematic-isolation.md +56 -0
  9. package/skills/vercel-advanced-troubleshooting/references/timing-analysis.md +35 -0
  10. package/skills/vercel-architecture-variants/SKILL.md +227 -216
  11. package/skills/vercel-architecture-variants/references/errors.md +11 -0
  12. package/skills/vercel-architecture-variants/references/examples.md +12 -0
  13. package/skills/vercel-architecture-variants/references/variant-a-monolith-(simple).md +44 -0
  14. package/skills/vercel-architecture-variants/references/variant-b-service-layer-(moderate).md +72 -0
  15. package/skills/vercel-architecture-variants/references/variant-c-microservice-(complex).md +81 -0
  16. package/skills/vercel-ci-integration/SKILL.md +183 -73
  17. package/skills/vercel-ci-integration/references/errors.md +10 -0
  18. package/skills/vercel-ci-integration/references/examples.md +36 -0
  19. package/skills/vercel-ci-integration/references/implementation.md +54 -0
  20. package/skills/vercel-common-errors/SKILL.md +164 -60
  21. package/skills/vercel-common-errors/references/errors.md +53 -0
  22. package/skills/vercel-common-errors/references/examples.md +23 -0
  23. package/skills/vercel-cost-tuning/SKILL.md +158 -145
  24. package/skills/vercel-cost-tuning/references/cost-estimation.md +34 -0
  25. package/skills/vercel-cost-tuning/references/cost-reduction-strategies.md +40 -0
  26. package/skills/vercel-cost-tuning/references/errors.md +11 -0
  27. package/skills/vercel-cost-tuning/references/examples.md +15 -0
  28. package/skills/vercel-data-handling/SKILL.md +202 -155
  29. package/skills/vercel-data-handling/references/errors.md +11 -0
  30. package/skills/vercel-data-handling/references/examples.md +27 -0
  31. package/skills/vercel-data-handling/references/implementation.md +223 -0
  32. package/skills/vercel-debug-bundle/SKILL.md +163 -67
  33. package/skills/vercel-debug-bundle/references/errors.md +12 -0
  34. package/skills/vercel-debug-bundle/references/examples.md +24 -0
  35. package/skills/vercel-debug-bundle/references/implementation.md +54 -0
  36. package/skills/vercel-deploy-integration/SKILL.md +163 -156
  37. package/skills/vercel-deploy-integration/references/errors.md +11 -0
  38. package/skills/vercel-deploy-integration/references/examples.md +21 -0
  39. package/skills/vercel-deploy-integration/references/google-cloud-run.md +36 -0
  40. package/skills/vercel-deploy-integration/references/vercel-deployment.md +35 -0
  41. package/skills/vercel-deploy-preview/SKILL.md +164 -39
  42. package/skills/vercel-edge-functions/SKILL.md +185 -37
  43. package/skills/vercel-enterprise-rbac/SKILL.md +185 -170
  44. package/skills/vercel-enterprise-rbac/references/errors.md +11 -0
  45. package/skills/vercel-enterprise-rbac/references/examples.md +12 -0
  46. package/skills/vercel-enterprise-rbac/references/role-implementation.md +33 -0
  47. package/skills/vercel-enterprise-rbac/references/sso-integration.md +35 -0
  48. package/skills/vercel-hello-world/SKILL.md +141 -55
  49. package/skills/vercel-incident-runbook/SKILL.md +186 -138
  50. package/skills/vercel-incident-runbook/references/errors.md +11 -0
  51. package/skills/vercel-incident-runbook/references/examples.md +10 -0
  52. package/skills/vercel-incident-runbook/references/immediate-actions-by-error-type.md +41 -0
  53. package/skills/vercel-install-auth/SKILL.md +130 -53
  54. package/skills/vercel-known-pitfalls/SKILL.md +235 -233
  55. package/skills/vercel-known-pitfalls/references/errors.md +11 -0
  56. package/skills/vercel-known-pitfalls/references/examples.md +12 -0
  57. package/skills/vercel-load-scale/SKILL.md +197 -204
  58. package/skills/vercel-load-scale/references/capacity-planning.md +47 -0
  59. package/skills/vercel-load-scale/references/errors.md +11 -0
  60. package/skills/vercel-load-scale/references/examples.md +26 -0
  61. package/skills/vercel-load-scale/references/load-testing-with-k6.md +59 -0
  62. package/skills/vercel-load-scale/references/scaling-patterns.md +65 -0
  63. package/skills/vercel-local-dev-loop/SKILL.md +159 -71
  64. package/skills/vercel-local-dev-loop/references/errors.md +11 -0
  65. package/skills/vercel-local-dev-loop/references/examples.md +21 -0
  66. package/skills/vercel-local-dev-loop/references/implementation.md +60 -0
  67. package/skills/vercel-migration-deep-dive/SKILL.md +202 -187
  68. package/skills/vercel-migration-deep-dive/references/errors.md +11 -0
  69. package/skills/vercel-migration-deep-dive/references/examples.md +12 -0
  70. package/skills/vercel-migration-deep-dive/references/implementation-plan.md +80 -0
  71. package/skills/vercel-migration-deep-dive/references/pre-migration-assessment.md +39 -0
  72. package/skills/vercel-multi-env-setup/SKILL.md +167 -164
  73. package/skills/vercel-multi-env-setup/references/configuration-structure.md +59 -0
  74. package/skills/vercel-multi-env-setup/references/errors.md +11 -0
  75. package/skills/vercel-multi-env-setup/references/examples.md +11 -0
  76. package/skills/vercel-observability/SKILL.md +205 -195
  77. package/skills/vercel-observability/references/alert-configuration.md +40 -0
  78. package/skills/vercel-observability/references/errors.md +11 -0
  79. package/skills/vercel-observability/references/examples.md +13 -0
  80. package/skills/vercel-observability/references/metrics-collection.md +65 -0
  81. package/skills/vercel-performance-tuning/SKILL.md +212 -156
  82. package/skills/vercel-performance-tuning/references/caching-strategy.md +49 -0
  83. package/skills/vercel-performance-tuning/references/errors.md +11 -0
  84. package/skills/vercel-performance-tuning/references/examples.md +13 -0
  85. package/skills/vercel-policy-guardrails/SKILL.md +276 -193
  86. package/skills/vercel-policy-guardrails/references/errors.md +11 -0
  87. package/skills/vercel-policy-guardrails/references/eslint-rules.md +46 -0
  88. package/skills/vercel-policy-guardrails/references/examples.md +10 -0
  89. package/skills/vercel-prod-checklist/SKILL.md +219 -94
  90. package/skills/vercel-prod-checklist/references/errors.md +11 -0
  91. package/skills/vercel-prod-checklist/references/examples.md +25 -0
  92. package/skills/vercel-prod-checklist/references/implementation.md +60 -0
  93. package/skills/vercel-rate-limits/SKILL.md +187 -100
  94. package/skills/vercel-rate-limits/references/errors.md +11 -0
  95. package/skills/vercel-rate-limits/references/examples.md +46 -0
  96. package/skills/vercel-rate-limits/references/implementation.md +66 -0
  97. package/skills/vercel-reference-architecture/SKILL.md +226 -180
  98. package/skills/vercel-reference-architecture/references/errors.md +11 -0
  99. package/skills/vercel-reference-architecture/references/examples.md +13 -0
  100. package/skills/vercel-reference-architecture/references/key-components.md +65 -0
  101. package/skills/vercel-reference-architecture/references/project-structure.md +40 -0
  102. package/skills/vercel-reliability-patterns/SKILL.md +272 -211
  103. package/skills/vercel-reliability-patterns/references/circuit-breaker.md +36 -0
  104. package/skills/vercel-reliability-patterns/references/dead-letter-queue.md +48 -0
  105. package/skills/vercel-reliability-patterns/references/errors.md +11 -0
  106. package/skills/vercel-reliability-patterns/references/examples.md +11 -0
  107. package/skills/vercel-reliability-patterns/references/idempotency-keys.md +36 -0
  108. package/skills/vercel-sdk-patterns/SKILL.md +264 -92
  109. package/skills/vercel-sdk-patterns/references/errors.md +11 -0
  110. package/skills/vercel-sdk-patterns/references/examples.md +45 -0
  111. package/skills/vercel-sdk-patterns/references/implementation.md +67 -0
  112. package/skills/vercel-security-basics/SKILL.md +186 -96
  113. package/skills/vercel-security-basics/references/errors.md +10 -0
  114. package/skills/vercel-security-basics/references/examples.md +70 -0
  115. package/skills/vercel-security-basics/references/implementation.md +39 -0
  116. package/skills/vercel-upgrade-migration/SKILL.md +167 -67
  117. package/skills/vercel-upgrade-migration/references/errors.md +10 -0
  118. package/skills/vercel-upgrade-migration/references/examples.md +51 -0
  119. package/skills/vercel-upgrade-migration/references/implementation.md +29 -0
  120. package/skills/vercel-webhooks-events/SKILL.md +208 -132
  121. package/skills/vercel-webhooks-events/references/errors.md +11 -0
  122. package/skills/vercel-webhooks-events/references/event-handler-pattern.md +37 -0
  123. package/skills/vercel-webhooks-events/references/examples.md +16 -0
  124. package/skills/vercel-webhooks-events/references/signature-verification.md +33 -0
@@ -1,290 +1,351 @@
1
1
  ---
2
2
  name: vercel-reliability-patterns
3
- description: |
4
- Implement Vercel reliability patterns including circuit breakers, idempotency, and graceful degradation.
5
- Use when building fault-tolerant Vercel integrations, implementing retry strategies,
3
+ description: 'Implement reliability patterns for Vercel deployments including circuit
4
+ breakers, retry logic, and graceful degradation.
5
+
6
+ Use when building fault-tolerant serverless functions, implementing retry strategies,
7
+
6
8
  or adding resilience to production Vercel services.
9
+
7
10
  Trigger with phrases like "vercel reliability", "vercel circuit breaker",
8
- "vercel idempotent", "vercel resilience", "vercel fallback", "vercel bulkhead".
11
+
12
+ "vercel resilience", "vercel fallback", "vercel graceful degradation".
13
+
14
+ '
9
15
  allowed-tools: Read, Write, Edit
10
16
  version: 1.0.0
11
17
  license: MIT
12
18
  author: Jeremy Longshore <jeremy@intentsolutions.io>
19
+ tags:
20
+ - saas
21
+ - vercel
22
+ - reliability
23
+ - resilience
24
+ - patterns
25
+ compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
13
26
  ---
14
-
15
27
  # Vercel Reliability Patterns
16
28
 
17
29
  ## Overview
18
- Production-grade reliability patterns for Vercel integrations.
30
+
31
+ Build fault-tolerant Vercel deployments with circuit breakers, retry logic, graceful degradation, and instant rollback integration. Addresses reliability at two levels: function-level resilience (protecting against dependency failures) and deployment-level resilience (protecting against bad deploys).
19
32
 
20
33
  ## Prerequisites
21
- - Understanding of circuit breaker pattern
22
- - opossum or similar library installed
23
- - Queue infrastructure for DLQ
24
- - Caching layer for fallbacks
25
34
 
26
- ## Circuit Breaker
35
+ - Vercel project deployed to production
36
+ - Understanding of failure modes in serverless
37
+ - External dependencies (databases, APIs) identified
38
+
39
+ ## Instructions
40
+
41
+ ### Step 1: Circuit Breaker for External Dependencies
27
42
 
28
43
  ```typescript
29
- import CircuitBreaker from 'opossum';
44
+ // lib/circuit-breaker.ts
45
+ type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
46
+
47
+ class CircuitBreaker {
48
+ private state: CircuitState = 'CLOSED';
49
+ private failures = 0;
50
+ private lastFailure = 0;
51
+ private readonly threshold: number;
52
+ private readonly resetTimeMs: number;
53
+
54
+ constructor(threshold = 5, resetTimeMs = 30000) {
55
+ this.threshold = threshold;
56
+ this.resetTimeMs = resetTimeMs;
57
+ }
30
58
 
31
- const vercelBreaker = new CircuitBreaker(
32
- async (operation: () => Promise<any>) => operation(),
33
- {
34
- timeout: 10000,
35
- errorThresholdPercentage: 50,
36
- resetTimeout: 30000,
37
- volumeThreshold: 10,
59
+ async call<T>(fn: () => Promise<T>, fallback: () => T): Promise<T> {
60
+ if (this.state === 'OPEN') {
61
+ if (Date.now() - this.lastFailure > this.resetTimeMs) {
62
+ this.state = 'HALF_OPEN';
63
+ } else {
64
+ console.warn('Circuit OPEN — returning fallback');
65
+ return fallback();
66
+ }
67
+ }
68
+
69
+ try {
70
+ const result = await fn();
71
+ this.onSuccess();
72
+ return result;
73
+ } catch (error) {
74
+ this.onFailure();
75
+ console.error('Circuit breaker caught error:', error);
76
+ return fallback();
77
+ }
38
78
  }
39
- );
40
79
 
41
- // Events
42
- vercelBreaker.on('open', () => {
43
- console.warn('Vercel circuit OPEN - requests failing fast');
44
- alertOps('Vercel circuit breaker opened');
45
- });
80
+ private onSuccess(): void {
81
+ this.failures = 0;
82
+ this.state = 'CLOSED';
83
+ }
46
84
 
47
- vercelBreaker.on('halfOpen', () => {
48
- console.info('Vercel circuit HALF-OPEN - testing recovery');
49
- });
85
+ private onFailure(): void {
86
+ this.failures++;
87
+ this.lastFailure = Date.now();
88
+ if (this.failures >= this.threshold) {
89
+ this.state = 'OPEN';
90
+ console.warn(`Circuit OPENED after ${this.failures} failures`);
91
+ }
92
+ }
93
+ }
50
94
 
51
- vercelBreaker.on('close', () => {
52
- console.info('Vercel circuit CLOSED - normal operation');
53
- });
95
+ // Usage in a serverless function:
96
+ const dbCircuit = new CircuitBreaker(3, 30000);
54
97
 
55
- // Usage
56
- async function safeVercelCall<T>(fn: () => Promise<T>): Promise<T> {
57
- return vercelBreaker.fire(fn);
98
+ export default async function handler(req, res) {
99
+ const users = await dbCircuit.call(
100
+ () => db.user.findMany({ take: 10 }),
101
+ () => [] // Fallback: empty array when DB is down
102
+ );
103
+ res.json({ users, degraded: users.length === 0 });
58
104
  }
59
105
  ```
60
106
 
61
- ## Idempotency Keys
107
+ **Important for serverless:** Circuit breaker state lives in a single function instance. Different instances have independent circuits. For global circuit state, use Vercel KV or Edge Config.
108
+
109
+ ### Step 2: Retry with Exponential Backoff
62
110
 
63
111
  ```typescript
64
- import { v4 as uuidv4 } from 'uuid';
65
- import crypto from 'crypto';
66
-
67
- // Generate deterministic idempotency key from input
68
- function generateIdempotencyKey(
69
- operation: string,
70
- params: Record<string, any>
71
- ): string {
72
- const data = JSON.stringify({ operation, params });
73
- return crypto.createHash('sha256').update(data).digest('hex');
112
+ // lib/retry.ts
113
+ interface RetryOptions {
114
+ maxRetries?: number;
115
+ baseDelayMs?: number;
116
+ maxDelayMs?: number;
117
+ retryOn?: (error: unknown) => boolean;
74
118
  }
75
119
 
76
- // Or use random key with storage
77
- class IdempotencyManager {
78
- private store: Map<string, { key: string; expiresAt: Date }> = new Map();
120
+ async function withRetry<T>(
121
+ fn: () => Promise<T>,
122
+ options: RetryOptions = {}
123
+ ): Promise<T> {
124
+ const { maxRetries = 3, baseDelayMs = 200, maxDelayMs = 5000, retryOn } = options;
79
125
 
80
- getOrCreate(operationId: string): string {
81
- const existing = this.store.get(operationId);
82
- if (existing && existing.expiresAt > new Date()) {
83
- return existing.key;
126
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
127
+ try {
128
+ return await fn();
129
+ } catch (error) {
130
+ if (attempt === maxRetries) throw error;
131
+ if (retryOn && !retryOn(error)) throw error;
132
+
133
+ const delay = Math.min(
134
+ baseDelayMs * Math.pow(2, attempt) + Math.random() * 200,
135
+ maxDelayMs
136
+ );
137
+ await new Promise(r => setTimeout(r, delay));
84
138
  }
85
-
86
- const key = uuidv4();
87
- this.store.set(operationId, {
88
- key,
89
- expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
90
- });
91
- return key;
92
139
  }
93
- }
94
- ```
95
-
96
- ## Bulkhead Pattern
97
-
98
- ```typescript
99
- import PQueue from 'p-queue';
100
-
101
- // Separate queues for different operations
102
- const vercelQueues = {
103
- critical: new PQueue({ concurrency: 10 }),
104
- normal: new PQueue({ concurrency: 5 }),
105
- bulk: new PQueue({ concurrency: 2 }),
106
- };
107
-
108
- async function prioritizedVercelCall<T>(
109
- priority: 'critical' | 'normal' | 'bulk',
110
- fn: () => Promise<T>
111
- ): Promise<T> {
112
- return vercelQueues[priority].add(fn);
140
+ throw new Error('Unreachable');
113
141
  }
114
142
 
115
- // Usage
116
- await prioritizedVercelCall('critical', () =>
117
- vercelClient.processPayment(order)
118
- );
119
-
120
- await prioritizedVercelCall('bulk', () =>
121
- vercelClient.syncCatalog(products)
143
+ // Usage:
144
+ const data = await withRetry(
145
+ () => fetch('https://api.example.com/data').then(r => {
146
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
147
+ return r.json();
148
+ }),
149
+ {
150
+ maxRetries: 3,
151
+ retryOn: (err) => {
152
+ // Only retry on network errors and 5xx, not 4xx
153
+ if (err instanceof TypeError) return true; // network error
154
+ return err.message?.includes('5');
155
+ },
156
+ }
122
157
  );
123
158
  ```
124
159
 
125
- ## Timeout Hierarchy
160
+ ### Step 3: Graceful Degradation with Stale Cache
126
161
 
127
162
  ```typescript
128
- const TIMEOUT_CONFIG = {
129
- connect: 5000, // Initial connection
130
- request: 30000, // Standard requests
131
- upload: 120000, // File uploads
132
- longPoll: 300000, // Webhook long-polling
133
- };
134
-
135
- async function timedoutVercelCall<T>(
136
- operation: 'connect' | 'request' | 'upload' | 'longPoll',
137
- fn: () => Promise<T>
138
- ): Promise<T> {
139
- const timeout = TIMEOUT_CONFIG[operation];
140
-
141
- return Promise.race([
142
- fn(),
143
- new Promise<never>((_, reject) =>
144
- setTimeout(() => reject(new Error(`Vercel ${operation} timeout`)), timeout)
145
- ),
146
- ]);
147
- }
148
- ```
149
-
150
- ## Graceful Degradation
163
+ // api/products.ts serve stale data when primary source is down
164
+ import { get, set } from '@vercel/kv';
151
165
 
152
- ```typescript
153
- interface VercelFallback {
154
- enabled: boolean;
155
- data: any;
156
- staleness: 'fresh' | 'stale' | 'very_stale';
157
- }
166
+ export default async function handler(req, res) {
167
+ const cacheKey = 'products:latest';
158
168
 
159
- async function withVercelFallback<T>(
160
- fn: () => Promise<T>,
161
- fallbackFn: () => Promise<T>
162
- ): Promise<{ data: T; fallback: boolean }> {
163
169
  try {
164
- const data = await fn();
165
- // Update cache for future fallback
166
- await updateFallbackCache(data);
167
- return { data, fallback: false };
170
+ // Try primary data source
171
+ const freshData = await fetchProductsFromDB();
172
+
173
+ // Update cache with fresh data
174
+ await set(cacheKey, JSON.stringify(freshData), { ex: 3600 });
175
+
176
+ res.setHeader('x-data-source', 'live');
177
+ res.json(freshData);
168
178
  } catch (error) {
169
- console.warn('Vercel failed, using fallback:', error.message);
170
- const data = await fallbackFn();
171
- return { data, fallback: true };
179
+ // Primary failed serve stale cache
180
+ const cachedData = await get(cacheKey);
181
+
182
+ if (cachedData) {
183
+ console.warn('Serving stale cache — primary source unavailable');
184
+ res.setHeader('x-data-source', 'cache-stale');
185
+ res.json(JSON.parse(cachedData as string));
186
+ } else {
187
+ // No cache available — return degraded response
188
+ res.setHeader('x-data-source', 'degraded');
189
+ res.status(503).json({
190
+ error: 'Service temporarily unavailable',
191
+ degraded: true,
192
+ });
193
+ }
172
194
  }
173
195
  }
174
196
  ```
175
197
 
176
- ## Dead Letter Queue
198
+ ### Step 4: Idempotency Keys for Mutations
177
199
 
178
200
  ```typescript
179
- interface DeadLetterEntry {
180
- id: string;
181
- operation: string;
182
- payload: any;
183
- error: string;
184
- attempts: number;
185
- lastAttempt: Date;
186
- }
201
+ // api/orders/route.ts — idempotent order creation
202
+ import { NextRequest, NextResponse } from 'next/server';
203
+ import { db } from '@/lib/db';
204
+
205
+ export async function POST(request: NextRequest) {
206
+ const idempotencyKey = request.headers.get('idempotency-key');
207
+ if (!idempotencyKey) {
208
+ return NextResponse.json(
209
+ { error: 'idempotency-key header required' },
210
+ { status: 400 }
211
+ );
212
+ }
187
213
 
188
- class VercelDeadLetterQueue {
189
- private queue: DeadLetterEntry[] = [];
214
+ // Check if this request was already processed
215
+ const existing = await db.idempotencyRecord.findUnique({
216
+ where: { key: idempotencyKey },
217
+ });
190
218
 
191
- add(entry: Omit<DeadLetterEntry, 'id' | 'lastAttempt'>): void {
192
- this.queue.push({
193
- ...entry,
194
- id: uuidv4(),
195
- lastAttempt: new Date(),
219
+ if (existing) {
220
+ // Return the cached response — same status and body
221
+ return NextResponse.json(JSON.parse(existing.responseBody), {
222
+ status: existing.responseStatus,
223
+ headers: { 'x-idempotent-replay': 'true' },
196
224
  });
197
225
  }
198
226
 
199
- async processOne(): Promise<boolean> {
200
- const entry = this.queue.shift();
201
- if (!entry) return false;
227
+ // Process the order
228
+ const body = await request.json();
229
+ const order = await db.order.create({ data: body });
202
230
 
203
- try {
204
- await vercelClient[entry.operation](entry.payload);
205
- console.log(`DLQ: Successfully reprocessed ${entry.id}`);
206
- return true;
207
- } catch (error) {
208
- entry.attempts++;
209
- entry.lastAttempt = new Date();
231
+ // Cache the response for idempotency
232
+ const responseBody = JSON.stringify({ order });
233
+ await db.idempotencyRecord.create({
234
+ data: { key: idempotencyKey, responseStatus: 201, responseBody },
235
+ });
210
236
 
211
- if (entry.attempts < 5) {
212
- this.queue.push(entry);
213
- } else {
214
- console.error(`DLQ: Giving up on ${entry.id} after 5 attempts`);
215
- await alertOnPermanentFailure(entry);
216
- }
217
- return false;
218
- }
219
- }
237
+ return NextResponse.json({ order }, { status: 201 });
220
238
  }
221
239
  ```
222
240
 
223
- ## Health Check with Degraded State
241
+ ### Step 5: Health Check with Dependency Status
224
242
 
225
243
  ```typescript
226
- type HealthStatus = 'healthy' | 'degraded' | 'unhealthy';
227
-
228
- async function vercelHealthCheck(): Promise<{
229
- status: HealthStatus;
230
- details: Record<string, any>;
231
- }> {
232
- const checks = {
233
- api: await checkApiConnectivity(),
234
- circuitBreaker: vercelBreaker.stats(),
235
- dlqSize: deadLetterQueue.size(),
236
- };
237
-
238
- const status: HealthStatus =
239
- !checks.api.connected ? 'unhealthy' :
240
- checks.circuitBreaker.state === 'open' ? 'degraded' :
241
- checks.dlqSize > 100 ? 'degraded' :
242
- 'healthy';
243
-
244
- return { status, details: checks };
244
+ // api/health/route.ts
245
+ export const dynamic = 'force-dynamic';
246
+
247
+ interface HealthCheck {
248
+ name: string;
249
+ check: () => Promise<boolean>;
250
+ }
251
+
252
+ const checks: HealthCheck[] = [
253
+ {
254
+ name: 'database',
255
+ check: async () => {
256
+ await db.$queryRaw`SELECT 1`;
257
+ return true;
258
+ },
259
+ },
260
+ {
261
+ name: 'cache',
262
+ check: async () => {
263
+ await kv.ping();
264
+ return true;
265
+ },
266
+ },
267
+ {
268
+ name: 'external-api',
269
+ check: async () => {
270
+ const r = await fetch('https://api.example.com/health', { signal: AbortSignal.timeout(3000) });
271
+ return r.ok;
272
+ },
273
+ },
274
+ ];
275
+
276
+ export async function GET() {
277
+ const results: Record<string, 'ok' | 'error'> = {};
278
+
279
+ await Promise.all(
280
+ checks.map(async ({ name, check }) => {
281
+ try {
282
+ await check();
283
+ results[name] = 'ok';
284
+ } catch {
285
+ results[name] = 'error';
286
+ }
287
+ })
288
+ );
289
+
290
+ const healthy = Object.values(results).every(v => v === 'ok');
291
+ return Response.json(
292
+ { status: healthy ? 'healthy' : 'degraded', checks: results },
293
+ { status: healthy ? 200 : 503 }
294
+ );
245
295
  }
246
296
  ```
247
297
 
248
- ## Instructions
298
+ ### Step 6: Deployment-Level Resilience
249
299
 
250
- ### Step 1: Implement Circuit Breaker
251
- Wrap Vercel calls with circuit breaker.
300
+ ```bash
301
+ # Instant rollback on health check failure (CI integration)
302
+ DEPLOY_URL=$(vercel --prod)
303
+ HEALTH=$(curl -s -o /dev/null -w "%{http_code}" "$DEPLOY_URL/api/health")
252
304
 
253
- ### Step 2: Add Idempotency Keys
254
- Generate deterministic keys for operations.
305
+ if [ "$HEALTH" != "200" ]; then
306
+ echo "Health check failed ($HEALTH) — rolling back"
307
+ vercel rollback
308
+ exit 1
309
+ fi
310
+ echo "Deployment healthy"
311
+ ```
255
312
 
256
- ### Step 3: Configure Bulkheads
257
- Separate queues for different priorities.
313
+ ## Reliability Patterns Summary
258
314
 
259
- ### Step 4: Set Up Dead Letter Queue
260
- Handle permanent failures gracefully.
315
+ | Pattern | Protects Against | Vercel Implementation |
316
+ |---------|-----------------|----------------------|
317
+ | Circuit breaker | Dependency degradation | In-function state or Edge Config |
318
+ | Retry + backoff | Transient failures | withRetry wrapper |
319
+ | Stale cache | Primary source outage | Vercel KV with TTL |
320
+ | Idempotency | Duplicate mutations | Database record per request |
321
+ | Health checks | Bad deployments | `/api/health` + rollback automation |
322
+ | Instant rollback | Deployment regression | `vercel rollback` in CI |
261
323
 
262
324
  ## Output
263
- - Circuit breaker protecting Vercel calls
264
- - Idempotency preventing duplicates
265
- - Bulkhead isolation implemented
266
- - DLQ for failed operations
267
325
 
268
- ## Error Handling
269
- | Issue | Cause | Solution |
270
- |-------|-------|----------|
271
- | Circuit stays open | Threshold too low | Adjust error percentage |
272
- | Duplicate operations | Missing idempotency | Add idempotency key |
273
- | Queue full | Rate too high | Increase concurrency |
274
- | DLQ growing | Persistent failures | Investigate root cause |
326
+ - Circuit breaker protecting all external dependency calls
327
+ - Retry logic with exponential backoff for transient failures
328
+ - Graceful degradation serving stale data when primary fails
329
+ - Idempotency preventing duplicate mutations
330
+ - Automated health check + rollback pipeline
275
331
 
276
- ## Examples
332
+ ## Error Handling
277
333
 
278
- ### Quick Circuit Check
279
- ```typescript
280
- const state = vercelBreaker.stats().state;
281
- console.log('Vercel circuit:', state);
282
- ```
334
+ | Error | Cause | Solution |
335
+ |-------|-------|----------|
336
+ | Circuit opens too aggressively | Threshold too low | Increase failure threshold (e.g., 5 → 10) |
337
+ | Retry causes duplicate side effects | No idempotency | Add idempotency-key to mutation endpoints |
338
+ | Stale cache expired | TTL too short or never populated | Increase TTL, seed cache on deploy |
339
+ | Health check false positive | Timeout too short | Increase AbortSignal timeout to 5s |
340
+ | Rollback reverts good deployment | Flaky health check | Add retry to health check before rollback |
283
341
 
284
342
  ## Resources
343
+
344
+ - [Vercel Instant Rollback](https://vercel.com/docs/instant-rollback)
345
+ - [Vercel KV](https://vercel.com/docs/storage/vercel-kv)
346
+ - [Edge Config](https://vercel.com/docs/edge-config)
285
347
  - [Circuit Breaker Pattern](https://martinfowler.com/bliki/CircuitBreaker.html)
286
- - [Opossum Documentation](https://nodeshift.dev/opossum/)
287
- - [Vercel Reliability Guide](https://vercel.com/docs/reliability)
288
348
 
289
349
  ## Next Steps
290
- For policy enforcement, see `vercel-policy-guardrails`.
350
+
351
+ For policy guardrails, see `vercel-policy-guardrails`.
@@ -0,0 +1,36 @@
1
+ # Circuit Breaker
2
+
3
+ ## Circuit Breaker
4
+
5
+ ```typescript
6
+ import CircuitBreaker from 'opossum';
7
+
8
+ const vercelBreaker = new CircuitBreaker(
9
+ async (operation: () => Promise<any>) => operation(),
10
+ {
11
+ timeout: 10000,
12
+ errorThresholdPercentage: 50,
13
+ resetTimeout: 30000,
14
+ volumeThreshold: 10,
15
+ }
16
+ );
17
+
18
+ // Events
19
+ vercelBreaker.on('open', () => {
20
+ console.warn('Vercel circuit OPEN - requests failing fast');
21
+ alertOps('Vercel circuit breaker opened');
22
+ });
23
+
24
+ vercelBreaker.on('halfOpen', () => {
25
+ console.info('Vercel circuit HALF-OPEN - testing recovery');
26
+ });
27
+
28
+ vercelBreaker.on('close', () => {
29
+ console.info('Vercel circuit CLOSED - normal operation');
30
+ });
31
+
32
+ // Usage
33
+ async function safeVercelCall<T>(fn: () => Promise<T>): Promise<T> {
34
+ return vercelBreaker.fire(fn);
35
+ }
36
+ ```
@@ -0,0 +1,48 @@
1
+ # Dead Letter Queue
2
+
3
+ ## Dead Letter Queue
4
+
5
+ ```typescript
6
+ interface DeadLetterEntry {
7
+ id: string;
8
+ operation: string;
9
+ payload: any;
10
+ error: string;
11
+ attempts: number;
12
+ lastAttempt: Date;
13
+ }
14
+
15
+ class VercelDeadLetterQueue {
16
+ private queue: DeadLetterEntry[] = [];
17
+
18
+ add(entry: Omit<DeadLetterEntry, 'id' | 'lastAttempt'>): void {
19
+ this.queue.push({
20
+ ...entry,
21
+ id: uuidv4(),
22
+ lastAttempt: new Date(),
23
+ });
24
+ }
25
+
26
+ async processOne(): Promise<boolean> {
27
+ const entry = this.queue.shift();
28
+ if (!entry) return false;
29
+
30
+ try {
31
+ await vercelCliententry.operation;
32
+ console.log(`DLQ: Successfully reprocessed ${entry.id}`);
33
+ return true;
34
+ } catch (error) {
35
+ entry.attempts++;
36
+ entry.lastAttempt = new Date();
37
+
38
+ if (entry.attempts < 5) {
39
+ this.queue.push(entry);
40
+ } else {
41
+ console.error(`DLQ: Giving up on ${entry.id} after 5 attempts`);
42
+ await alertOnPermanentFailure(entry);
43
+ }
44
+ return false;
45
+ }
46
+ }
47
+ }
48
+ ```
@@ -0,0 +1,11 @@
1
+ # Error Handling Reference
2
+
3
+ | Issue | Cause | Solution |
4
+ |-------|-------|----------|
5
+ | Circuit stays open | Threshold too low | Adjust error percentage |
6
+ | Duplicate operations | Missing idempotency | Add idempotency key |
7
+ | Queue full | Rate too high | Increase concurrency |
8
+ | DLQ growing | Persistent failures | Investigate root cause |
9
+
10
+ ---
11
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*
@@ -0,0 +1,11 @@
1
+ ## Examples
2
+
3
+ ### Quick Circuit Check
4
+
5
+ ```typescript
6
+ const state = vercelBreaker.stats().state;
7
+ console.log('Vercel circuit:', state);
8
+ ```
9
+
10
+ ---
11
+ *[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*