Fix AWS Lambda Out of Memory: Reading REPORT Lines & Sizing Memory
If a Lambda function is failing with an out-of-memory error, the fix is almost never "just crank Memory Size to 10,240 MB and move on." The honest fix is to read the REPORT line CloudWatch writes after every single invocation, find the real ceiling your function needs, and set memory a comfortable margin above it — because that same REPORT line also controls how much CPU your function gets, so guessing wrong costs you either crashes or real money every month. Here's the part almost nobody tells you: the "Max Memory Used" number you're staring at right now might not even belong to the invocation that just failed.
Jake's shop runs a nightly job that resizes customer trade-in photos before they go on his resale listings. It's a small Lambda function, nothing fancy. Three nights a week it works fine. The other four, about a third of the batch fails silently, and Jake doesn't find out until a customer calls asking why their phone still shows the old, blurry photo online. That's a real cost: an annoyed customer, a re-do, and Jake standing in his shop wondering if "the cloud thing" is broken again.
It isn't broken. It's out of memory. And the fix is sitting in a log line Jake has never once opened.
What the REPORT line actually tells you
Every time a Lambda function finishes running — whether it succeeds, fails, or crashes outright — AWS writes one line to CloudWatch Logs that starts with the word REPORT. Think of it like a receipt printed at the end of a transaction: it doesn't tell you what happened during the work, but it tells you exactly what the work cost and how close you came to the ceiling.
♂️ Jake's Reality Check
"I opened CloudWatch once and it was just a wall of green text. I closed the tab. Is any of that actually meant for a normal person?"
One line of it is. The REPORT line, specifically. You can ignore almost everything else CloudWatch shows you and still fix an out-of-memory function just by reading that one line correctly.
A REPORT line looks like this, with real numbers filled in:
REPORT RequestId: 3604209a-e9a3-11e6-939a-754dd98c7be3 Duration: 245.31 ms Billed Duration: 246 ms Memory Size: 512 MB Max Memory Used: 87 MB Init Duration: 412.08 ms
Six fields, each answering a specific question:
| Field | What it means | Why it matters for OOM |
|---|---|---|
| Duration | How long the handler code ran, in milliseconds | Slow durations that trend upward across invocations can be a symptom of a memory leak, not just a slow function |
| Billed Duration | What you're actually charged for, rounded per the billing model | Directly multiplied by Memory Size to calculate cost — this is why oversizing memory has a real dollar cost |
| Memory Size | The amount of memory you configured for the function | Your ceiling. Nothing about the function, including its CPU power, can exceed what this number implies |
| Max Memory Used | The highest memory the execution environment reached | The single most important number on the line for this problem — see the warning below before you trust it blindly |
| Init Duration | Time spent loading your code and running anything outside the handler, on a cold start only | Only appears on the first invocation of a fresh environment; a large one is a cold-start issue, not a memory issue |
| Status / ErrorType (newer log format) | Whether the invocation succeeded, and if not, what kind of failure it was | An ErrorType that names a runtime crash, rather than your own code throwing an exception, points at the platform — which is exactly what an OOM kill looks like |
⚠️ What this actually breaks: trusting Max Memory Used on its own
Lambda can reuse the same running execution environment for several invocations back to back — that's how "warm starts" work. When that happens, Max Memory Used reports the highest figure across every invocation that environment has handled, not just the one on that REPORT line. If invocation four used 480 MB and invocation five only needed 90 MB, invocation five's REPORT line still shows 480 MB. Read one line in isolation and you can talk yourself into a false alarm, or worse, miss a slow leak because a lucky lightweight invocation happened to run right after a heavy one got measured. Read several REPORT lines in sequence before you decide anything.
Reading a memory crash like an autopsy
Here's the counterintuitive part. When a Lambda function actually runs out of memory, your own code almost never gets the chance to say so. The operating system running underneath your function kills the process the instant it tries to grab memory that isn't there, the same way a landlord changes the locks the moment rent stops arriving — there's no polite warning conversation first. Your try/except or try/catch block never runs, because the process it was running inside of is already gone.
What you get instead is a message from the Lambda platform itself, sitting in CloudWatch right above the REPORT line, describing a process that vanished without explaining itself:
RequestId: c3252230-c73d-49f6-8844-968c01d1e2e1 Error: Runtime exited without providing a reason Runtime.ExitError
Or, depending on the runtime and how it was killed, something closer to Runtime exited with error: signal: killed. Neither of those sentences contains the word "memory." That's exactly why the REPORT line matters more than the error text: the error tells you something died, and the REPORT line tells you why.
The tell on the REPORT line itself
When the crash is genuinely a memory kill, the REPORT line accompanying it almost always shows Max Memory Used sitting at, or a hair above, Memory Size — something like Memory Size: 128 MB Max Memory Used: 129 MB. That's the single most reliable diagnostic signal you have, more reliable than the wording of the error message, because different runtimes and different kinds of crashes phrase the error differently, but the accounting on the REPORT line doesn't lie.
What each runtime tends to say
The exact wording varies by language, and it's worth knowing the shape of it so you're not searching for the wrong phrase at 11 p.m.:
| Runtime | What you'll typically see |
|---|---|
| Node.js | A "JavaScript heap out of memory" message from V8 if the heap ceiling is hit first, or a bare "Runtime exited with error: signal: killed" if the OS kills the whole process before V8 gets to report anything |
| Python | Usually no Python-level traceback at all — the process is killed mid-instruction, so the last thing in the log is often just the crash notice, not a MemoryError your except block could have caught |
| Java | Sometimes an actual "java.lang.OutOfMemoryError: Java heap space," which is one of the few runtimes that gets a real chance to say what happened before the JVM gives up |
| Go, Rust, custom runtimes | A generic "fatal error: out of memory" from the language runtime, or the same platform-level "Runtime.ExitError" with no further detail |
Notice how many of these boil down to "the process just stopped." That's not a gap in AWS's logging — it's what actually happens when the kernel's out-of-memory killer steps in. There's no graceful shutdown to log, because graceful is exactly what an OOM kill isn't.
Is it really out of memory, or something wearing the same costume?
Before you touch the memory setting, it's worth thirty seconds to rule out the two problems that look almost identical in the log but need a completely different fix. Bumping memory won't help either of them, and you'll have spent money finding that out the hard way.
| Symptom | Likely cause | Does more memory fix it? |
|---|---|---|
| Max Memory Used at/above Memory Size, crash mid-invocation | Genuine out-of-memory kill | Yes, if sized correctly |
| Duration matches or exceeds the configured Timeout, Max Memory Used well under the limit | Function timed out, not a memory problem | Sometimes indirectly — more memory means more CPU, which can speed up a genuinely slow function, but the fix is really the Timeout setting or the code |
"No space left on device" or errors writing to /tmp |
Ephemeral storage is full, which is a completely separate setting from Memory Size | No — you need to raise ephemeral storage instead, see below |
| "Too many open files" or connection errors, memory usage looks normal | File descriptor or thread limit hit, often from SDK clients created inside the handler on every invocation | No — the fix is moving client setup outside the handler, not raising memory |
✅ Why this is the one to check first
The fastest way to tell these apart is to open CloudWatch Logs Insights and run one query against a week or two of REPORT lines, rather than eyeballing single invocations. A pattern across dozens of invocations tells you far more than any one crash does.
Here's a query that pulls exactly the numbers you need, comparing peak usage against your configured ceiling:
- Open the CloudWatch console and go to Logs Insights, then choose the log group for your function — it's named
/aws/lambda/your-function-name. - Run this query, which filters to REPORT lines and calculates the maximum, average, and minimum memory used across the time range:
filter @type = "REPORT" | stats max(@maxMemoryUsed / 1024 / 1024) as maxMemMB, avg(@maxMemoryUsed / 1024 / 1024) as avgMemMB, max(@memorySize / 1024 / 1024) as configuredMB - Compare
maxMemMBtoconfiguredMB. If they're within a few megabytes of each other on more than a handful of invocations, you're genuinely hitting the ceiling, not seeing a one-off spike. - If the query returns nothing at all for a period where you know invocations happened, that's its own signal — an invocation that crashes hard enough, fast enough, sometimes never gets to write a REPORT line, so a gap in the data can itself point at a severe OOM kill rather than a healthy quiet period.
Sizing memory honestly: the manual method
Lambda lets you set memory anywhere between 128 MB and 10,240 MB, in 1 MB increments, and you can change it through the console, the AWS CLI, or infrastructure-as-code tools like CloudFormation, SAM, or Terraform. The default for any function created in the console is the lowest possible setting, 128 MB — which AWS itself recommends only for simple functions that transform and route events to other services. Once your function imports real libraries, touches S3 or EFS, or does any actual processing work, 128 MB is rarely enough, and that's exactly the gap where OOM crashes show up first.
To change it through the CLI:
aws lambda update-function-configuration --function-name your-function --memory-size 512
The manual approach is simple, and for a low-traffic function it's often all you need:
- Set memory to a generous guess — double your best estimate is a reasonable starting point if you have no data at all.
- Let real traffic run for a few days, or replay a batch of realistic test events if the function is new.
- Pull the REPORT lines and find the actual peak Max Memory Used across that window, not just one invocation.
- Set Memory Size with real headroom above that peak — not the maximum available, not a round number picked out of habit, but a number that comfortably clears what you actually measured.
- Re-check after a week. Traffic patterns, payload sizes, and dependency versions change, and last month's safe number isn't guaranteed to still be safe.
What changed: memory and CPU used to feel like separate dials
- Before: many teams treated the Memory Size setting as purely a memory question — "how much RAM does my code need" — and left it low to save money.
- Now: AWS documents that CPU power is allocated in direct proportion to memory. At 1,769 MB a function reaches the equivalent of one full vCPU, and AWS's own troubleshooting guide states plainly that a function has access to more than one vCPU core above roughly 1.8 GB, reaching six vCPUs at the 10,240 MB maximum.
- What that means for the steps above: sizing memory purely by watching Max Memory Used can leave real performance on the table, even for functions that never come close to running out of RAM — AWS explicitly says you can improve performance by raising memory even when the function doesn't use all of it, because you're really buying CPU.
That last point is worth sitting with for a second. A function that's slow but never crashes isn't necessarily "fine as is" — it might be starved for CPU, and the only lever Lambda gives you to add CPU is the same Memory Size slider you're already looking at for the OOM problem. There's a catch worth being honest about, though: those extra cores past the one-vCPU line only help if your code can actually use more than one thread or process at a time. A single-threaded handler generally can't spend a second or third vCPU on its own; it's runtimes and libraries that internally use multiple cores — garbage collection, JIT compilation, certain crypto or compression libraries — that benefit automatically once more cores are available.
Letting AWS Compute Optimizer do the guessing for you
If manually pulling REPORT lines sounds like a chore — and for anyone running more than a handful of functions, it is — AWS Compute Optimizer can generate memory recommendations for you once it's opted in and has enough invocation history to work from. Instead of you reading logs, it reads them for you and hands back a suggested Memory Size based on actual production behavior over time.
It works from history, which is both its strength and its limit: a brand-new function, or one whose traffic just changed shape (a new customer with much larger files, say), won't have a reliable recommendation yet. Compute Optimizer is a good ongoing habit for a mature function, not a substitute for watching the REPORT line closely right after you deploy something new.
Where the recommendation shows up
Once your account is opted into Compute Optimizer and a function has accumulated enough invocation data, the recommended memory value appears directly in the Lambda console's configuration screen for that function, alongside the option to accept it with one click.
AWS Lambda Power Tuning: testing memory sizes like a scientist instead of a gambler
AWS Lambda Power Tuning is an open-source tool, built by AWS and run inside your own account through AWS Step Functions, that does something neither the manual method nor Compute Optimizer does on its own: it invokes your function multiple times at several different memory settings, back to back, and plots the resulting cost and duration against each other so you can see the actual trade-off curve instead of guessing at it.
♂️ Jake's Reality Check
"So I just... keep bumping the number until it stops crashing and call it a day? That feels like enough."
It's enough to stop the crash. It's not enough to know if you're paying for memory your function never touches. A function can stop crashing at 512 MB and still be wildly over-provisioned at 1,024 MB "just to be safe" — and that extra memory is billed every single invocation, forever, whether the function uses it or not.
Because Power Tuning runs your actual function code with actual payloads through actual HTTP calls and SDK interactions, its results reflect real production behavior far better than a synthetic benchmark would. AWS also documents that this tool can be wired into a CI/CD pipeline, so memory sizing gets re-checked automatically every time the function changes, rather than becoming a one-time decision nobody revisits for two years.
⚠️ What this actually costs if you skip it
Watch for the stretch around 1,769 MB to 1.8 GB — the one-vCPU line. Single-threaded handler code stops getting automatically faster from more memory once it's already using the one core it can use on its own, even though more cores technically become available above that point, up to six at the 10,240 MB maximum. If your Power Tuning curve keeps improving well past that line, that's worth double-checking rather than assuming: it usually means something in your runtime is genuinely using extra cores, which is fine, but it's a fact to confirm rather than a default to expect.
Runtime-specific memory traps
Here's where "what's your handler even written in" starts mattering. Different language runtimes manage their own internal memory before the Lambda platform's hard ceiling ever gets involved, and that internal ceiling can trip well before Max Memory Used reaches Memory Size.
Node.js: the V8 heap has its own opinion
Node's V8 engine manages its own "heap" — think of it as a workbench with a fixed size, separate from the room it's sitting in. Even if the room (the Lambda function's total Memory Size) has plenty of space, V8 can decide it's out of workbench space and throw its own "JavaScript heap out of memory" error before the OS ever needs to step in. You can raise V8's own ceiling with an environment variable, but the room it's sitting in still has to be big enough to hold the whole workbench plus everything else Node needs to run, so this is a tuning knob that works alongside an adequate Memory Size, not a replacement for one:
NODE_OPTIONS=--max-old-space-size=<value in MB>
As a general engineering habit rather than a fixed AWS-published number: leave headroom between the V8 heap ceiling you set and the function's total Memory Size, so the rest of the Node runtime and any native modules still have room to breathe. Setting the heap ceiling equal to the full Memory Size just moves the crash from "V8 says heap out of memory" to "the OS kills the process instead," which is a worse error message for the same underlying problem.
Python: no equivalent knob, but a way to watch
Python doesn't give you a direct heap-size dial the way Node does. What it does give you is the standard-library tracemalloc module, which you can use during development to trace which objects in your code are actually consuming memory, rather than guessing from the outside. This is a development-time tool, not something to leave running against production traffic, but it's genuinely useful for pinning down which library or data structure is the real culprit before you write a single line of the fix.
Java: the one runtime that usually tells you the truth on the way out
Java's JVM is the exception to the "the process just vanishes" pattern described earlier. Because the JVM manages its own heap explicitly, it often has time to log an actual java.lang.OutOfMemoryError: Java heap space before the process dies, which is a genuine gift if you're debugging a Java function — you get a real error message pointing at the real cause, instead of a generic "something died" notice.
Go, Rust, and custom runtimes: the OS gets there first
Compiled languages running through a custom or provided runtime tend to fall back to the platform-level crash notice covered earlier, because there's no separate managed heap standing between your code and the OS to catch the problem and log something friendlier on the way down.
When it isn't your code: /tmp, SDK clients, and warm-start ghosts
Three patterns account for most "we bumped the memory and it still crashes sometimes" tickets, and none of them are fixed by raising Memory Size further.
Ephemeral storage is a different meter entirely
Lambda gives every function ephemeral storage at /tmp, configurable between 512 MB and 10,240 MB in 1 MB increments, and it is billed and configured completely separately from Memory Size. A function that writes large temp files — extracting a zip, buffering a video, staging an ETL job — can run out of disk space in /tmp while its actual memory usage sits nowhere near the limit. If your errors mention disk space rather than memory, this is the setting to raise, not Memory Size.
There's a second trap hiding in this same directory: /tmp persists across warm invocations that reuse the same execution environment. If your code writes files there and never cleans them up, the third or fourth invocation on that same warm container can fail even though every individual invocation, in isolation, would have been fine.
SDK clients created inside the handler
If your function creates a new AWS SDK client, or a new database connection, every single time the handler runs rather than once outside it, you can exhaust the function's file descriptor and thread limit — 1,024 of them — which shows up as connection errors or "too many files open" messages that have nothing directly to do with memory, even though they get lumped into the same "the function is broken" bucket by whoever's on call. Moving client and connection setup to the global scope, outside the handler function, lets warm invocations reuse the same connections instead of piling up new ones.
The slow leak that only shows up after a while
This is the pattern that matches Jake's photo-resizing job, and it's specific enough that AWS's own troubleshooting documentation names it directly as "memory leakage between invocations." A genuine memory leak in the handler code doesn't crash the first invocation, or the fifth, or usually the tenth. It accumulates across every invocation that reuses the same warm execution environment, and because Lambda freezes and resumes that environment between invocations rather than starting fresh each time, whatever your code failed to clean up on invocation four is still sitting there for invocation five to inherit.
The documented symptom pattern is distinctive once you know to look for it: invocations run fine at a steady rate for a while, then duration starts climbing as the underlying system pages memory to disk to cope with the growing footprint, and eventually the function starts erroring out — either from timing out because everything got slower, or from the execution environment being stopped outright. If Jake's job fails "about a third of the time" rather than consistently, this pattern, tied to however many invocations happen to land on the same warm container before AWS eventually recycles it, is the most likely explanation.
Why your account might be capped below 10,240 MB
Every Lambda function can technically be configured up to 10,240 MB, but AWS documents that new accounts start with reduced memory and concurrency quotas, which raise automatically as usage grows. If you try to set memory above what your account currently allows, you'll get a specific, unambiguous rejection rather than a silent failure — the update simply won't apply, and the error will name the exact ceiling your account is currently allowed. If you've genuinely outgrown that ceiling, a Service Quotas increase request through AWS Support resolves it; it isn't something you can raise from inside the Lambda console itself.
⚠️ What this actually looks like
A rejected memory update on a brand-new account isn't a bug in your CLI command or your CloudFormation template. It's the account-level quota, and no amount of retrying the same request will change the outcome — only a quota increase will.
The cost math nobody explains before you touch the slider
Lambda bills roughly on Billed Duration multiplied by Memory Size. Double the memory and, all else equal, you'd expect double the cost for the same work. But all else usually isn't equal, because more memory also means more CPU, and more CPU often means the function finishes faster — sometimes dramatically faster, if the function was CPU-starved rather than just memory-tight. That's how a function can double its memory setting and see its bill stay almost flat, because duration dropped by nearly the same factor memory went up.
| Situation | What raising memory does to cost |
|---|---|
| Function is I/O-bound (waiting on a network call, a database, an external API) | Cost rises close to proportionally — the extra CPU has little to speed up while the function is mostly waiting, so you're just paying for a bigger, mostly idle room |
| Function is CPU-bound (image processing, compression, heavy computation) | Cost can stay flat or even fall, because duration drops enough to offset the higher per-millisecond rate |
| Function is already comfortably under 1,769 MB and single-threaded | Diminishing returns are less likely yet; there's usually still real speed to buy for the money below the one-vCPU line |
| Function is already well past 1,769 MB and single-threaded | Extra cores become available — up to six at the 10,240 MB maximum — but a single-threaded handler can't spend them on its own, so further increases mostly just raise cost unless the runtime itself uses multiple cores; this is the point to stop guessing and let Power Tuning show you the actual curve |
This is why "just set it to max and forget it" is the wrong instinct even when it technically stops the crash. It trades a debugging problem for a recurring, invisible line item on the AWS bill that nobody revisits until finance asks why the Lambda spend crept up.
When you've raised memory and it still fails
Say this plainly, because it's the least comfortable but most useful thing in this entire post: if you've already raised memory to something generous and the function still runs out, more memory was never the actual fix — it was buying time against a leak or an unbounded input, and that time has run out.
Ask whether the input itself is unbounded
AWS's own troubleshooting documentation walks through exactly this scenario: a function with 128 MB of memory performing image processing on a JPG file stored in S3 works fine for typical files, then throws an out-of-memory error the day a much larger JPG shows up as input. Nothing about the code changed; the input did. A function sized correctly for a typical file can still run out of memory the day someone uploads a file ten times the usual size, and if there's no validation on input size before your code starts loading the whole thing into memory, no amount of Memory Size headroom is truly safe — you're just moving the failure point further out, not removing it. AWS's own recommendation here is to test with examples from the upper bounds of expected data sizes and to validate payload sizes explicitly, rather than assuming typical inputs will always stay typical.
Ask whether the leak is in your code or a dependency
Not every leak is something you wrote. A library your code depends on can hold references longer than it should, especially across the kind of warm-container reuse Lambda relies on for performance. If Python's tracemalloc, or the equivalent profiling for your runtime, points at objects you never explicitly created and never explicitly free, that's usually a sign to look at what a dependency does with its own internal caches or connection pools rather than assuming your handler logic is at fault.
Consider Lambda Insights for the pattern you can't see from REPORT lines alone
Lambda Insights, an enhanced monitoring option you can turn on for a function, tracks metrics REPORT lines don't expose on their own, including open file descriptor counts over time via its fd_use metric. For the specific "too many files open" pattern from SDK clients created inside the handler, this is the tool that shows you the trend building up, rather than making you infer it after the fact from a pile of crash logs.
✅ The honest bottom line
Memory sizing solves memory sizing problems. It doesn't solve unbounded inputs, dependency leaks, or file-descriptor exhaustion, even though all three can look identical to a genuine OOM on the surface. The REPORT line and a week of pattern-watching tell you which one you actually have before you spend money guessing.
Back at Jake's shop, the fix ended up being two changes, not one: the function's memory went from 128 MB to 384 MB, comfortably above the roughly 260 MB peak a week of REPORT lines actually showed, and the code that resized photos got a line added at the top of the handler to clear out any leftover temp files from a previous invocation on the same warm container. Neither change alone would have solved it. Together, the failed-listing calls stopped.
Frequently asked questions
How do I know if my Lambda function actually ran out of memory?
Check the REPORT line for the failed invocation. If Max Memory Used is at or very close to Memory Size, and the log above it shows a runtime crash notice like "Runtime exited without providing a reason" rather than an exception from your own code, that's a genuine out-of-memory kill.
What does "Max Memory Used" mean if it's lower than "Memory Size"?
It means the execution environment never needed all the memory you configured for that stretch of invocations. It's not automatically a problem, but a very large gap can mean you're over-provisioned and paying for memory the function doesn't use.
Why does Max Memory Used sometimes show a number close to my memory limit even though the function succeeded?
Because Lambda can reuse the same running execution environment across several invocations, and Max Memory Used reports the peak across every invocation that environment has handled, not just the current one. A successful, lightweight invocation can still report a high number if a heavier invocation ran on the same warm container earlier.
What's the difference between Memory Size and ephemeral storage?
Memory Size controls RAM available while the function runs, from 128 MB to 10,240 MB. Ephemeral storage controls disk space at /tmp, configured separately between 512 MB and 10,240 MB. Running out of one produces different errors than running out of the other, and raising one setting does nothing for the other.
Does increasing Lambda memory also increase CPU?
Yes. Lambda allocates CPU power in direct proportion to the configured memory. There's no separate CPU setting; memory is the only lever you have for both.
What is the 1,769 MB vCPU threshold and why does it matter?
At 1,769 MB, a Lambda function reaches the equivalent of one full vCPU. Above roughly that point, the function has access to more than one vCPU core, up to six vCPUs at the 10,240 MB maximum. A single-threaded handler generally can't use those extra cores on its own, though, so the practical benefit past that line depends on whether the runtime or its dependencies actually use multiple cores.
How much does it cost to run Lambda functions with more memory?
Billing is based on Billed Duration multiplied by Memory Size, so cost rises with memory on its own. Whether the total bill rises depends on whether the extra CPU that comes with more memory also shortens the duration enough to offset it, which tends to happen for CPU-bound functions and not for functions that are mostly waiting on network or database calls.
What is AWS Lambda Power Tuning and how do I use it?
It's an open-source tool, run through AWS Step Functions in your own account, that invokes your function at several memory settings using real payloads and measures the resulting cost and duration at each one, so you can pick the actual sweet spot rather than guessing. It can also be wired into a CI/CD pipeline to re-check sizing automatically as the function changes.
Does AWS Compute Optimizer work for every Lambda function?
It needs your account opted in and enough invocation history to build a reliable recommendation, so it works best for functions with steady, established traffic. A brand-new function, or one whose traffic pattern just changed significantly, won't have a trustworthy recommendation yet.
Why does my Lambda function get "Runtime exited with error: signal: killed"?
That message usually means the operating system killed the function's process directly, most often because it exceeded the available memory. Because the process is terminated rather than allowed to fail gracefully, your own error-handling code never gets a chance to run or log anything more specific.
Can a memory leak cause failures even if I stay under my memory limit most of the time?
Yes. Because Lambda can reuse the same execution environment for multiple invocations, a leak that doesn't clean up after itself accumulates across those invocations. AWS's own troubleshooting documentation names this pattern directly: the environment can run fine for a stretch, then start slowing down as memory pressure builds, and eventually fail, even though no single invocation looked obviously oversized on its own.
Why does Node.js run out of memory before hitting the configured Memory Size?
Node's V8 engine manages its own internal heap with a default ceiling that's independent of the Lambda function's total Memory Size. V8 can hit its own limit and throw a heap-out-of-memory error well before the surrounding process reaches the platform's actual memory ceiling. Raising V8's heap size with the NODE_OPTIONS environment variable, alongside an adequate Memory Size, addresses this.
How do I monitor Python Lambda memory usage during development?
Python doesn't expose a direct heap-size setting the way Node does, but the standard-library tracemalloc module lets you trace which objects in your code are actually consuming memory. It's best used during development against test payloads rather than left running against live production traffic.
What's the maximum memory I can allocate to a Lambda function?
10,240 MB, configurable in 1 MB increments starting from a minimum of 128 MB. New AWS accounts may start with a lower effective cap that rises automatically with account usage, or can be raised on request through a Service Quotas increase.
Why is my new AWS account capped below 10,240 MB?
New accounts start with reduced Lambda memory and concurrency quotas as a default safeguard. These quotas rise automatically as the account's usage grows, or can be increased directly by filing a Service Quotas limit-increase request with AWS Support if you've genuinely outgrown the current cap.
Should I just set every Lambda function to the maximum memory to be safe?
It will usually stop the crashing, but it isn't sizing — it's paying to avoid the question. Every invocation is billed against whatever Memory Size you set, whether the function uses it or not, so a maxed-out setting that isn't actually needed becomes a permanent, invisible cost. Measuring the real peak and adding honest headroom above it gets you the same reliability without the padding.
Revision note. Written September 2026. This will need a fresh look if AWS changes the REPORT line format further, moves the vCPU-equivalent threshold, or expands the memory ceiling past 10,240 MB. If you're reading this at 11 p.m. with a crashing function and a customer waiting, take a breath — the REPORT line already has the answer, it just needed someone to point at the right number.