Over-provisioned memory findings apply to functions that are being invoked. Functions with no traffic at all are covered by idle Lambda functions instead.
What triggers this finding
A Lambda function with at least 512 MB of memory, more than 1,000 invocations in the lookback window, and average duration under 200 ms — indicating memory is likely over-allocated.
Typical fix
Reduce memory allocation toward 128–256 MB and re-test. Lambda bills proportionally to memory, so rightsizing can cut cost without hurting performance.
Example savings
Varies by invocation volume — flagged when estimated monthly cost is at least $1; high-traffic functions can save $50+/month.
See also: Severity and savings estimates for how Parsivex calculates figures on your report.
The GB-second model behind this finding
Lambda bills compute as memory multiplied by duration: gigabytes of allocated memory times seconds of wall-clock execution, at $0.0000166667 per GB-second on x86, plus $0.20 per million requests. Memory is the only dial you set directly, but it is not the only thing it moves. Lambda allocates vCPU in proportion to memory, so a function given a quarter of the memory also gets a quarter of the CPU.
Parsivex models that coupling honestly, and the result is deliberately unflattering to the finding: when it projects the cost of the suggested memory setting, it scales the duration up by the same ratio it scales the memory down. GB-seconds stay flat, and the estimated saving comes out at roughly zero. That is not a bug in the estimate. It is the correct answer for a purely CPU-bound function, where halving the memory simply doubles the runtime and you pay the same either way.
The finding is therefore a prompt to measure, not a promised saving. Real money appears when the function is not CPU-bound. A handler that spends 150 ms waiting on DynamoDB, S3, or an HTTP call is idle for most of its billed duration; dropping it from 1,024 MB to 256 MB barely moves the wall clock and cuts the bill close to four-fold. That is why the detector gates on an average duration under 200 ms with at least 512 MB allocated and more than 1,000 invocations in the 30-day window: short, frequent, low-compute invocations are where the coupling assumption breaks in your favour. Functions whose modelled monthly cost is under $1 are skipped.
Measuring real memory use
Every invocation writes a REPORT line to the function's log group containing both the allocated memory and the high-water mark actually used:
aws logs filter-log-events \
--log-group-name /aws/lambda/thumbnail-api \
--filter-pattern '"REPORT RequestId"' \
--limit 50 --query 'events[].message' --output text
Compare Max Memory Used with Memory Size across a representative sample. A function that never exceeds 90 MB of a 1,024 MB allocation has headroom that is doing nothing for it. A function that regularly reaches 800 MB does not, whatever the duration says.
For anything you care about, measure the trade-off rather than guessing at it: AWS Lambda Power Tuning runs the same payload across a range of memory settings and plots cost against latency, which answers the question this finding can only raise. Duration percentiles are worth pulling too, since the detector only sees the mean:
aws cloudwatch get-metric-statistics --namespace AWS/Lambda \
--metric-name Duration --dimensions Name=FunctionName,Value=thumbnail-api \
--start-time 2026-07-12T00:00:00Z --end-time 2026-08-11T00:00:00Z \
--period 86400 --extended-statistics p95 p99
Functions where the memory is doing work
- A low mean hiding a heavy tail. Parsivex averages daily
Durationaverages. A function with a 40 ms median and a four-second p99 still averages well under the 200 ms gate, and the p99 path is usually the one that needs the memory. - Memory bought for latency, not throughput. For a user-facing function, extra memory is a performance purchase. Cutting it to save $3 a month while adding 80 ms to p95 is a bad trade, and no cost tool can see that from the outside.
- Cold-start weight. Large dependency trees, model files, and connection pools spike memory during initialization.
Max Memory Usedon a warm invocation understates what the cold path needs. - Bursty concurrency. Total invocations tell you nothing about their shape. A function that runs 1,000 times in a five-minute window behaves differently under a smaller allocation than one that runs 1,000 times across a month.
Before spending time here, consider the larger lever: arm64 GB-second pricing runs roughly 20% below x86, and for most interpreted runtimes switching architecture is a configuration change rather than a rewrite.
Cost and risk of a memory change
Memory is a single control-plane update that takes effect on the next invocation, with no downtime and no data risk:
aws lambda update-function-configuration --function-name thumbnail-api --memory-size 512
Reversal is the same command with the old number, effective just as quickly — this is one of the cheapest experiments in AWS. The failure mode is the runtime being killed when it exceeds the new allocation, which surfaces as an invocation error rather than a silent slowdown, so it is easy to detect and easy to undo.
Move one step at a time rather than jumping straight to the suggested value, and hold each step through a full traffic cycle including the daily peak. Watch Duration at p95 and p99, Errors, and any downstream timeout that the longer runtime might now breach — an API Gateway integration with a 29-second ceiling is unforgiving of a function that got slower. If the function is defined in infrastructure as code, change it there; a console edit will be reverted by the next deploy and the finding will come back.