CRITICAL

High Memory Utilization

Peak memory approaching or exceeding allocation, risking OOM

What this means

Every Lambda function has a configured memory allocation between 128 MB and 10,240 MB. The REPORT line in CloudWatch logs includes both "Memory Size" (what you configured) and "Max Memory Used" (the peak RSS during that invocation). When the max memory used consistently approaches the allocated amount, your function is under memory pressure. If it actually exceeds the allocation, Lambda kills the process with a "Runtime exited with error: signal: killed" message — an out-of-memory (OOM) crash.

The problem is that memory pressure may not cause immediate failures. A function running at 92% memory utilization works fine until a slightly larger input or an extra database result set pushes it over the edge. The failure mode is also particularly harsh: OOM kills are not catchable in your code. There is no try/catch for a SIGKILL. The invocation simply dies, any in-progress work is lost, and the error message in CloudWatch gives no stack trace — just the signal kill notification.

Memory allocation in Lambda also directly controls CPU allocation. AWS allocates CPU proportionally to memory: 1,769 MB gives you one full vCPU, 3,538 MB gives two, and so on. A function configured with 256 MB gets roughly 15% of a vCPU, which can make CPU-bound operations extremely slow. This means that increasing memory is not just about avoiding OOM — it also speeds up your function by giving it more compute power. Many teams discover that doubling memory from 512 MB to 1,024 MB reduces duration by 40-50%, making the invocation cheaper despite the higher per-millisecond rate.

Detection criteria

smplogs triggers this finding when:

  • CRITICAL — Peak memory utilization exceeds 95% of allocated memory
  • HIGH — Peak memory utilization exceeds 85% of allocated memory

Example finding

CRITICAL · 512 MB allocated High Memory Utilization

Peak memory used: 498 MB of 512 MB (97.3%). Memory utilization exceeded 95% in 41 of 620 invocations. 3 invocations ended with "Runtime exited with error: signal: killed" (OOM).

-> Increase memory allocation (also gives more CPU). Profile heap usage.

How to fix

Increase memory allocation

The simplest fix is to increase the function's memory setting. If you are at 512 MB and hitting 97%, bump to 1,024 MB. This also doubles your CPU allocation, which often reduces duration enough to offset the higher per-millisecond cost. Use AWS Lambda Power Tuning (an open-source Step Functions tool) to find the optimal memory setting for your function — it runs your function at different memory levels and plots cost vs. duration, showing you the sweet spot where additional memory no longer improves performance.

Stream data instead of buffering

Many memory problems come from loading entire files or result sets into memory. If your function downloads an S3 object, processes it, and uploads the result, use streaming: pipe the S3 GetObject readable stream through a transform and into a PutObject upload without ever holding the full object in memory. For Node.js, the AWS SDK v3 returns a readable stream from S3. For Python, use boto3's download_fileobj with a chunked reader. This can reduce peak memory from "file size" to "chunk size" (typically 64 KB-1 MB).

Paginate database and API queries

DynamoDB Scan and Query operations, Elasticsearch queries, and REST API calls that return large collections can easily fill memory if you accumulate all results in an array. Process each page as it arrives and discard it before fetching the next. For DynamoDB, use the paginator from the SDK rather than collecting all items with scanAll() patterns. For SQL databases, use cursor-based pagination or LIMIT/OFFSET to process rows in batches rather than loading an entire table into a variable.

Watch for memory leaks in warm environments

Lambda reuses execution environments across invocations, so variables declared at module scope persist between calls. If your handler appends to a module-scoped array, adds entries to a Map without eviction, or accumulates event listeners, memory usage will grow with each invocation until the environment is recycled. Check for any module-level state that grows unboundedly. A telltale sign is max memory used increasing steadily across invocations in the same log stream (each log stream corresponds to one execution environment).

Check if your functions are running hot on memory. Upload a CloudWatch export to find out.

Try it free