Skip to content

How does Lambda handle host resource usage (RAM/disk/network) when scaling concurrency with large container images (~1GB)?

0

I'm trying to understand the underlying resource behavior when a Lambda function backed by a ~1GB container image scales to handle a burst of concurrent requests. From what I understand, each concurrent invocation gets its own Firecracker microVM (execution environment), and the memory available to each microVM is bound by the function's configured memory setting (e.g. 512MB), not by the image size itself. What I'd like to clarify:

Image layer loading across concurrent microVMs — When 100 concurrent invocations spin up on the same underlying host, does each microVM pull/load the image layers independently, or are image layers cached/shared at the host level (e.g. via the lazy-loading block device mechanism described for Lambda container image support)? Specifically, does scaling concurrency multiply disk I/O and network egress for image retrieval, or is there a single fetch per host with subsequent reads served from a shared cache? Per-host capacity impact — As concurrency increases for a function using a large image, what host-level resources actually become the bottleneck first — RAM (per function memory config), disk space for image caching, network bandwidth for image pulls, or something else? Is there documented guidance on how image size affects max achievable concurrency density per host? Cold start cost scaling — Does a larger image size (closer to the 10GB limit) cause cold start latency to scale linearly with concurrency under burst load, or is the lazy-loading mechanism designed to keep cold start latency roughly constant regardless of concurrent invocation count?

Any pointers to official architecture docs or re:Invent talks covering the internals here would also be appreciated — I've read the general container image support announcement but it doesn't go deep into host-level resource sharing behavior under concurrent load.

4 Answers
0
Accepted Answer

As a follow-up to @Thanh:

Thanks, that’s a fair way to compare the two models, but I’d tweak one part of the Lambda side.

You’re right that EC2 and Lambda have different tradeoffs. On EC2, if you’re running a containerized API on a long-lived instance, the app process can start once and keep serving requests until the instance, task, or process is restarted. You manage the capacity, and in return, you get a long-running process.

With Lambda, you don’t get that same “this app process is always running” guarantee. Lambda creates execution environments when it needs them, reuses them when it can, and eventually removes them when they’re no longer needed. AWS describes that lifecycle here: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html

So yes, if an execution environment has been removed and Lambda needs a new one, that new environment has to run initialization again before it can serve the request. If your app startup imports a large framework, opens database clients, scans files, loads models, or builds a lot of in-memory state, that init cost can come back on cold starts.

The part I wouldn’t describe as accurate is “Lambda pulls the full 1 GB image after every idle gap.” A cold start means a new execution environment and a new init path. It does not necessarily mean a fresh full Docker-style image pull from ECR every time.

For container image functions, AWS has a separate image-optimization lifecycle. After you create or update the function, Lambda optimizes the container image before the function becomes active. AWS documents that here: https://docs.aws.amazon.com/lambda/latest/dg/images-create.html#images-create-lifecycle

That same lifecycle is also why an unused container image can later become Inactive after multiple weeks without being invoked. In that case, Lambda may need to re-optimize the image before the function becomes active again. That’s different from a normal execution environment being recycled after an idle period.

So I’d frame the comparison this way: EC2 provides always-on capacity, so the app stays initialized between requests. At the same time, on-demand Lambda removes the need to pay for idle execution time but may require initializing a new execution environment when traffic returns. The repeated cost you should assume for a Lambda cold start is the runtime and application initialization for that new environment, not necessarily a full 1 GB image pull from ECR. The “image reclaimed and re-optimized” case exists too, but that’s a separate lifecycle case tied to a function being unused for multiple weeks, not every normal idle gap.

If the API is latency-sensitive and you want Lambda to behave more like “initialized capacity is already waiting,” provisioned concurrency is the Lambda feature built for that. AWS describes it as pre-initialized execution environments that are ready to respond immediately: https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html

That doesn’t make Lambda the same as EC2, because you’re now paying to keep capacity prepared, and Lambda still manages the underlying hosts. But it addresses the main concern in your comparison: avoiding user-facing cold starts after quiet periods.

One extra note: SnapStart is sometimes mentioned in cold-start discussions, but it doesn’t help this particular case if you’re using a container image, because Lambda SnapStart doesn’t support container image functions: https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html

Thanks,

James

answered 2 months ago

0

Hola,

I agree with the other answers here: AWS doesn't really publish the host-level details for this. You can find docs on Lambda concurrency and scaling. Still, not on things like host placement, exactly how image cache is shared across hosts, or a formula like "a 1 GB image means fewer execution environments per host." That's probably by design. Lambda is a managed service, so AWS can keep changing its internals without forcing customers to design around them.

That said, I wouldn't think of a 100-concurrency burst as "Lambda pulls the full 1 GB image 100 separate times." As Brettski-AWS mentioned, Marc Brooker's "On-Demand Container Loading in AWS Lambda" paper is probably the best public explanation of what's going on under the hood: https://www.usenix.org/conference/atc23/presentation/brooker

There's also an arXiv copy here: https://arxiv.org/abs/2305.13162

The important idea from that paper is that Lambda doesn't treat container startup like a normal Docker host pulling and unpacking a whole image before anything can run. The image is turned into a block-device-style filesystem, split into chunks, and loaded on demand as the function actually reads those parts of the image. Those chunks can come from cache close to the worker, a wider AZ-level cache, or S3 behind the scenes.

So, for the image-loading question, I'd answer: probably not independent full-image pulls in the usual container sense. Each concurrent invocation still runs in its own execution environment, so each can read from its own mounted filesystem. But that doesn't mean each microVM has to download the entire image or pull every layer by itself. The published design is built around lazy loading and cache reuse.

For the host bottleneck question, I don't think there's a public answer like "RAM is always first" or "network is always first." From the customer side, the meaningful controls are still the normal Lambda controls: memory size, ephemeral storage, reserved concurrency, provisioned concurrency, account concurrency limits, the function scaling rate, and what your code actually does during init and invoke.

AWS documents Lambda scaling behavior here: https://docs.aws.amazon.com/lambda/latest/dg/scaling-behavior.html

At the time I'm writing this, Lambda documents that a function can scale by up to 1,000 new execution environments every 10 seconds, subject to account concurrency and other limits.

AWS documents Lambda memory configuration here: https://docs.aws.amazon.com/lambda/latest/dg/configuration-memory.html

Memory is still important because each concurrent request needs its own execution environment, and Lambda allocates CPU in proportion to the configured memory. But image size and runtime memory use are different things. A 1 GB image can run fine in a 512 MB function if the running process only needs that much memory. A much smaller image can still run out of memory if the app loads a lot into RAM.

For cold starts, I also wouldn't assume "twice the image size means twice the cold start," especially with Lambda's on-demand loading model. What matters more is what your function touches during startup. If your init path only needs a small part of the image, a large image may not hurt as much as you'd expect. If your app imports a large dependency tree, scans files, loads models, or reads many assets during init, then the image contents can absolutely affect cold start time.

The practical things I'd check are:

  • Keep the init path small. Don't load large models, dependency trees, font packs, static assets, or other bulky files during init unless every invocation needs them immediately.
  • Use AWS Lambda base images where possible, since common base content is more likely to benefit from Lambda's optimizations and caching.
  • Put the code that changes most often toward the end of the Dockerfile so you don't keep invalidating large base layers on every build.
  • During burst testing, watch Init Duration, total duration, Max Memory Used, throttles, and concurrency. Those numbers will tell you more than image size alone.
  • If you're seeing a real production bottleneck, open an AWS Support case with the image size, memory setting, init duration, concurrency target, burst-test results, and any throttling or errors. They can examine service-side behavior that public docs don't expose.
  • If you need predictable control over host placement, local disk behavior, image pull behavior, or instance sizing, Lambda may not be the right abstraction. ECS, EKS, or Fargate will give you more control over those details.

Lambda's design shouldn't treat each concurrent execution as a full image pull, but AWS doesn't expose enough host-level details to predict the exact RAM, disk, or network bottleneck from image size alone. I'd use the Brooker paper to understand the design, but I wouldn't treat it as a customer-facing service contract.

Thanks,

James

answered 2 months ago

  • Thanks for your answer I do have some questions about this, glad to hear response from you soon

    I want to validate one specific architectural comparison between EC2 and Lambda for an API workload, building on an earlier thread here about container image loading. On EC2, the app process starts once and stays running indefinitely. Every request just hits an already-initialized app and returns a response — no re-init cost, no image pull, per request. On Lambda, my understanding is: the app isn't running continuously. When a request comes in after the environment has been idle/reclaimed, Lambda has to spin up a fresh execution environment, pull/load the container image (~1GB in my case), and run through the entire app initialization just to serve that one endpoint — even if the actual response is just a few KB. If the environment sits idle past some internal timeout, it's torn down, and the next request after that gap pays the same cost again: image load + full init, repeated from scratch. So compared to EC2 (pull image once, init once, serve forever), Lambda seems to repeatedly pay "pull the image + boot the whole app" every time there's a gap in traffic long enough for the environment to be reclaimed — which feels disproportionate when the image is ~1GB but the actual work done per invocation is small. Questions:

    Is this accurately described as architectural overhead inherent to Lambda's execution model — i.e., is "image pull + full app init repeated after every idle teardown

0

Based on the available documentation, Lambda's scaling behavior focuses on concurrency limits and scaling rates rather than the specific host-level resource mechanics you're asking about. Here's what is documented:

Concurrency Scaling Behavior: Lambda scales by allocating execution environments at a rate of up to 1,000 additional execution environment instances every 10 seconds (or 10,000 requests per second every 10 seconds) per function. This scaling rate is a function-level limit, meaning each function scales independently. When your function receives increasing requests, Lambda scales at the fastest rate available up to your account's concurrency limit. If requests arrive faster than your function can scale or if maximum concurrency is reached, additional requests fail with a throttling error (429 status code).

Execution Environment Behavior: When you first invoke a function, Lambda creates an instance of the function and runs its handler. When the function returns a response, it stays active to process additional events. If you invoke the function again while the first event is being processed, Lambda initializes another instance, allowing concurrent processing. As more events arrive, Lambda routes them to available instances and creates new instances as needed.

What's Not Documented: The specific questions you're asking about—image layer caching mechanisms across concurrent microVMs on the same host, per-host capacity bottlenecks related to image size, and whether cold start latency scales linearly with image size under burst load—are not covered in the available public documentation. These implementation details about host-level resource sharing, disk I/O patterns for container image layers, and the internal architecture of how Lambda manages container images across concurrent executions are not publicly disclosed.

For workloads requiring specific control over compute resources and scaling behavior, you might want to explore Lambda Managed Instances, which allows you to select specific EC2 instance types and provides more visibility into resource utilization through CloudWatch metrics at both the function and capacity provider levels. However, this still doesn't expose the low-level image caching mechanics you're asking about.

I'd recommend reaching out through the AWS Support Center if you need architecture guidance specific to your use case with large container images under high concurrency.
Sources
Understanding Lambda function scaling - AWS Lambda
Lambda scaling behavior - AWS Lambda
Elastic - Reactive Systems on AWS
re:Invent 2025 - Lambda Managed Instances: EC2 Power with Serverless Simplicity | AWS re:Post

answered 2 months ago

EXPERT

reviewed 2 months ago

0

The re:Post Agent answer is good and for a lot of the stuff you're asking (as that answer says) there is no documentation. That allows AWS to change the implementation details and improve how the service is delivered. Lambda is a managed service - it's a vast abstraction of compute (in general) so all of those things are "taken care of".

That said, you might want to look at this paper and talk from Marc Brooker where he talks about how Lambda delivers large container images quickly and at scale.

If you are experiencing issues then I'd suggest a support case is the way to go. If you want more control over how the underlying host environment is set up, then ECS or Fargate are good choices.

EXPERT

answered 2 months ago

EXPERT

reviewed 2 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.