How Lambda is billed
cost ≈ invocations × request price + (duration in seconds × memory in GB) × GB-second price
CPU allocation rises with memory. A CPU-bound function at 256 MB may take 4× longer than at 1,024 MB. Same cost, slower. Or more memory can be both faster and cheaper.
1. Find the functions that matter
Cost Explorer grouped by resource (with resource-level data enabled), or a CloudWatch Metrics Insights query in the console:
SELECT SUM(Duration)
FROM SCHEMA("AWS/Lambda", FunctionName)
GROUP BY FunctionName
ORDER BY SUM() DESC
LIMIT 15
Top functions by total duration (and invocations) are where tuning pays.
2. Power Tuning
AWS Lambda Power Tuning (open-source Step Functions state machine) runs a function at several memory sizes and charts cost vs speed:
{
"lambdaARN": "arn:aws:lambda:eu-west-1:123456789012:function:resize-image",
"powerValues": [256, 512, 1024, 1536, 2048, 3008],
"num": 50,
"payload": { "bucket": "test-images", "key": "sample.jpg" },
"parallelInvocation": true,
"strategy": "balanced"
}
Use a realistic payload. For functions with side effects, point it at test resources.
3. arm64 (Graviton)
Switching the architecture to arm64 typically gives a lower GB-second price and often similar or better performance. Check native dependencies (compiled Python wheels, Node native modules, layers) have arm64 builds, then test:
aws lambda update-function-code --function-name resize-image --zip-file fileb://build-arm64.zip --architectures arm64
4. Reduce cold start and init time
| Cause | Fix |
|---|---|
| Large deployment package | Remove unused dependencies; tree-shake (Node); slim layers |
| SDK clients created per invocation | Create once outside the handler, reuse |
| Heavy framework start-up (Java/Spring, .NET) | SnapStart (supported runtimes), lighter frameworks |
| VPC attachment | Modern VPC networking removed most ENI cold-start delay; check other causes first |
| Loading config/secrets on every call | Cache with TTL (Parameters and Secrets extension) |
Look at Init Duration in REPORT log lines or Lambda Insights to measure.
5. SnapStart vs provisioned concurrency
| SnapStart | Provisioned concurrency | |
|---|---|---|
| What | Snapshot of initialised environment, restored on cold start | Pre-initialised environments kept warm |
| Cost | Supported runtimes; caching/restore charges may apply by runtime | Pay for configured concurrency all the time it's on |
| Use when | Init is slow and occasional cold starts are OK if fast | Strict latency, predictable traffic (schedule with Application Auto Scaling) |
Code that generates unique values or opens connections at init time needs care with SnapStart (runtime hooks).
6. Fewer, better invocations
- Batch SQS/Kinesis records (
BatchSize,MaximumBatchingWindowInSeconds) instead of one message per invocation. - Event filtering on event source mappings so irrelevant events never invoke the function.
- Don't poll from Lambda on a schedule when an event exists.
- Step Functions for waiting, not
sleepinside Lambda.
7. Also check
- Timeouts set close to real p99 duration, not 15 minutes "just in case".
- Logs: JSON with
WARNlevel in prod (logging is often a hidden cost). - Recursive loops: Lambda's recursion detection catches some, but design guards in.
Tip
Re-run Power Tuning after big code or dependency changes. The best memory setting moves when the workload changes from I/O-bound to CPU-bound.
Checklist
- Top functions by duration and invocations identified
- Power Tuning on the top ones with realistic payloads
- arm64 where dependencies allow
- Init time reduced; SnapStart or provisioned concurrency where justified
- Batching and event filtering on stream/queue sources
- Timeouts and log levels reviewed