@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.
- package/LICENSE +1 -1
- package/README.md +67 -44
- package/package.json +4 -4
- package/skills/vercel-advanced-troubleshooting/SKILL.md +185 -195
- package/skills/vercel-advanced-troubleshooting/references/errors.md +11 -0
- package/skills/vercel-advanced-troubleshooting/references/evidence-collection-framework.md +34 -0
- package/skills/vercel-advanced-troubleshooting/references/examples.md +11 -0
- package/skills/vercel-advanced-troubleshooting/references/systematic-isolation.md +56 -0
- package/skills/vercel-advanced-troubleshooting/references/timing-analysis.md +35 -0
- package/skills/vercel-architecture-variants/SKILL.md +227 -216
- package/skills/vercel-architecture-variants/references/errors.md +11 -0
- package/skills/vercel-architecture-variants/references/examples.md +12 -0
- package/skills/vercel-architecture-variants/references/variant-a-monolith-(simple).md +44 -0
- package/skills/vercel-architecture-variants/references/variant-b-service-layer-(moderate).md +72 -0
- package/skills/vercel-architecture-variants/references/variant-c-microservice-(complex).md +81 -0
- package/skills/vercel-ci-integration/SKILL.md +183 -73
- package/skills/vercel-ci-integration/references/errors.md +10 -0
- package/skills/vercel-ci-integration/references/examples.md +36 -0
- package/skills/vercel-ci-integration/references/implementation.md +54 -0
- package/skills/vercel-common-errors/SKILL.md +164 -60
- package/skills/vercel-common-errors/references/errors.md +53 -0
- package/skills/vercel-common-errors/references/examples.md +23 -0
- package/skills/vercel-cost-tuning/SKILL.md +158 -145
- package/skills/vercel-cost-tuning/references/cost-estimation.md +34 -0
- package/skills/vercel-cost-tuning/references/cost-reduction-strategies.md +40 -0
- package/skills/vercel-cost-tuning/references/errors.md +11 -0
- package/skills/vercel-cost-tuning/references/examples.md +15 -0
- package/skills/vercel-data-handling/SKILL.md +202 -155
- package/skills/vercel-data-handling/references/errors.md +11 -0
- package/skills/vercel-data-handling/references/examples.md +27 -0
- package/skills/vercel-data-handling/references/implementation.md +223 -0
- package/skills/vercel-debug-bundle/SKILL.md +163 -67
- package/skills/vercel-debug-bundle/references/errors.md +12 -0
- package/skills/vercel-debug-bundle/references/examples.md +24 -0
- package/skills/vercel-debug-bundle/references/implementation.md +54 -0
- package/skills/vercel-deploy-integration/SKILL.md +163 -156
- package/skills/vercel-deploy-integration/references/errors.md +11 -0
- package/skills/vercel-deploy-integration/references/examples.md +21 -0
- package/skills/vercel-deploy-integration/references/google-cloud-run.md +36 -0
- package/skills/vercel-deploy-integration/references/vercel-deployment.md +35 -0
- package/skills/vercel-deploy-preview/SKILL.md +164 -39
- package/skills/vercel-edge-functions/SKILL.md +185 -37
- package/skills/vercel-enterprise-rbac/SKILL.md +185 -170
- package/skills/vercel-enterprise-rbac/references/errors.md +11 -0
- package/skills/vercel-enterprise-rbac/references/examples.md +12 -0
- package/skills/vercel-enterprise-rbac/references/role-implementation.md +33 -0
- package/skills/vercel-enterprise-rbac/references/sso-integration.md +35 -0
- package/skills/vercel-hello-world/SKILL.md +141 -55
- package/skills/vercel-incident-runbook/SKILL.md +186 -138
- package/skills/vercel-incident-runbook/references/errors.md +11 -0
- package/skills/vercel-incident-runbook/references/examples.md +10 -0
- package/skills/vercel-incident-runbook/references/immediate-actions-by-error-type.md +41 -0
- package/skills/vercel-install-auth/SKILL.md +130 -53
- package/skills/vercel-known-pitfalls/SKILL.md +235 -233
- package/skills/vercel-known-pitfalls/references/errors.md +11 -0
- package/skills/vercel-known-pitfalls/references/examples.md +12 -0
- package/skills/vercel-load-scale/SKILL.md +197 -204
- package/skills/vercel-load-scale/references/capacity-planning.md +47 -0
- package/skills/vercel-load-scale/references/errors.md +11 -0
- package/skills/vercel-load-scale/references/examples.md +26 -0
- package/skills/vercel-load-scale/references/load-testing-with-k6.md +59 -0
- package/skills/vercel-load-scale/references/scaling-patterns.md +65 -0
- package/skills/vercel-local-dev-loop/SKILL.md +159 -71
- package/skills/vercel-local-dev-loop/references/errors.md +11 -0
- package/skills/vercel-local-dev-loop/references/examples.md +21 -0
- package/skills/vercel-local-dev-loop/references/implementation.md +60 -0
- package/skills/vercel-migration-deep-dive/SKILL.md +202 -187
- package/skills/vercel-migration-deep-dive/references/errors.md +11 -0
- package/skills/vercel-migration-deep-dive/references/examples.md +12 -0
- package/skills/vercel-migration-deep-dive/references/implementation-plan.md +80 -0
- package/skills/vercel-migration-deep-dive/references/pre-migration-assessment.md +39 -0
- package/skills/vercel-multi-env-setup/SKILL.md +167 -164
- package/skills/vercel-multi-env-setup/references/configuration-structure.md +59 -0
- package/skills/vercel-multi-env-setup/references/errors.md +11 -0
- package/skills/vercel-multi-env-setup/references/examples.md +11 -0
- package/skills/vercel-observability/SKILL.md +205 -195
- package/skills/vercel-observability/references/alert-configuration.md +40 -0
- package/skills/vercel-observability/references/errors.md +11 -0
- package/skills/vercel-observability/references/examples.md +13 -0
- package/skills/vercel-observability/references/metrics-collection.md +65 -0
- package/skills/vercel-performance-tuning/SKILL.md +212 -156
- package/skills/vercel-performance-tuning/references/caching-strategy.md +49 -0
- package/skills/vercel-performance-tuning/references/errors.md +11 -0
- package/skills/vercel-performance-tuning/references/examples.md +13 -0
- package/skills/vercel-policy-guardrails/SKILL.md +276 -193
- package/skills/vercel-policy-guardrails/references/errors.md +11 -0
- package/skills/vercel-policy-guardrails/references/eslint-rules.md +46 -0
- package/skills/vercel-policy-guardrails/references/examples.md +10 -0
- package/skills/vercel-prod-checklist/SKILL.md +219 -94
- package/skills/vercel-prod-checklist/references/errors.md +11 -0
- package/skills/vercel-prod-checklist/references/examples.md +25 -0
- package/skills/vercel-prod-checklist/references/implementation.md +60 -0
- package/skills/vercel-rate-limits/SKILL.md +187 -100
- package/skills/vercel-rate-limits/references/errors.md +11 -0
- package/skills/vercel-rate-limits/references/examples.md +46 -0
- package/skills/vercel-rate-limits/references/implementation.md +66 -0
- package/skills/vercel-reference-architecture/SKILL.md +226 -180
- package/skills/vercel-reference-architecture/references/errors.md +11 -0
- package/skills/vercel-reference-architecture/references/examples.md +13 -0
- package/skills/vercel-reference-architecture/references/key-components.md +65 -0
- package/skills/vercel-reference-architecture/references/project-structure.md +40 -0
- package/skills/vercel-reliability-patterns/SKILL.md +272 -211
- package/skills/vercel-reliability-patterns/references/circuit-breaker.md +36 -0
- package/skills/vercel-reliability-patterns/references/dead-letter-queue.md +48 -0
- package/skills/vercel-reliability-patterns/references/errors.md +11 -0
- package/skills/vercel-reliability-patterns/references/examples.md +11 -0
- package/skills/vercel-reliability-patterns/references/idempotency-keys.md +36 -0
- package/skills/vercel-sdk-patterns/SKILL.md +264 -92
- package/skills/vercel-sdk-patterns/references/errors.md +11 -0
- package/skills/vercel-sdk-patterns/references/examples.md +45 -0
- package/skills/vercel-sdk-patterns/references/implementation.md +67 -0
- package/skills/vercel-security-basics/SKILL.md +186 -96
- package/skills/vercel-security-basics/references/errors.md +10 -0
- package/skills/vercel-security-basics/references/examples.md +70 -0
- package/skills/vercel-security-basics/references/implementation.md +39 -0
- package/skills/vercel-upgrade-migration/SKILL.md +167 -67
- package/skills/vercel-upgrade-migration/references/errors.md +10 -0
- package/skills/vercel-upgrade-migration/references/examples.md +51 -0
- package/skills/vercel-upgrade-migration/references/implementation.md +29 -0
- package/skills/vercel-webhooks-events/SKILL.md +208 -132
- package/skills/vercel-webhooks-events/references/errors.md +11 -0
- package/skills/vercel-webhooks-events/references/event-handler-pattern.md +37 -0
- package/skills/vercel-webhooks-events/references/examples.md +16 -0
- package/skills/vercel-webhooks-events/references/signature-verification.md +33 -0
|
@@ -1,274 +1,267 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vercel-load-scale
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
description: 'Load test and scale Vercel deployments with concurrency tuning and capacity
|
|
4
|
+
planning.
|
|
5
|
+
|
|
6
|
+
Use when running performance tests, planning for traffic spikes,
|
|
7
|
+
|
|
8
|
+
or optimizing serverless function scaling on Vercel.
|
|
9
|
+
|
|
7
10
|
Trigger with phrases like "vercel load test", "vercel scale",
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
|
|
12
|
+
"vercel performance test", "vercel capacity", "vercel benchmark".
|
|
13
|
+
|
|
14
|
+
'
|
|
15
|
+
allowed-tools: Read, Write, Edit, Bash(npx:*), Bash(vercel:*), Bash(curl:*)
|
|
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
|
+
- testing
|
|
23
|
+
- performance
|
|
24
|
+
- scaling
|
|
25
|
+
compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
|
|
13
26
|
---
|
|
14
|
-
|
|
15
27
|
# Vercel Load & Scale
|
|
16
28
|
|
|
17
29
|
## Overview
|
|
18
|
-
|
|
30
|
+
|
|
31
|
+
Load test Vercel deployments to identify scaling limits, cold start impact, and concurrency thresholds. Covers k6/autocannon test scripts, Vercel's auto-scaling model, Fluid Compute concurrency, and capacity planning.
|
|
19
32
|
|
|
20
33
|
## Prerequisites
|
|
21
|
-
- k6 load testing tool installed
|
|
22
|
-
- Kubernetes cluster with HPA configured
|
|
23
|
-
- Prometheus for metrics collection
|
|
24
|
-
- Test environment API keys
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
- Load testing tool: k6, autocannon, or artillery
|
|
36
|
+
- Test environment deployment (never load test production without approval)
|
|
37
|
+
- Access to Vercel Analytics for monitoring during tests
|
|
38
|
+
|
|
39
|
+
## Instructions
|
|
40
|
+
|
|
41
|
+
### Step 1: Understand Vercel's Scaling Model
|
|
42
|
+
|
|
43
|
+
Vercel serverless functions scale automatically:
|
|
44
|
+
|
|
45
|
+
| Behavior | Details |
|
|
46
|
+
|----------|---------|
|
|
47
|
+
| Scale-up | New function instances spawn on demand |
|
|
48
|
+
| Scale-down | Idle instances shut down after ~15 minutes |
|
|
49
|
+
| Cold starts | First request to a new instance pays initialization cost |
|
|
50
|
+
| Concurrency | Each instance handles one request at a time (by default) |
|
|
51
|
+
| Fluid Compute | Pro/Enterprise: multiple requests per instance |
|
|
52
|
+
|
|
53
|
+
**Concurrency limits by plan:**
|
|
54
|
+
|
|
55
|
+
| Plan | Max Concurrent Functions |
|
|
56
|
+
|------|------------------------|
|
|
57
|
+
| Hobby | 10 |
|
|
58
|
+
| Pro | 1,000 |
|
|
59
|
+
| Enterprise | 100,000 |
|
|
60
|
+
|
|
61
|
+
### Step 2: Basic Load Test with autocannon
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Install autocannon
|
|
65
|
+
npm install -g autocannon
|
|
66
|
+
|
|
67
|
+
# Test with 50 concurrent connections for 30 seconds
|
|
68
|
+
autocannon -c 50 -d 30 https://my-app-preview.vercel.app/api/endpoint
|
|
69
|
+
|
|
70
|
+
# Output includes:
|
|
71
|
+
# Latency: avg, p50, p99, max
|
|
72
|
+
# Requests/sec: avg, min, max
|
|
73
|
+
# Errors: timeouts, non-2xx responses
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Step 3: k6 Load Test Script
|
|
27
77
|
|
|
28
|
-
### Basic Load Test
|
|
29
78
|
```javascript
|
|
30
|
-
//
|
|
79
|
+
// load-test.js
|
|
31
80
|
import http from 'k6/http';
|
|
32
81
|
import { check, sleep } from 'k6';
|
|
82
|
+
import { Rate, Trend } from 'k6/metrics';
|
|
83
|
+
|
|
84
|
+
const errorRate = new Rate('errors');
|
|
85
|
+
const coldStartRate = new Rate('cold_starts');
|
|
86
|
+
const latency = new Trend('api_latency');
|
|
33
87
|
|
|
34
88
|
export const options = {
|
|
35
89
|
stages: [
|
|
36
|
-
{ duration: '
|
|
37
|
-
{ duration: '
|
|
38
|
-
{ duration: '2m', target:
|
|
39
|
-
{ duration: '
|
|
40
|
-
{ duration: '2m', target: 0 }, // Ramp down
|
|
90
|
+
{ duration: '1m', target: 10 }, // Warm up
|
|
91
|
+
{ duration: '3m', target: 50 }, // Ramp to 50 users
|
|
92
|
+
{ duration: '2m', target: 100 }, // Peak load
|
|
93
|
+
{ duration: '1m', target: 0 }, // Cool down
|
|
41
94
|
],
|
|
42
95
|
thresholds: {
|
|
43
|
-
http_req_duration: ['p(95)<
|
|
44
|
-
|
|
96
|
+
http_req_duration: ['p(95)<2000'], // P95 < 2s
|
|
97
|
+
errors: ['rate<0.01'], // Error rate < 1%
|
|
45
98
|
},
|
|
46
99
|
};
|
|
47
100
|
|
|
48
101
|
export default function () {
|
|
49
|
-
const
|
|
50
|
-
'https://api.vercel.com/v1/resource',
|
|
51
|
-
JSON.stringify({ test: true }),
|
|
52
|
-
{
|
|
53
|
-
headers: {
|
|
54
|
-
'Content-Type': 'application/json',
|
|
55
|
-
'Authorization': `Bearer ${__ENV.VERCEL_API_KEY}`,
|
|
56
|
-
},
|
|
57
|
-
}
|
|
58
|
-
);
|
|
102
|
+
const res = http.get('https://my-app-preview.vercel.app/api/endpoint');
|
|
59
103
|
|
|
60
|
-
check(
|
|
104
|
+
check(res, {
|
|
61
105
|
'status is 200': (r) => r.status === 200,
|
|
62
|
-
'latency <
|
|
106
|
+
'latency < 2s': (r) => r.timings.duration < 2000,
|
|
63
107
|
});
|
|
64
108
|
|
|
109
|
+
errorRate.add(res.status !== 200);
|
|
110
|
+
latency.add(res.timings.duration);
|
|
111
|
+
|
|
112
|
+
// Track cold starts if your API returns this header
|
|
113
|
+
if (res.headers['X-Cold-Start'] === 'true') {
|
|
114
|
+
coldStartRate.add(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
65
117
|
sleep(1);
|
|
66
118
|
}
|
|
67
119
|
```
|
|
68
120
|
|
|
69
|
-
### Run Load Test
|
|
70
121
|
```bash
|
|
71
|
-
#
|
|
72
|
-
|
|
73
|
-
# or: sudo apt install k6 # Linux
|
|
122
|
+
# Run the load test
|
|
123
|
+
k6 run load-test.js
|
|
74
124
|
|
|
75
|
-
# Run
|
|
76
|
-
k6 run --
|
|
77
|
-
|
|
78
|
-
# Run with output to InfluxDB
|
|
79
|
-
k6 run --out influxdb=http://localhost:8086/k6 vercel-load-test.js
|
|
125
|
+
# Run with output to JSON for analysis
|
|
126
|
+
k6 run --out json=results.json load-test.js
|
|
80
127
|
```
|
|
81
128
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
### Horizontal Scaling
|
|
85
|
-
```yaml
|
|
86
|
-
# kubernetes HPA
|
|
87
|
-
apiVersion: autoscaling/v2
|
|
88
|
-
kind: HorizontalPodAutoscaler
|
|
89
|
-
metadata:
|
|
90
|
-
name: vercel-integration-hpa
|
|
91
|
-
spec:
|
|
92
|
-
scaleTargetRef:
|
|
93
|
-
apiVersion: apps/v1
|
|
94
|
-
kind: Deployment
|
|
95
|
-
name: vercel-integration
|
|
96
|
-
minReplicas: 2
|
|
97
|
-
maxReplicas: 20
|
|
98
|
-
metrics:
|
|
99
|
-
- type: Resource
|
|
100
|
-
resource:
|
|
101
|
-
name: cpu
|
|
102
|
-
target:
|
|
103
|
-
type: Utilization
|
|
104
|
-
averageUtilization: 70
|
|
105
|
-
- type: Pods
|
|
106
|
-
pods:
|
|
107
|
-
metric:
|
|
108
|
-
name: vercel_queue_depth
|
|
109
|
-
target:
|
|
110
|
-
type: AverageValue
|
|
111
|
-
averageValue: 100
|
|
112
|
-
```
|
|
129
|
+
### Step 4: Cold Start Stress Test
|
|
113
130
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
import
|
|
131
|
+
```javascript
|
|
132
|
+
// cold-start-test.js — specifically test cold start behavior
|
|
133
|
+
import http from 'k6/http';
|
|
134
|
+
import { sleep } from 'k6';
|
|
117
135
|
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
136
|
+
export const options = {
|
|
137
|
+
scenarios: {
|
|
138
|
+
// Scenario 1: Sustained load (warm instances)
|
|
139
|
+
sustained: {
|
|
140
|
+
executor: 'constant-arrival-rate',
|
|
141
|
+
rate: 10,
|
|
142
|
+
timeUnit: '1s',
|
|
143
|
+
duration: '2m',
|
|
144
|
+
preAllocatedVUs: 20,
|
|
145
|
+
},
|
|
146
|
+
// Scenario 2: Spike (forces new cold starts)
|
|
147
|
+
spike: {
|
|
148
|
+
executor: 'ramping-arrival-rate',
|
|
149
|
+
startRate: 10,
|
|
150
|
+
timeUnit: '1s',
|
|
151
|
+
stages: [
|
|
152
|
+
{ target: 200, duration: '10s' }, // Sudden spike
|
|
153
|
+
{ target: 10, duration: '1m' }, // Return to normal
|
|
154
|
+
],
|
|
155
|
+
preAllocatedVUs: 300,
|
|
156
|
+
startTime: '2m', // Start after sustained phase
|
|
157
|
+
},
|
|
126
158
|
},
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
async function withVercelClient<T>(
|
|
133
|
-
fn: (client: VercelClient) => Promise<T>
|
|
134
|
-
): Promise<T> {
|
|
135
|
-
const client = await vercelPool.acquire();
|
|
136
|
-
try {
|
|
137
|
-
return await fn(client);
|
|
138
|
-
} finally {
|
|
139
|
-
vercelPool.release(client);
|
|
140
|
-
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export default function () {
|
|
162
|
+
const res = http.get('https://my-app-preview.vercel.app/api/endpoint');
|
|
163
|
+
// Log cold start timing for analysis
|
|
141
164
|
}
|
|
142
165
|
```
|
|
143
166
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
### Metrics to Monitor
|
|
147
|
-
| Metric | Warning | Critical |
|
|
148
|
-
|--------|---------|----------|
|
|
149
|
-
| CPU Utilization | > 70% | > 85% |
|
|
150
|
-
| Memory Usage | > 75% | > 90% |
|
|
151
|
-
| Request Queue Depth | > 100 | > 500 |
|
|
152
|
-
| Error Rate | > 1% | > 5% |
|
|
153
|
-
| P95 Latency | > 500ms | > 2000ms |
|
|
154
|
-
|
|
155
|
-
### Capacity Calculation
|
|
156
|
-
```typescript
|
|
157
|
-
interface CapacityEstimate {
|
|
158
|
-
currentRPS: number;
|
|
159
|
-
maxRPS: number;
|
|
160
|
-
headroom: number;
|
|
161
|
-
scaleRecommendation: string;
|
|
162
|
-
}
|
|
167
|
+
### Step 5: Fluid Compute Concurrency Tuning
|
|
163
168
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
currentRPS,
|
|
177
|
-
maxRPS: Math.floor(maxRPS),
|
|
178
|
-
headroom: Math.round(headroom),
|
|
179
|
-
scaleRecommendation: headroom < 30
|
|
180
|
-
? 'Scale up soon'
|
|
181
|
-
: headroom < 50
|
|
182
|
-
? 'Monitor closely'
|
|
183
|
-
: 'Adequate capacity',
|
|
184
|
-
};
|
|
169
|
+
```json
|
|
170
|
+
// vercel.json — configure concurrency for Fluid Compute (Pro/Enterprise)
|
|
171
|
+
{
|
|
172
|
+
"functions": {
|
|
173
|
+
"api/high-throughput.ts": {
|
|
174
|
+
"memory": 1024,
|
|
175
|
+
"maxDuration": 30,
|
|
176
|
+
"concurrency": 10
|
|
177
|
+
}
|
|
178
|
+
}
|
|
185
179
|
}
|
|
186
180
|
```
|
|
187
181
|
|
|
188
|
-
|
|
182
|
+
With Fluid Compute concurrency, a single function instance handles multiple requests:
|
|
189
183
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
**SDK Version:** X.Y.Z
|
|
184
|
+
- Reduces cold starts (fewer instances needed)
|
|
185
|
+
- Reduces cost (shared memory across requests)
|
|
186
|
+
- Best for I/O-bound functions (waiting on DB/API calls)
|
|
187
|
+
- Not ideal for CPU-bound functions (computation blocks other requests)
|
|
195
188
|
|
|
196
|
-
###
|
|
197
|
-
- Duration: 10 minutes
|
|
198
|
-
- Ramp: 10 → 100 → 10 VUs
|
|
199
|
-
- Target endpoint: /v1/resource
|
|
189
|
+
### Step 6: Capacity Planning
|
|
200
190
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|--------|-------|
|
|
204
|
-
| Total Requests | 50,000 |
|
|
205
|
-
| Success Rate | 99.9% |
|
|
206
|
-
| P50 Latency | 120ms |
|
|
207
|
-
| P95 Latency | 350ms |
|
|
208
|
-
| P99 Latency | 800ms |
|
|
209
|
-
| Max RPS Achieved | 150 |
|
|
191
|
+
```
|
|
192
|
+
Capacity Planning Formula:
|
|
210
193
|
|
|
211
|
-
|
|
212
|
-
- [Key finding 1]
|
|
213
|
-
- [Key finding 2]
|
|
194
|
+
Required instances = Peak RPS * Avg Response Time (seconds)
|
|
214
195
|
|
|
215
|
-
|
|
216
|
-
-
|
|
196
|
+
Example:
|
|
197
|
+
- Peak: 500 requests/second
|
|
198
|
+
- Avg response: 200ms (0.2s)
|
|
199
|
+
- Required: 500 * 0.2 = 100 concurrent instances
|
|
200
|
+
|
|
201
|
+
With Fluid Compute (concurrency=10):
|
|
202
|
+
- Required: 500 * 0.2 / 10 = 10 concurrent instances
|
|
203
|
+
|
|
204
|
+
Plan check:
|
|
205
|
+
- Hobby (10 concurrent): NOT sufficient
|
|
206
|
+
- Pro (1000 concurrent): Sufficient with headroom
|
|
217
207
|
```
|
|
218
208
|
|
|
219
|
-
##
|
|
209
|
+
## Load Test Results Template
|
|
220
210
|
|
|
221
|
-
|
|
222
|
-
|
|
211
|
+
```markdown
|
|
212
|
+
## Load Test Report — [Date]
|
|
223
213
|
|
|
224
|
-
###
|
|
225
|
-
|
|
214
|
+
### Configuration
|
|
215
|
+
- Target: https://my-app-preview.vercel.app/api/endpoint
|
|
216
|
+
- Tool: k6 v0.50
|
|
217
|
+
- Duration: 7 minutes (ramp up → peak → cool down)
|
|
218
|
+
- Peak concurrent users: 100
|
|
226
219
|
|
|
227
|
-
###
|
|
228
|
-
|
|
220
|
+
### Results
|
|
221
|
+
| Metric | Value |
|
|
222
|
+
|--------|-------|
|
|
223
|
+
| Total requests | 12,450 |
|
|
224
|
+
| Success rate | 99.8% |
|
|
225
|
+
| P50 latency | 45ms |
|
|
226
|
+
| P95 latency | 320ms |
|
|
227
|
+
| P99 latency | 1,200ms |
|
|
228
|
+
| Max latency | 3,400ms |
|
|
229
|
+
| Cold start % | 8% |
|
|
230
|
+
| Avg cold start duration | 650ms |
|
|
231
|
+
| Throttled (429) | 0 |
|
|
229
232
|
|
|
230
|
-
###
|
|
231
|
-
|
|
233
|
+
### Recommendations
|
|
234
|
+
1. Cold start: 650ms avg — consider Edge Functions for latency-critical paths
|
|
235
|
+
2. P99 spike: caused by cold starts — Fluid Compute concurrency would help
|
|
236
|
+
3. No throttling at 100 concurrent — Pro plan (1000 limit) is sufficient
|
|
237
|
+
```
|
|
232
238
|
|
|
233
239
|
## Output
|
|
234
|
-
|
|
235
|
-
-
|
|
240
|
+
|
|
241
|
+
- Load test scripts for sustained and spike traffic scenarios
|
|
242
|
+
- Cold start frequency and duration measured
|
|
243
|
+
- Concurrency limits tested and validated
|
|
244
|
+
- Capacity plan with scaling recommendations
|
|
236
245
|
- Benchmark results documented
|
|
237
|
-
- Capacity recommendations defined
|
|
238
246
|
|
|
239
247
|
## Error Handling
|
|
240
|
-
| Issue | Cause | Solution |
|
|
241
|
-
|-------|-------|----------|
|
|
242
|
-
| k6 timeout | Rate limited | Reduce RPS |
|
|
243
|
-
| HPA not scaling | Wrong metrics | Verify metric name |
|
|
244
|
-
| Connection refused | Pool exhausted | Increase pool size |
|
|
245
|
-
| Inconsistent results | Warm-up needed | Add ramp-up phase |
|
|
246
|
-
|
|
247
|
-
## Examples
|
|
248
|
-
|
|
249
|
-
### Quick k6 Test
|
|
250
|
-
```bash
|
|
251
|
-
k6 run --vus 10 --duration 30s vercel-load-test.js
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### Check Current Capacity
|
|
255
|
-
```typescript
|
|
256
|
-
const metrics = await getSystemMetrics();
|
|
257
|
-
const capacity = estimateVercelCapacity(metrics);
|
|
258
|
-
console.log('Headroom:', capacity.headroom + '%');
|
|
259
|
-
console.log('Recommendation:', capacity.scaleRecommendation);
|
|
260
|
-
```
|
|
261
248
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
249
|
+
| Error | Cause | Solution |
|
|
250
|
+
|-------|-------|----------|
|
|
251
|
+
| `FUNCTION_THROTTLED` (429) | Exceeded concurrent limit | Reduce test concurrency or upgrade plan |
|
|
252
|
+
| Vercel blocks load test | Not from approved IP | Contact Vercel support before load testing |
|
|
253
|
+
| High P99 but low P50 | Cold starts on spikes | Use Fluid Compute concurrency or Edge Functions |
|
|
254
|
+
| All requests timeout | Function region far from test origin | Set `regions` in vercel.json closer to test source |
|
|
255
|
+
| Inconsistent results | Shared infrastructure variability | Run multiple test rounds, use median results |
|
|
267
256
|
|
|
268
257
|
## Resources
|
|
258
|
+
|
|
259
|
+
- [Vercel Function Limits](https://vercel.com/docs/functions/limitations)
|
|
260
|
+
- [Concurrency Scaling](https://vercel.com/docs/functions/concurrency-scaling)
|
|
261
|
+
- [Fluid Compute](https://vercel.com/docs/functions/usage-and-pricing)
|
|
269
262
|
- [k6 Documentation](https://k6.io/docs/)
|
|
270
|
-
- [
|
|
271
|
-
- [Vercel Rate Limits](https://vercel.com/docs/rate-limits)
|
|
263
|
+
- [Vercel Load Testing Policy](https://vercel.com/kb/guide/what-s-vercel-s-policy-regarding-load-testing-deployments)
|
|
272
264
|
|
|
273
265
|
## Next Steps
|
|
274
|
-
|
|
266
|
+
|
|
267
|
+
For reliability patterns, see `vercel-reliability-patterns`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Capacity Planning
|
|
2
|
+
|
|
3
|
+
## Capacity Planning
|
|
4
|
+
|
|
5
|
+
### Metrics to Monitor
|
|
6
|
+
|
|
7
|
+
| Metric | Warning | Critical |
|
|
8
|
+
|--------|---------|----------|
|
|
9
|
+
| CPU Utilization | > 70% | > 85% |
|
|
10
|
+
| Memory Usage | > 75% | > 90% |
|
|
11
|
+
| Request Queue Depth | > 100 | > 500 |
|
|
12
|
+
| Error Rate | > 1% | > 5% |
|
|
13
|
+
| P95 Latency | > 500ms | > 2000ms |
|
|
14
|
+
|
|
15
|
+
### Capacity Calculation
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
interface CapacityEstimate {
|
|
19
|
+
currentRPS: number;
|
|
20
|
+
maxRPS: number;
|
|
21
|
+
headroom: number;
|
|
22
|
+
scaleRecommendation: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function estimateVercelCapacity(
|
|
26
|
+
metrics: SystemMetrics
|
|
27
|
+
): CapacityEstimate {
|
|
28
|
+
const currentRPS = metrics.requestsPerSecond;
|
|
29
|
+
const avgLatency = metrics.p50Latency;
|
|
30
|
+
const cpuUtilization = metrics.cpuPercent;
|
|
31
|
+
|
|
32
|
+
// Estimate max RPS based on current performance
|
|
33
|
+
const maxRPS = currentRPS / (cpuUtilization / 100) * 0.7; // 70% target
|
|
34
|
+
const headroom = ((maxRPS - currentRPS) / currentRPS) * 100;
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
currentRPS,
|
|
38
|
+
maxRPS: Math.floor(maxRPS),
|
|
39
|
+
headroom: Math.round(headroom),
|
|
40
|
+
scaleRecommendation: headroom < 30
|
|
41
|
+
? 'Scale up soon'
|
|
42
|
+
: headroom < 50
|
|
43
|
+
? 'Monitor closely'
|
|
44
|
+
: 'Adequate capacity',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Error Handling Reference
|
|
2
|
+
|
|
3
|
+
| Issue | Cause | Solution |
|
|
4
|
+
|-------|-------|----------|
|
|
5
|
+
| k6 timeout | Rate limited | Reduce RPS |
|
|
6
|
+
| HPA not scaling | Wrong metrics | Verify metric name |
|
|
7
|
+
| Connection refused | Pool exhausted | Increase pool size |
|
|
8
|
+
| Inconsistent results | Warm-up needed | Add ramp-up phase |
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
*[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## Examples
|
|
2
|
+
|
|
3
|
+
### Quick k6 Test
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
k6 run --vus 10 --duration 30s vercel-load-test.js
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
### Check Current Capacity
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
const metrics = await getSystemMetrics();
|
|
13
|
+
const capacity = estimateVercelCapacity(metrics);
|
|
14
|
+
console.log('Headroom:', capacity.headroom + '%');
|
|
15
|
+
console.log('Recommendation:', capacity.scaleRecommendation);
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Scale HPA Manually
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
kubectl scale deployment vercel-integration --replicas=5
|
|
22
|
+
kubectl get hpa vercel-integration-hpa
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
*[Tons of Skills](https://tonsofskills.com) by [Intent Solutions](https://intentsolutions.io) | [jeremylongshore.com](https://jeremylongshore.com)*
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Load Testing With K6
|
|
2
|
+
|
|
3
|
+
## Load Testing with k6
|
|
4
|
+
|
|
5
|
+
### Basic Load Test
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
// vercel-load-test.js
|
|
9
|
+
import http from 'k6/http';
|
|
10
|
+
import { check, sleep } from 'k6';
|
|
11
|
+
|
|
12
|
+
export const options = {
|
|
13
|
+
stages: [
|
|
14
|
+
{ duration: '2m', target: 10 }, // Ramp up
|
|
15
|
+
{ duration: '5m', target: 10 }, // Steady state
|
|
16
|
+
{ duration: '2m', target: 50 }, // Ramp to peak
|
|
17
|
+
{ duration: '5m', target: 50 }, // Stress test
|
|
18
|
+
{ duration: '2m', target: 0 }, // Ramp down
|
|
19
|
+
],
|
|
20
|
+
thresholds: {
|
|
21
|
+
http_req_duration: ['p(95)<100'],
|
|
22
|
+
http_req_failed: ['rate<0.01'],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default function () {
|
|
27
|
+
const response = http.post(
|
|
28
|
+
'https://api.vercel.com/v1/resource',
|
|
29
|
+
JSON.stringify({ test: true }),
|
|
30
|
+
{
|
|
31
|
+
headers: {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
'Authorization': `Bearer ${__ENV.VERCEL_API_KEY}`,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
check(response, {
|
|
39
|
+
'status is 200': (r) => r.status === 200,
|
|
40
|
+
'latency < 100ms': (r) => r.timings.duration < 100,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
sleep(1);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Run Load Test
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install k6
|
|
51
|
+
brew install k6 # macOS
|
|
52
|
+
# or: sudo apt install k6 # Linux
|
|
53
|
+
|
|
54
|
+
# Run test
|
|
55
|
+
k6 run --env VERCEL_API_KEY=${VERCEL_API_KEY} vercel-load-test.js
|
|
56
|
+
|
|
57
|
+
# Run with output to InfluxDB
|
|
58
|
+
k6 run --out influxdb=http://localhost:8086/k6 vercel-load-test.js
|
|
59
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Scaling Patterns
|
|
2
|
+
|
|
3
|
+
## Scaling Patterns
|
|
4
|
+
|
|
5
|
+
### Horizontal Scaling
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
# kubernetes HPA
|
|
9
|
+
apiVersion: autoscaling/v2
|
|
10
|
+
kind: HorizontalPodAutoscaler
|
|
11
|
+
metadata:
|
|
12
|
+
name: vercel-integration-hpa
|
|
13
|
+
spec:
|
|
14
|
+
scaleTargetRef:
|
|
15
|
+
apiVersion: apps/v1
|
|
16
|
+
kind: Deployment
|
|
17
|
+
name: vercel-integration
|
|
18
|
+
minReplicas: 2
|
|
19
|
+
maxReplicas: 20
|
|
20
|
+
metrics:
|
|
21
|
+
- type: Resource
|
|
22
|
+
resource:
|
|
23
|
+
name: cpu
|
|
24
|
+
target:
|
|
25
|
+
type: Utilization
|
|
26
|
+
averageUtilization: 70
|
|
27
|
+
- type: Pods
|
|
28
|
+
pods:
|
|
29
|
+
metric:
|
|
30
|
+
name: vercel_queue_depth
|
|
31
|
+
target:
|
|
32
|
+
type: AverageValue
|
|
33
|
+
averageValue: 100
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Connection Pooling
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Pool } from 'generic-pool';
|
|
40
|
+
|
|
41
|
+
const vercelPool = Pool.create({
|
|
42
|
+
create: async () => {
|
|
43
|
+
return new VercelClient({
|
|
44
|
+
apiKey: process.env.VERCEL_API_KEY!,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
destroy: async (client) => {
|
|
48
|
+
await client.close();
|
|
49
|
+
},
|
|
50
|
+
max: None,
|
|
51
|
+
min: None,
|
|
52
|
+
idleTimeoutMillis: 30000,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
async function withVercelClient<T>(
|
|
56
|
+
fn: (client: VercelClient) => Promise<T>
|
|
57
|
+
): Promise<T> {
|
|
58
|
+
const client = await vercelPool.acquire();
|
|
59
|
+
try {
|
|
60
|
+
return await fn(client);
|
|
61
|
+
} finally {
|
|
62
|
+
vercelPool.release(client);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|