vybekiit 0.7.0 → 0.7.2
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/dist/bin.js +1697 -562
- package/dist/global-skills/add-ai/SKILL.md +1 -1
- package/dist/global-skills/add-analytics/SKILL.md +1 -1
- package/dist/global-skills/add-blog/SKILL.md +1 -1
- package/dist/global-skills/add-crud/SKILL.md +1 -1
- package/dist/global-skills/add-files/SKILL.md +1 -1
- package/dist/global-skills/add-images/SKILL.md +1 -1
- package/dist/global-skills/add-language/SKILL.md +1 -1
- package/dist/global-skills/add-notifications/SKILL.md +1 -1
- package/dist/global-skills/add-realtime/SKILL.md +1 -1
- package/dist/global-skills/add-route/SKILL.md +1 -1
- package/dist/global-skills/add-search/SKILL.md +1 -1
- package/dist/global-skills/add-signin/SKILL.md +1 -1
- package/dist/global-skills/add-teams/SKILL.md +1 -1
- package/dist/global-skills/add-upload/SKILL.md +1 -1
- package/dist/global-skills/aws-serverless/SKILL.md +44 -44
- package/dist/global-skills/aws-serverless/assets/powertools-handler.py +1 -2
- package/dist/global-skills/aws-serverless/references/api-gateway.md +470 -50
- package/dist/global-skills/aws-serverless/references/architecture.md +186 -47
- package/dist/global-skills/aws-serverless/references/concurrency.md +158 -44
- package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
- package/dist/global-skills/aws-serverless/references/event-sources.md +391 -72
- package/dist/global-skills/aws-serverless/references/lambda.md +428 -69
- package/dist/global-skills/aws-serverless/references/orchestration.md +384 -65
- package/dist/global-skills/aws-serverless/references/production.md +415 -78
- package/dist/global-skills/aws-serverless/references/troubleshooting.md +626 -79
- package/dist/global-skills/back-up-my-code/SKILL.md +1 -1
- package/dist/global-skills/buy-domain/SKILL.md +1 -1
- package/dist/global-skills/check-safety/SKILL.md +1 -1
- package/dist/global-skills/configure-capabilities/SKILL.md +1 -1
- package/dist/global-skills/connect-account/SKILL.md +1 -1
- package/dist/global-skills/connect-account-backend/SKILL.md +1 -1
- package/dist/global-skills/design-my-data/SKILL.md +1 -1
- package/dist/global-skills/doctor/SKILL.md +1 -1
- package/dist/global-skills/feedback/SKILL.md +63 -0
- package/dist/global-skills/go-live/SKILL.md +1 -1
- package/dist/global-skills/harden/SKILL.md +1 -1
- package/dist/global-skills/instrument-feature-flags/references/usage.md +0 -35
- package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/android.md +0 -36
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +0 -1
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +0 -37
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +2 -3
- package/dist/global-skills/instrument-product-analytics/references/usage.md +0 -35
- package/dist/global-skills/manifest.json +2 -1
- package/dist/global-skills/neon/SKILL.md +20 -27
- package/dist/global-skills/neon-ai-gateway/SKILL.md +2 -68
- package/dist/global-skills/neon-functions/SKILL.md +7 -7
- package/dist/global-skills/neon-object-storage/SKILL.md +2 -2
- package/dist/global-skills/neon-postgres/SKILL.md +5 -5
- package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -1
- package/dist/global-skills/onboarding/SKILL.md +1 -1
- package/dist/global-skills/plan-my-idea/SKILL.md +1 -1
- package/dist/global-skills/publish-app/SKILL.md +1 -1
- package/dist/global-skills/publish-extension/SKILL.md +1 -1
- package/dist/global-skills/reset-password/SKILL.md +1 -1
- package/dist/global-skills/save-data/SKILL.md +1 -1
- package/dist/global-skills/setup-email/SKILL.md +1 -1
- package/dist/global-skills/setup-payments/SKILL.md +1 -1
- package/dist/global-skills/setup-sms/SKILL.md +1 -1
- package/dist/global-skills/sign-in-with-email-link/SKILL.md +1 -1
- package/dist/global-skills/sign-in-with-google/SKILL.md +1 -1
- package/dist/global-skills/sign-in-with-phone/SKILL.md +1 -1
- package/dist/global-skills/stripe-best-practices/SKILL.md +6 -11
- package/dist/global-skills/stripe-best-practices/references/billing.md +0 -5
- package/dist/global-skills/stripe-best-practices/references/payments.md +2 -4
- package/dist/global-skills/stripe-best-practices/references/tax.md +8 -78
- package/dist/global-skills/track-errors/SKILL.md +1 -1
- package/dist/global-skills/update-kit/SKILL.md +1 -1
- package/dist/global-skills/wire-auth/SKILL.md +1 -1
- package/dist/global-skills/wire-database/SKILL.md +1 -1
- package/dist/global-skills/wire-email/SKILL.md +1 -1
- package/dist/global-skills/wire-payments/SKILL.md +1 -1
- package/package.json +8 -8
- package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +0 -30
- package/dist/global-skills/email-best-practices/README.md +0 -63
- package/dist/global-skills/email-best-practices/references/accessibility.md +0 -189
- package/dist/global-skills/email-best-practices/references/compliance.md +0 -125
- package/dist/global-skills/email-best-practices/references/deliverability.md +0 -121
- package/dist/global-skills/email-best-practices/references/email-capture.md +0 -129
- package/dist/global-skills/email-best-practices/references/email-types.md +0 -173
- package/dist/global-skills/email-best-practices/references/list-management.md +0 -157
- package/dist/global-skills/email-best-practices/references/marketing-emails.md +0 -115
- package/dist/global-skills/email-best-practices/references/sending-reliability.md +0 -155
- package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +0 -418
- package/dist/global-skills/email-best-practices/references/transactional-emails.md +0 -92
- package/dist/global-skills/email-best-practices/references/webhooks-events.md +0 -167
- package/dist/global-skills/email-best-practices/tests/README.md +0 -35
- package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +0 -46
- package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +0 -48
- package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +0 -36
- package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +0 -52
- package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +0 -51
- package/dist/global-skills/neon-postgres/references/neon-sdk.md +0 -262
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# Production-Ready Serverless on AWS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Quick-reference for shipping Lambda workloads to production. Covers the pre-deployment checklist, architecture trade-offs, and operational patterns for production traffic.
|
|
4
4
|
|
|
5
5
|
## Contents
|
|
6
6
|
|
|
7
7
|
- [Production readiness checklist](#production-readiness-checklist)
|
|
8
8
|
- [Architecture decisions](#architecture-decisions)
|
|
9
9
|
- [Observability](#observability)
|
|
10
|
-
- [
|
|
10
|
+
- [Security hardening](#security-hardening)
|
|
11
|
+
- [Testing strategies](#testing-strategies)
|
|
12
|
+
- [Idempotency patterns](#idempotency-patterns)
|
|
11
13
|
- [Response streaming](#response-streaming)
|
|
12
14
|
- [Anti-patterns](#anti-patterns)
|
|
13
15
|
|
|
@@ -15,134 +17,365 @@ Pre-deployment checklist, architecture trade-offs, and operational patterns. Con
|
|
|
15
17
|
|
|
16
18
|
## Production readiness checklist
|
|
17
19
|
|
|
20
|
+
Walk through every item before the first production deployment.
|
|
21
|
+
|
|
18
22
|
### Compute
|
|
19
23
|
|
|
20
|
-
- [ ] Memory right-sized (Power Tuning
|
|
21
|
-
- [ ] Timeout set explicitly (P99 + buffer
|
|
22
|
-
- [ ] Reserved concurrency
|
|
23
|
-
- [ ] DLQ
|
|
24
|
-
- [ ]
|
|
25
|
-
- [ ]
|
|
24
|
+
- [ ] Memory right-sized (use AWS Lambda Power Tuning or load testing)
|
|
25
|
+
- [ ] Timeout set explicitly (P99 + buffer, never the 3 s default)
|
|
26
|
+
- [ ] Reserved concurrency configured to protect downstream systems
|
|
27
|
+
- [ ] Dead-letter queue (DLQ) or on-failure destination for every async invocation
|
|
28
|
+
- [ ] Environment variables for all config (bucket names, table names, endpoints)
|
|
29
|
+
- [ ] Code signing enabled (if compliance requires it)
|
|
30
|
+
- [ ] SDK clients initialized outside handler (reuse across warm invocations)
|
|
31
|
+
- [ ] Deployment package size minimized (exclude tests, docs, unused dependencies)
|
|
26
32
|
|
|
27
33
|
### Observability
|
|
28
34
|
|
|
29
|
-
- [ ] Structured JSON logging
|
|
30
|
-
- [ ] X-Ray active tracing
|
|
31
|
-
- [ ] Custom metrics via EMF
|
|
32
|
-
- [ ] Alarms on Errors, Throttles, Duration P99, IteratorAge, ConcurrentExecutions, DLQ depth
|
|
33
|
-
- [ ] Log retention set —
|
|
34
|
-
- [ ]
|
|
35
|
-
- [ ] Lambda Insights enabled
|
|
35
|
+
- [ ] Structured JSON logging via Powertools Logger
|
|
36
|
+
- [ ] X-Ray active tracing enabled
|
|
37
|
+
- [ ] Custom metrics emitted via Embedded Metric Format (EMF)
|
|
38
|
+
- [ ] CloudWatch Alarms on Errors, Throttles, Duration P99, IteratorAge, ConcurrentExecutions, DLQ depth
|
|
39
|
+
- [ ] Log retention policy set — do not leave at unlimited
|
|
40
|
+
- [ ] Correlation IDs propagated to downstream services
|
|
41
|
+
- [ ] Lambda Insights enabled for system-level metrics (CPU, memory, network)
|
|
36
42
|
|
|
37
43
|
### Security
|
|
38
44
|
|
|
39
|
-
- [ ] One IAM role per function, scoped to exact resource ARNs
|
|
40
|
-
- [ ] No secrets in
|
|
41
|
-
- [ ] Input validation
|
|
42
|
-
- [ ] VPC only when required (RDS, ElastiCache); VPC endpoints for AWS services
|
|
43
|
-
- [ ] GuardDuty Lambda Protection
|
|
45
|
+
- [ ] One IAM execution role per function, scoped to exact resource ARNs
|
|
46
|
+
- [ ] No secrets in environment variables — use Secrets Manager / SSM with caching
|
|
47
|
+
- [ ] Input validation on every event payload (JSON Schema, Zod, Pydantic)
|
|
48
|
+
- [ ] VPC placement only when required (RDS, ElastiCache); VPC endpoints for AWS services
|
|
49
|
+
- [ ] GuardDuty Lambda Protection enabled
|
|
50
|
+
- [ ] Security Hub Lambda controls enabled
|
|
51
|
+
- [ ] Dependency scanning in CI (`npm audit`, `pip-audit`, Snyk)
|
|
52
|
+
- [ ] Amazon Inspector Lambda scanning enabled
|
|
44
53
|
- [ ] Function URLs use `AWS_IAM` auth (not `NONE`) in production
|
|
45
|
-
- [ ] SQS queues use SSE-KMS for encryption at rest when compliance requires customer managed keys (SSE-SQS is enabled by default)
|
|
46
|
-
- [ ] DynamoDB tables use customer managed KMS keys when compliance requires key control (AWS owned encryption is enabled by default)
|
|
47
|
-
- [ ] Enforce HTTPS-only access with `aws:SecureTransport` condition in resource policies (S3 buckets, SQS queues)
|
|
48
54
|
|
|
49
55
|
### Reliability
|
|
50
56
|
|
|
51
|
-
- [ ] Every handler idempotent
|
|
52
|
-
- [ ] Partial batch failure reporting (SQS, Kinesis, DynamoDB Streams)
|
|
53
|
-
- [ ] `BisectBatchOnFunctionError` for stream sources
|
|
54
|
-
- [ ] Retry config tuned
|
|
55
|
-
- [ ]
|
|
56
|
-
- [ ]
|
|
57
|
+
- [ ] Every handler is idempotent
|
|
58
|
+
- [ ] Partial batch failure reporting enabled (SQS, Kinesis, DynamoDB Streams)
|
|
59
|
+
- [ ] `BisectBatchOnFunctionError` enabled for stream sources (isolates poison records)
|
|
60
|
+
- [ ] Retry config tuned — `MaximumRetryAttempts`, `MaximumEventAgeInSeconds`
|
|
61
|
+
- [ ] Circuit breakers on downstream HTTP calls
|
|
62
|
+
- [ ] Reserved concurrency = 0 documented as emergency kill switch
|
|
63
|
+
- [ ] Graceful error handling — catch, log, and return meaningful errors (no unhandled exceptions)
|
|
57
64
|
|
|
58
65
|
### Deployment
|
|
59
66
|
|
|
60
|
-
- [ ] Aliases + weighted shifting (or CodeDeploy canary/linear)
|
|
61
|
-
- [ ]
|
|
62
|
-
- [ ]
|
|
63
|
-
- [ ]
|
|
67
|
+
- [ ] Aliases + weighted traffic shifting (or CodeDeploy canary/linear)
|
|
68
|
+
- [ ] Rollback alarms wired into the deployment pipeline
|
|
69
|
+
- [ ] All infrastructure defined in code (CDK, SAM, or CloudFormation)
|
|
70
|
+
- [ ] Separate AWS accounts for dev, staging, production
|
|
71
|
+
- [ ] Automated smoke tests run post-deployment before full traffic shift
|
|
72
|
+
- [ ] Pre-traffic hooks (BeforeAllowTraffic) validate function health before shifting
|
|
64
73
|
|
|
65
74
|
---
|
|
66
75
|
|
|
67
76
|
## Architecture decisions
|
|
68
77
|
|
|
69
|
-
###
|
|
78
|
+
### Monolith Lambda vs micro-Lambda
|
|
79
|
+
|
|
80
|
+
| Aspect | Lambdalith (single function) | Micro-Lambda (function per route) |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| Cold starts | One function to warm; larger package | Many functions; smaller, faster init |
|
|
83
|
+
| IAM granularity | Single broad role | Per-function least-privilege |
|
|
84
|
+
| Deployment | Everything together; simpler CI/CD | Independent; more pipeline complexity |
|
|
85
|
+
| Observability | One log group; harder per-route metrics | Per-function metrics, alarms, logs |
|
|
86
|
+
| Scaling | Single concurrency pool | Independent scaling + reserved concurrency per function |
|
|
87
|
+
| DX | Familiar Express/FastAPI style | More AWS-native; requires IaC discipline |
|
|
88
|
+
|
|
89
|
+
**Guidance**: Prefer micro-Lambda for greenfield (least privilege, independent scaling, granular observability). Use Lambdalith when migrating existing Express/FastAPI apps or when team size makes deployment simplicity more valuable than granularity.
|
|
90
|
+
|
|
91
|
+
### Function URLs vs API Gateway
|
|
70
92
|
|
|
71
|
-
|
|
93
|
+
| Feature | Function URLs | API Gateway (HTTP API) | API Gateway (REST API) |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| Auth | IAM only (or in-code) | IAM, JWT, Lambda authorizers | IAM, Cognito, Lambda authorizers, API keys |
|
|
96
|
+
| Rate limiting | None built-in | Built-in throttling | Throttling + usage plans |
|
|
97
|
+
| Response streaming | Yes (native) | No | Yes (proxy integration) |
|
|
98
|
+
| Custom domains | Via CloudFront | Built-in | Built-in |
|
|
99
|
+
| WAF | No (use CloudFront) | No (use CloudFront) | Yes |
|
|
100
|
+
| Request validation | None | None | JSON Schema |
|
|
101
|
+
| Caching | Via CloudFront | None | Built-in |
|
|
102
|
+
| WebSocket | No | No | No (separate WebSocket API required) |
|
|
103
|
+
|
|
104
|
+
**Use Function URLs** for: internal service-to-service (IAM auth), Lambdalith + CloudFront, streaming, webhook receivers.
|
|
105
|
+
|
|
106
|
+
**Use API Gateway** for: public APIs needing rate limiting, JWT/Cognito auth, multi-function path routing, WAF without CloudFront.
|
|
72
107
|
|
|
73
108
|
### Reserved vs Provisioned Concurrency
|
|
74
109
|
|
|
75
|
-
|
|
110
|
+
| Aspect | Reserved Concurrency | Provisioned Concurrency |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| Purpose | Guarantee capacity + protect downstream | Eliminate cold starts |
|
|
113
|
+
| Cold starts | Still possible | Eliminated (pre-warmed) |
|
|
114
|
+
| Throttling | Throttles at the limit | Spills to on-demand beyond provisioned |
|
|
115
|
+
| Use case | Protect a database; guarantee capacity | Latency-sensitive APIs; payment processing |
|
|
116
|
+
|
|
117
|
+
Decision flow:
|
|
118
|
+
|
|
119
|
+
1. **Need to limit scaling** → Reserved concurrency
|
|
120
|
+
2. **Need to eliminate cold starts** → Provisioned concurrency (try SnapStart first — no additional cost for Java; caching + restore charges for Python/.NET)
|
|
121
|
+
3. **Need both** → Set provisioned ≤ reserved; reserved acts as the ceiling
|
|
76
122
|
|
|
77
123
|
---
|
|
78
124
|
|
|
79
125
|
## Observability
|
|
80
126
|
|
|
81
|
-
|
|
127
|
+
### Powertools setup (Python / TypeScript / Java / .NET)
|
|
82
128
|
|
|
83
|
-
|
|
129
|
+
**Logger** — structured JSON, correlation IDs injected automatically, log level via env var.
|
|
84
130
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
|
92
|
-
|
|
131
|
+
**Tracer** — wraps X-Ray SDK; auto-captures AWS SDK calls, HTTP requests, handler. Add custom subsegments for critical paths. Annotate traces with business keys (customer ID, order ID) for filtering.
|
|
132
|
+
|
|
133
|
+
**Metrics** — emits via Embedded Metric Format. Zero latency impact.
|
|
134
|
+
|
|
135
|
+
### EMF vs PutMetricData
|
|
136
|
+
|
|
137
|
+
| | EMF (Powertools Metrics) | `PutMetricData` API |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| Latency impact | Zero — writes to stdout | Synchronous API call (~5–20 ms) |
|
|
140
|
+
| Complexity | One-liner with Powertools | Manual batching, error handling |
|
|
141
|
+
| Recommendation | **Use this** | Avoid in hot paths |
|
|
142
|
+
|
|
143
|
+
### Minimum alarm set
|
|
144
|
+
|
|
145
|
+
Set these six alarms on every production function:
|
|
93
146
|
|
|
94
|
-
|
|
147
|
+
| Alarm | Metric | Threshold | Period | Why |
|
|
148
|
+
|---|---|---|---|---|
|
|
149
|
+
| Error rate | `Errors / Invocations` | > 1 % | 5 min | Catch bugs and upstream failures |
|
|
150
|
+
| Throttles | `Throttles` | > 0 | 5 min | Concurrency limit hit |
|
|
151
|
+
| Duration P99 | `Duration` P99 | > 80 % of timeout | 5 min | Catch slow functions before timeout |
|
|
152
|
+
| Iterator age | `IteratorAge` | > 60 s | 5 min | Stream processing falling behind |
|
|
153
|
+
| Concurrent executions | `ConcurrentExecutions` | > 80 % of reserved | 5 min | Approaching throttle threshold |
|
|
154
|
+
| DLQ depth | SQS `ApproximateNumberOfMessagesVisible` | > 0 | 5 min | Failed messages accumulating |
|
|
95
155
|
|
|
96
|
-
###
|
|
156
|
+
### Log retention
|
|
97
157
|
|
|
98
|
-
|
|
158
|
+
Set retention when creating log groups. Defaults to "never expire" — storage accumulates continuously. Choose a retention period based on your compliance and debugging needs.
|
|
99
159
|
|
|
100
160
|
---
|
|
101
161
|
|
|
102
|
-
##
|
|
162
|
+
## Security hardening
|
|
103
163
|
|
|
104
|
-
|
|
164
|
+
### One role per function
|
|
105
165
|
|
|
106
|
-
|
|
166
|
+
Never share IAM roles across functions. Scope every policy to specific resource ARNs:
|
|
107
167
|
|
|
108
|
-
|
|
168
|
+
```yaml
|
|
169
|
+
# Good
|
|
170
|
+
Effect: Allow
|
|
171
|
+
Action: dynamodb:PutItem
|
|
172
|
+
Resource: arn:aws:dynamodb:us-east-1:123456789012:table/OrdersTable
|
|
109
173
|
|
|
110
|
-
|
|
174
|
+
# Bad
|
|
175
|
+
Effect: Allow
|
|
176
|
+
Action: dynamodb:*
|
|
177
|
+
Resource: "*"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Use IAM Access Analyzer to identify unused permissions and generate least-privilege policies.
|
|
181
|
+
|
|
182
|
+
### Secrets management
|
|
183
|
+
|
|
184
|
+
- Store in **Secrets Manager** or **SSM Parameter Store** (SecureString)
|
|
185
|
+
- Cache in the execution environment with **Powertools Parameters** (avoids API call per invocation)
|
|
186
|
+
- Rotate automatically via Secrets Manager rotation Lambdas
|
|
187
|
+
- Environment variables are visible in the Lambda console and API — never put secrets there
|
|
188
|
+
|
|
189
|
+
### Input validation
|
|
190
|
+
|
|
191
|
+
Validate at the handler boundary before business logic runs:
|
|
192
|
+
|
|
193
|
+
| Language | Library |
|
|
111
194
|
|---|---|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
116
|
-
|
|
195
|
+
| TypeScript | Zod, io-ts, JSON Schema |
|
|
196
|
+
| Python | Pydantic, Powertools Validation (JSON Schema) |
|
|
197
|
+
| Java | Bean Validation (JSR 380), JSON Schema |
|
|
198
|
+
|
|
199
|
+
Powertools Validation supports envelope extraction for API Gateway, SQS, EventBridge, etc.
|
|
200
|
+
|
|
201
|
+
### VPC: endpoints over NAT Gateway
|
|
117
202
|
|
|
118
|
-
|
|
203
|
+
If your function must be in a VPC, use **VPC endpoints** for AWS service access instead of NAT Gateway:
|
|
204
|
+
|
|
205
|
+
| | VPC Endpoint | NAT Gateway |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| Latency | Lower (stays on AWS backbone) | Higher (extra hop) |
|
|
208
|
+
|
|
209
|
+
Create endpoints for: DynamoDB (gateway), S3 (gateway), SQS, Secrets Manager, SSM, KMS.
|
|
119
210
|
|
|
120
211
|
---
|
|
121
212
|
|
|
122
|
-
##
|
|
213
|
+
## Testing strategies
|
|
123
214
|
|
|
124
|
-
|
|
215
|
+
### The serverless testing pyramid (inverted)
|
|
125
216
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
217
|
+
```
|
|
218
|
+
┌─────────────┐
|
|
219
|
+
│ E2E Tests │ Few — full workflow verification
|
|
220
|
+
├─────────────┤
|
|
221
|
+
│ Integration │ Many — THIS IS THE MOST VALUABLE LAYER
|
|
222
|
+
│ (in cloud) │ Test real service interactions
|
|
223
|
+
├─────────────┤
|
|
224
|
+
│ Unit Tests │ Fast — pure business logic only
|
|
225
|
+
└─────────────┘
|
|
226
|
+
```
|
|
131
227
|
|
|
132
|
-
|
|
228
|
+
Serverless apps are primarily about service integrations, not complex business logic. Integration tests in the cloud detect the most impactful defects.
|
|
229
|
+
|
|
230
|
+
### Structure code for testability
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
handler (thin adapter)
|
|
234
|
+
→ extract + validate event
|
|
235
|
+
→ call business logic (pure functions — unit test these)
|
|
236
|
+
→ call AWS services (integration test these in the cloud)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### What to test where
|
|
240
|
+
|
|
241
|
+
| Layer | What | How |
|
|
242
|
+
|---|---|---|
|
|
243
|
+
| Unit | Business logic (calculations, transforms, validation) | Local, fast, mocked dependencies |
|
|
244
|
+
| Integration | Service contracts (DynamoDB reads/writes, SQS send/receive, IAM permissions) | Deploy to AWS, test against real services |
|
|
245
|
+
| E2E | Full workflows (API → Lambda → DynamoDB → Stream → Lambda → SQS) | Dedicated staging environment; poll for async side effects |
|
|
246
|
+
|
|
247
|
+
### Fast iteration
|
|
248
|
+
|
|
249
|
+
- **`sam sync`** — hot-deploys code changes to AWS in seconds
|
|
250
|
+
- **`cdk watch`** — watches for file changes and auto-deploys
|
|
251
|
+
- Each developer gets an isolated test stack (separate account or prefixed stack name)
|
|
252
|
+
|
|
253
|
+
### What NOT to do
|
|
254
|
+
|
|
255
|
+
- Don't rely on LocalStack / DynamoDB Local as primary testing — they diverge from real AWS (IAM, quotas, error codes)
|
|
256
|
+
- Don't mock AWS SDK calls for integration tests — you'll miss permission and config issues
|
|
257
|
+
- Don't skip cloud testing because "it's slow" — use `sam sync` / `cdk watch`
|
|
133
258
|
|
|
134
259
|
---
|
|
135
260
|
|
|
136
|
-
##
|
|
261
|
+
## Idempotency patterns
|
|
262
|
+
|
|
263
|
+
Lambda guarantees **at-least-once** execution. Duplicates happen from: async retries, SQS visibility timeout expiry, stream shard replays, client retries on timeout, Step Functions task retries.
|
|
264
|
+
|
|
265
|
+
### Powertools Idempotency utility
|
|
266
|
+
|
|
267
|
+
Uses DynamoDB to track processed events. Available for Python, TypeScript, Java, .NET.
|
|
268
|
+
|
|
269
|
+
**Python:**
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
from aws_lambda_powertools.utilities.idempotency import (
|
|
273
|
+
DynamoDBPersistenceLayer, idempotent
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
persistence = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
|
|
277
|
+
|
|
278
|
+
@idempotent(persistence_store=persistence)
|
|
279
|
+
def handler(event, context):
|
|
280
|
+
payment = process_payment(event)
|
|
281
|
+
return {"statusCode": 200, "body": payment}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**TypeScript:**
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import { makeIdempotent } from "@aws-lambda-powertools/idempotency";
|
|
288
|
+
import { DynamoDBPersistenceLayer } from "@aws-lambda-powertools/idempotency/dynamodb";
|
|
289
|
+
|
|
290
|
+
const persistence = new DynamoDBPersistenceLayer({ tableName: "IdempotencyTable" });
|
|
291
|
+
|
|
292
|
+
export const handler = makeIdempotent(async (event) => {
|
|
293
|
+
const payment = await processPayment(event);
|
|
294
|
+
return { statusCode: 200, body: JSON.stringify(payment) };
|
|
295
|
+
}, { persistenceStore: persistence });
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### DynamoDB table design
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
Table: IdempotencyTable
|
|
302
|
+
PK: id (String) — hash of the idempotency key
|
|
303
|
+
Attributes:
|
|
304
|
+
status: INPROGRESS | COMPLETED | EXPIRED
|
|
305
|
+
data: cached response payload
|
|
306
|
+
expiration: TTL epoch timestamp
|
|
307
|
+
TTL attribute: expiration
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Choosing the idempotency key
|
|
311
|
+
|
|
312
|
+
| Event source | Key |
|
|
313
|
+
|---|---|
|
|
314
|
+
| SQS | `messageId` |
|
|
315
|
+
| EventBridge | `detail.id` or composite of event fields |
|
|
316
|
+
| DynamoDB Streams | `eventID` |
|
|
317
|
+
| API Gateway / Function URL | `Idempotency-Key` header or request body hash |
|
|
318
|
+
| Step Functions | Execution ID + task token |
|
|
319
|
+
|
|
320
|
+
### TTL for cleanup
|
|
137
321
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
322
|
+
Set TTL based on how long duplicates can arrive. Typical values:
|
|
323
|
+
|
|
324
|
+
- API retries: 1 hour
|
|
325
|
+
- SQS retries: match the queue's `maxReceiveCount` × visibility timeout
|
|
326
|
+
- Stream replays: 24 hours (Kinesis retention default)
|
|
327
|
+
|
|
328
|
+
DynamoDB automatically deletes expired items (typically within a few days of TTL expiry).
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Response streaming
|
|
333
|
+
|
|
334
|
+
### When to use
|
|
335
|
+
|
|
336
|
+
| Use case | Why streaming helps |
|
|
337
|
+
|---|---|
|
|
338
|
+
| Large payloads (> 6 MB) | Buffered limit is 6 MB; streaming supports up to 200 MB |
|
|
339
|
+
| TTFB-sensitive responses | Client sees partial data immediately (HTML shell, then content) |
|
|
340
|
+
| Server-sent events (SSE) | Real-time updates to browser clients |
|
|
341
|
+
| LLM / AI token streaming | Stream tokens as generated (conversational AI-style) |
|
|
342
|
+
| Large file generation | CSV/PDF rows streamed as produced |
|
|
343
|
+
|
|
344
|
+
### Constraints
|
|
345
|
+
|
|
346
|
+
- **Function URLs** are simplest for streaming. REST API also supports streaming via proxy integration with STREAM transfer mode. HTTP API does **not** support streaming.
|
|
347
|
+
- **200 MB** response limit
|
|
348
|
+
- **2 MBps** bandwidth cap after the first 6 MB
|
|
349
|
+
- Billed for full function duration even if client disconnects
|
|
350
|
+
- Node.js has native support; other runtimes use custom runtime or Lambda Web Adapter
|
|
351
|
+
- **Function URL streaming is NOT supported for VPC-attached functions.** Use the `InvokeWithResponseStream` API as an alternative.
|
|
352
|
+
|
|
353
|
+
### Node.js example
|
|
354
|
+
|
|
355
|
+
```javascript
|
|
356
|
+
export const handler = awslambda.streamifyResponse(
|
|
357
|
+
async (event, responseStream, context) => {
|
|
358
|
+
const metadata = {
|
|
359
|
+
statusCode: 200,
|
|
360
|
+
headers: { "Content-Type": "text/html" },
|
|
361
|
+
};
|
|
362
|
+
responseStream = awslambda.HttpResponseStream.from(responseStream, metadata);
|
|
363
|
+
|
|
364
|
+
responseStream.write("<html><body>");
|
|
365
|
+
for (const chunk of generateContent()) {
|
|
366
|
+
responseStream.write(chunk);
|
|
367
|
+
}
|
|
368
|
+
responseStream.write("</body></html>");
|
|
369
|
+
responseStream.end();
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### When NOT to use
|
|
375
|
+
|
|
376
|
+
- Small JSON responses (< 6 MB) — buffered is simpler
|
|
377
|
+
- When you need API Gateway features (rate limiting, caching, WAF) without CloudFront
|
|
378
|
+
- VPC-based functions needing Function URL streaming (use `InvokeWithResponseStream` API instead)
|
|
146
379
|
|
|
147
380
|
---
|
|
148
381
|
|
|
@@ -151,6 +384,110 @@ Don't stream small JSON (< 6 MB) — buffered is simpler.
|
|
|
151
384
|
- [AWS Lambda Best Practices](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)
|
|
152
385
|
- [Lambda Concurrency and Scaling](https://docs.aws.amazon.com/lambda/latest/dg/lambda-concurrency.html)
|
|
153
386
|
- [Response Streaming](https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html)
|
|
154
|
-
- [
|
|
387
|
+
- [How to Test Serverless Functions](https://docs.aws.amazon.com/lambda/latest/dg/testing-guide.html)
|
|
155
388
|
- [Serverless Applications Lens — Well-Architected](https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/welcome.html)
|
|
156
389
|
- [Powertools for AWS Lambda](https://docs.powertools.aws.dev/lambda/)
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Anti-patterns
|
|
394
|
+
|
|
395
|
+
Common mistakes that cause production issues in serverless applications. Each pairs the problem with the correct alternative.
|
|
396
|
+
|
|
397
|
+
### Avoid: Lambda calling Lambda synchronously
|
|
398
|
+
|
|
399
|
+
Synchronous Lambda-to-Lambda invocation doubles latency, creates tight coupling, and makes error handling fragile.
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
# BAD: Direct synchronous invocation
|
|
403
|
+
lambda_client.invoke(FunctionName='downstream', InvocationType='RequestResponse', Payload=json.dumps(event))
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Instead: Use Step Functions or SQS
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
# GOOD: Decouple via SQS
|
|
410
|
+
sqs.send_message(QueueUrl=QUEUE_URL, MessageBody=json.dumps(event))
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Or use Step Functions for orchestration when you need the result.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
### Avoid: Monolithic handler without intentional design
|
|
418
|
+
|
|
419
|
+
Routing logic stuffed into a single handler without considering trade-offs prevents independent scaling, broadens IAM blast radius, and increases cold start times.
|
|
420
|
+
|
|
421
|
+
```python
|
|
422
|
+
# BAD: One function handling all routes without considering trade-offs
|
|
423
|
+
def handler(event, context):
|
|
424
|
+
path = event['path']
|
|
425
|
+
if path == '/users': return handle_users(event)
|
|
426
|
+
elif path == '/orders': return handle_orders(event)
|
|
427
|
+
elif path == '/products': return handle_products(event)
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Instead: Choose deliberately
|
|
431
|
+
|
|
432
|
+
For greenfield projects, prefer one function per route (least privilege, independent scaling, granular observability). For migrations from Express/FastAPI or small teams prioritizing deployment simplicity, a Lambdalith is a valid choice — see [Architecture decisions](#architecture-decisions) for trade-offs.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
### Avoid: Secrets in environment variables
|
|
437
|
+
|
|
438
|
+
Visible in console and API, 4 KB total limit for all environment variables combined.
|
|
439
|
+
|
|
440
|
+
```python
|
|
441
|
+
# BAD: Secret in env var
|
|
442
|
+
db_password = os.environ['DB_PASSWORD']
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Instead: Use Secrets Manager with Powertools caching
|
|
446
|
+
|
|
447
|
+
```python
|
|
448
|
+
# GOOD: Cached secret retrieval
|
|
449
|
+
from aws_lambda_powertools.utilities import parameters
|
|
450
|
+
db_password = parameters.get_secret("my-db-secret", max_age=300)
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
### Avoid: Skipping idempotency
|
|
456
|
+
|
|
457
|
+
Lambda delivers at-least-once; duplicates cause duplicate records.
|
|
458
|
+
|
|
459
|
+
### Instead: Use Powertools Idempotency
|
|
460
|
+
|
|
461
|
+
```python
|
|
462
|
+
from aws_lambda_powertools.utilities.idempotency import idempotent, DynamoDBPersistenceLayer
|
|
463
|
+
|
|
464
|
+
persistence = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
|
|
465
|
+
|
|
466
|
+
@idempotent(persistence_store=persistence)
|
|
467
|
+
def handler(event, context):
|
|
468
|
+
return process_payment(event)
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
### Avoid: VPC when not needed
|
|
474
|
+
|
|
475
|
+
Adds cold start latency. Only attach Lambda to a VPC for private resources (RDS, ElastiCache, Elasticsearch). Use VPC endpoints for AWS service access instead.
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### Avoid: Default 3s timeout
|
|
480
|
+
|
|
481
|
+
Legitimate requests fail silently. Set timeout based on load-test P99 + buffer. Set SDK/HTTP client timeouts shorter than Lambda timeout to get meaningful errors instead of generic timeouts.
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### Avoid: Missing DLQ
|
|
486
|
+
|
|
487
|
+
Failed async invocations and event source messages are discarded without notification. Configure dead-letter queues on all async invocations and event source mappings.
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### Avoid: CloudWatch Logs retention = forever
|
|
492
|
+
|
|
493
|
+
Storage accumulates continuously. Set a retention period — do not leave at unlimited.
|