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.
Files changed (94) hide show
  1. package/dist/bin.js +1697 -562
  2. package/dist/global-skills/add-ai/SKILL.md +1 -1
  3. package/dist/global-skills/add-analytics/SKILL.md +1 -1
  4. package/dist/global-skills/add-blog/SKILL.md +1 -1
  5. package/dist/global-skills/add-crud/SKILL.md +1 -1
  6. package/dist/global-skills/add-files/SKILL.md +1 -1
  7. package/dist/global-skills/add-images/SKILL.md +1 -1
  8. package/dist/global-skills/add-language/SKILL.md +1 -1
  9. package/dist/global-skills/add-notifications/SKILL.md +1 -1
  10. package/dist/global-skills/add-realtime/SKILL.md +1 -1
  11. package/dist/global-skills/add-route/SKILL.md +1 -1
  12. package/dist/global-skills/add-search/SKILL.md +1 -1
  13. package/dist/global-skills/add-signin/SKILL.md +1 -1
  14. package/dist/global-skills/add-teams/SKILL.md +1 -1
  15. package/dist/global-skills/add-upload/SKILL.md +1 -1
  16. package/dist/global-skills/aws-serverless/SKILL.md +44 -44
  17. package/dist/global-skills/aws-serverless/assets/powertools-handler.py +1 -2
  18. package/dist/global-skills/aws-serverless/references/api-gateway.md +470 -50
  19. package/dist/global-skills/aws-serverless/references/architecture.md +186 -47
  20. package/dist/global-skills/aws-serverless/references/concurrency.md +158 -44
  21. package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
  22. package/dist/global-skills/aws-serverless/references/event-sources.md +391 -72
  23. package/dist/global-skills/aws-serverless/references/lambda.md +428 -69
  24. package/dist/global-skills/aws-serverless/references/orchestration.md +384 -65
  25. package/dist/global-skills/aws-serverless/references/production.md +415 -78
  26. package/dist/global-skills/aws-serverless/references/troubleshooting.md +626 -79
  27. package/dist/global-skills/back-up-my-code/SKILL.md +1 -1
  28. package/dist/global-skills/buy-domain/SKILL.md +1 -1
  29. package/dist/global-skills/check-safety/SKILL.md +1 -1
  30. package/dist/global-skills/configure-capabilities/SKILL.md +1 -1
  31. package/dist/global-skills/connect-account/SKILL.md +1 -1
  32. package/dist/global-skills/connect-account-backend/SKILL.md +1 -1
  33. package/dist/global-skills/design-my-data/SKILL.md +1 -1
  34. package/dist/global-skills/doctor/SKILL.md +1 -1
  35. package/dist/global-skills/feedback/SKILL.md +63 -0
  36. package/dist/global-skills/go-live/SKILL.md +1 -1
  37. package/dist/global-skills/harden/SKILL.md +1 -1
  38. package/dist/global-skills/instrument-feature-flags/references/usage.md +0 -35
  39. package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -1
  40. package/dist/global-skills/instrument-product-analytics/references/android.md +0 -36
  41. package/dist/global-skills/instrument-product-analytics/references/configuration.md +0 -1
  42. package/dist/global-skills/instrument-product-analytics/references/flutter.md +0 -37
  43. package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +2 -3
  44. package/dist/global-skills/instrument-product-analytics/references/usage.md +0 -35
  45. package/dist/global-skills/manifest.json +2 -1
  46. package/dist/global-skills/neon/SKILL.md +20 -27
  47. package/dist/global-skills/neon-ai-gateway/SKILL.md +2 -68
  48. package/dist/global-skills/neon-functions/SKILL.md +7 -7
  49. package/dist/global-skills/neon-object-storage/SKILL.md +2 -2
  50. package/dist/global-skills/neon-postgres/SKILL.md +5 -5
  51. package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -1
  52. package/dist/global-skills/onboarding/SKILL.md +1 -1
  53. package/dist/global-skills/plan-my-idea/SKILL.md +1 -1
  54. package/dist/global-skills/publish-app/SKILL.md +1 -1
  55. package/dist/global-skills/publish-extension/SKILL.md +1 -1
  56. package/dist/global-skills/reset-password/SKILL.md +1 -1
  57. package/dist/global-skills/save-data/SKILL.md +1 -1
  58. package/dist/global-skills/setup-email/SKILL.md +1 -1
  59. package/dist/global-skills/setup-payments/SKILL.md +1 -1
  60. package/dist/global-skills/setup-sms/SKILL.md +1 -1
  61. package/dist/global-skills/sign-in-with-email-link/SKILL.md +1 -1
  62. package/dist/global-skills/sign-in-with-google/SKILL.md +1 -1
  63. package/dist/global-skills/sign-in-with-phone/SKILL.md +1 -1
  64. package/dist/global-skills/stripe-best-practices/SKILL.md +6 -11
  65. package/dist/global-skills/stripe-best-practices/references/billing.md +0 -5
  66. package/dist/global-skills/stripe-best-practices/references/payments.md +2 -4
  67. package/dist/global-skills/stripe-best-practices/references/tax.md +8 -78
  68. package/dist/global-skills/track-errors/SKILL.md +1 -1
  69. package/dist/global-skills/update-kit/SKILL.md +1 -1
  70. package/dist/global-skills/wire-auth/SKILL.md +1 -1
  71. package/dist/global-skills/wire-database/SKILL.md +1 -1
  72. package/dist/global-skills/wire-email/SKILL.md +1 -1
  73. package/dist/global-skills/wire-payments/SKILL.md +1 -1
  74. package/package.json +8 -8
  75. package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +0 -30
  76. package/dist/global-skills/email-best-practices/README.md +0 -63
  77. package/dist/global-skills/email-best-practices/references/accessibility.md +0 -189
  78. package/dist/global-skills/email-best-practices/references/compliance.md +0 -125
  79. package/dist/global-skills/email-best-practices/references/deliverability.md +0 -121
  80. package/dist/global-skills/email-best-practices/references/email-capture.md +0 -129
  81. package/dist/global-skills/email-best-practices/references/email-types.md +0 -173
  82. package/dist/global-skills/email-best-practices/references/list-management.md +0 -157
  83. package/dist/global-skills/email-best-practices/references/marketing-emails.md +0 -115
  84. package/dist/global-skills/email-best-practices/references/sending-reliability.md +0 -155
  85. package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +0 -418
  86. package/dist/global-skills/email-best-practices/references/transactional-emails.md +0 -92
  87. package/dist/global-skills/email-best-practices/references/webhooks-events.md +0 -167
  88. package/dist/global-skills/email-best-practices/tests/README.md +0 -35
  89. package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +0 -46
  90. package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +0 -48
  91. package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +0 -36
  92. package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +0 -52
  93. package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +0 -51
  94. 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
- Pre-deployment checklist, architecture trade-offs, and operational patterns. Concise on purpose — the value here is the structured checklist and opinionated defaults, not API syntax.
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
- - [Idempotency](#idempotency)
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 / load test)
21
- - [ ] Timeout set explicitly (P99 + buffer never the 3s default)
22
- - [ ] Reserved concurrency set to protect downstream
23
- - [ ] DLQ / on-failure destination on every async invocation and ESM
24
- - [ ] Config via env vars; SDK clients initialized outside the handler
25
- - [ ] Deployment package minimized (exclude tests, docs, unused deps)
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 (Powertools Logger) + correlation IDs propagated
30
- - [ ] X-Ray active tracing
31
- - [ ] Custom metrics via EMF
32
- - [ ] Alarms on Errors, Throttles, Duration P99, IteratorAge, ConcurrentExecutions, DLQ depth (see below)
33
- - [ ] Log retention set — **not** unlimited
34
- - [ ] Log group encryption with customer managed KMS key when compliance requires it
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 env vars — Secrets Manager / SSM (SecureString) with Powertools caching
41
- - [ ] Input validation at the handler boundary (Zod / Pydantic / Powertools Validation)
42
- - [ ] VPC only when required (RDS, ElastiCache); VPC endpoints for AWS services
43
- - [ ] GuardDuty Lambda Protection, Security Hub Lambda controls, Inspector Lambda scanning, CI dependency scanning
45
+ - [ ] One IAM execution role per function, scoped to exact resource ARNs
46
+ - [ ] No secrets in environment variablesuse 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 (`MaximumRetryAttempts`, `MaximumEventAgeInSeconds`)
55
- - [ ] Reserved concurrency = 0 documented as the emergency kill switch
56
- - [ ] No unhandled exceptions catch, log, return meaningful errors
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) with rollback alarms
61
- - [ ] All infra in code (CDK/SAM/CloudFormation)
62
- - [ ] Separate accounts for dev/staging/prod
63
- - [ ] Post-deploy smoke tests + pre-traffic hooks before full shift
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
- ### Lambdalith vs micro-Lambda
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
- Prefer **micro-Lambda** (function per route) for greenfield: per-function least-privilege IAM, independent scaling + reserved concurrency, granular observability, smaller/faster cold starts. Use a **Lambdalith** when migrating an existing Express/FastAPI app or when a small team values deployment simplicity over granularity.
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
- Reserved = guarantee capacity + protect downstream (cold starts still possible, throttles at the limit). Provisioned = eliminate cold starts (spills to on-demand beyond the count). Need both → provisioned ≤ reserved. Try **SnapStart** before Provisioned for Java/Python 3.12+/.NET 8+ (no cost for Java). See [concurrency.md](concurrency.md).
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
- Use Powertools **Logger** (structured JSON, auto correlation IDs), **Tracer** (wraps X-Ray, auto-captures SDK/HTTP calls; annotate traces with business keys), **Metrics** (EMF — zero latency, writes to stdout vs ~5–20ms for synchronous `PutMetricData`; avoid `PutMetricData` in hot paths).
127
+ ### Powertools setup (Python / TypeScript / Java / .NET)
82
128
 
83
- ### Minimum alarm set (every production function)
129
+ **Logger** structured JSON, correlation IDs injected automatically, log level via env var.
84
130
 
85
- | Alarm | Metric | Threshold | Why |
86
- |---|---|---|---|
87
- | Error rate | `Errors / Invocations` | > 1% | Bugs / upstream failures |
88
- | Throttles | `Throttles` | > 0 | Concurrency limit hit |
89
- | Duration P99 | `Duration` P99 | > 80% of timeout | Catch slow functions before timeout |
90
- | Iterator age | `IteratorAge` | > 60s | Stream processing falling behind |
91
- | Concurrent executions | `ConcurrentExecutions` | > 80% of reserved | Approaching throttle threshold |
92
- | DLQ depth | SQS `ApproximateNumberOfMessagesVisible` | > 0 | Failed messages accumulating |
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
- Set **log retention** when creating log groups the default is "never expire."
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
- ### Testing
156
+ ### Log retention
97
157
 
98
- Serverless apps are mostly about **service integrations**, not complex business logic so the **integration layer (tested in the cloud) is the most valuable**, with few unit tests (pure logic) and few E2E. Structure handlers as thin adapters calling pure functions. Don't rely on LocalStack/DynamoDB Local as primary testing (they diverge on IAM, quotas, error codes); don't mock AWS SDK calls for integration tests. Iterate fast with `sam sync` / `cdk watch`; give each developer an isolated stack.
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
- ## Idempotency
162
+ ## Security hardening
103
163
 
104
- Lambda guarantees **at-least-once** duplicates come from async retries, SQS visibility expiry, stream replays, client retries, Step Functions task retries. Use the **Powertools Idempotency** utility (Python/TS/Java/.NET), backed by a DynamoDB table with TTL.
164
+ ### One role per function
105
165
 
106
- Table: `id` (hash of idempotency key) + `status` (INPROGRESS/COMPLETED/EXPIRED), `data` (cached response), `expiration` (TTL).
166
+ Never share IAM roles across functions. Scope every policy to specific resource ARNs:
107
167
 
108
- Idempotency key by source:
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
- | Source | Key |
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
- | SQS | `messageId` |
113
- | EventBridge | `detail.id` or composite |
114
- | DynamoDB Streams | `eventID` |
115
- | API Gateway / Function URL | `Idempotency-Key` header or body hash |
116
- | Step Functions | Execution ID + task token |
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
- TTL how long duplicates can arrive (API retries ~1h; SQS `maxReceiveCount` × visibility; stream replays ~24h).
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
- ## Response streaming
213
+ ## Testing strategies
123
214
 
124
- Use for payloads > 6 MB (buffered limit), TTFB-sensitive responses, SSE, LLM token streaming, or large file generation.
215
+ ### The serverless testing pyramid (inverted)
125
216
 
126
- - **Function URLs** are simplest; REST API also supports streaming (proxy, STREAM mode); **HTTP API does not**.
127
- - **200 MB** response limit; **2 MBps** cap after the first 6 MB.
128
- - Billed for full duration even if the client disconnects.
129
- - Node.js has native support (`awslambda.streamifyResponse` + `awslambda.HttpResponseStream.from`); other runtimes need a custom runtime or Lambda Web Adapter.
130
- - **Not supported for VPC-attached functions via Function URL** — use the `InvokeWithResponseStream` API instead.
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
- Don't stream small JSON (< 6 MB) buffered is simpler.
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
- ## Anti-patterns
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
- - **Lambda calling Lambda synchronously** doubles latency, tight coupling, fragile error handling. Decouple via SQS, or use Step Functions when you need the result.
139
- - **Unintentional monolithic handler** — routing stuffed into one function without weighing trade-offs prevents independent scaling and broadens IAM blast radius. Choose Lambdalith vs micro-Lambda deliberately (see above).
140
- - **Secrets in env vars** — visible in console/API, 4 KB total cap. Use Secrets Manager with Powertools caching.
141
- - **Skipping idempotency** at-least-once delivery causes duplicate records.
142
- - **VPC when not needed** adds cold-start latency. Only for private resources; use VPC endpoints for AWS services.
143
- - **Default 3s timeout** — legitimate requests fail silently. Set SDK/HTTP client timeouts shorter than the Lambda timeout for meaningful errors.
144
- - **Missing DLQ** failed async invocations / ESM messages are discarded silently.
145
- - **Log retention = forever** — storage accumulates continuously.
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
- - [Testing serverless functions](https://docs.aws.amazon.com/lambda/latest/dg/testing-guide.html)
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.