TL;DR: Lambda charges GB-seconds — memory × runtime — so a 512 MB function running 2 s costs exactly what a 1024 MB function running 1 s costs. CPU scales with memory, which means for CPU-bound code more memory is frequently cheaper (runtime falls faster than the rate rises), and for I/O-bound code extra memory buys nothing. Lambda Power Tuning — an open-source Step Functions app — measures every memory level against your real function in 2–5 minutes and hands you the cost/speed curve. Teams typically cut 20–50% on tuned functions.
The numbers
- Billing: ~$0.0000166667 per GB-second (x86); 512 MB × 2 s = 1024 MB × 1 s — a perfect tie until CPU-boundness breaks it
- Field example: a SaaS running its whole API on Lambda at a blanket "safe" 1024 MB tuned its top 10 functions — 5 were fine at 512 MB, 3 CPU-bound ones got faster and cheaper at 1536 MB, 2 I/O-bound ones dropped to 256 MB — 35% off the Lambda bill (~$4,000/month) for a 2-hour exercise
- Typical result at 1024 MB "just to be safe": 512 MB is 10% slower and 40% cheaper, or 1792 MB is 50% faster for 15% more
Do this
-
Find your top spenders: invocations × duration × memory per function (CloudWatch). Tuning a function that costs $2/month is hobbyism; tune the top ten.
-
Deploy Power Tuning (Serverless Application Repository →
aws-lambda-power-tuning, one click) and run the state machine per candidate:{ "lambdaARN": "arn:aws:lambda:us-east-1:123456789012:function:my-fn", "powerValues": [128, 256, 512, 1024, 1792, 3008], "num": 50, "payload": { "your": "realistic payload" } }It invokes at each level, averages, and outputs a visualization URL where the sweet spot is obvious.
-
Read the curve: flat duration across memory = I/O-bound → take the lowest safe memory. Duration dropping with memory = CPU-bound → the cost minimum is often higher than you'd guess.
-
Apply manually — Power Tuning only recommends; you change
MemorySizeyourself. Optimize customer-facing functions for speed and background jobs for cost; the graph shows both axes. -
Re-run quarterly and after major dependency changes; also test with cold starts included if your traffic pattern has many (check "Init Duration" in logs).
Gotchas
- Unrealistic payloads give unrealistic answers — tune with production-shaped input.
- Cold-start-heavy functions need cold starts in the test mix, or the recommendation undercounts init time (heavy Python data-science imports especially).
- Provisioned concurrency is a different lever — Power Tuning won't fix latency from cold starts; it optimizes the run itself.
- Don't forget Graviton: switching eligible functions to arm64 is ~20% cheaper per GB-second on top of whatever tuning finds.
- The tool runs real invocations — point it at test/staging aliases for functions with side effects.
Skip this if
- Your Lambda bill is trivial or dominated by a handful of rarely-run functions — the exercise won't move money.
- The function is pure I/O passthrough at 128 MB already — it's done.
- The real spend is API Gateway routing in front of the functions — see HTTP APIs and Function URLs first.