This argument usually gets settled by whoever on the team feels most strongly, which is a poor way to pick a runtime. The honest answer is that the technical differences matter less than four questions about your workload and your team.
How long does a request run?
Lambda caps a single invocation at fifteen minutes. If any part of your workload runs longer — a video transcode, a large report, a nightly batch job — that part is not going on Lambda, and splitting it into chunks to fit is a design compromise you will resent.
Everything under a few seconds is comfortable Lambda territory. Between those two, it depends on how spiky the traffic is.
What shape is the traffic?
Lambda bills per millisecond of execution. Idle costs nothing. That is transformative for workloads that are quiet most of the day and busy in bursts — internal tools, webhooks, scheduled jobs, an API that gets a few thousand calls a day.
For steady traffic that keeps containers busy around the clock, per-millisecond billing stops being an advantage and a right-sized Fargate task or an EC2 fleet under a Savings Plan is usually cheaper. Crossover depends on your request profile, so measure rather than assume.
Cold starts: real, usually survivable
A new Lambda execution environment takes time to initialise before your code runs. For a Python or Node function with light dependencies, that is generally a small fraction of a second. For a JVM function with a heavy framework, it is long enough that a user notices.
Provisioned concurrency removes cold starts by keeping environments warm — and reintroduces a fixed hourly cost, which undercuts the main reason people chose Lambda. If you need provisioned concurrency across the board, that is a signal to look at containers.
What are you willing to operate?
This is the question that actually decides it for most small teams.
- Lambda — no servers, no patching, no capacity planning. You give up control over the runtime and take on a different debugging experience.
- ECS on Fargate — containers without managing nodes. Simpler than Kubernetes by a wide margin, integrated with the rest of AWS, and the right default for most teams that need containers.
- EKS — full Kubernetes. Portable, enormous ecosystem, and a genuine operational burden: control plane charges per cluster, version upgrades on the AWS schedule, and someone on the team who knows what a CRD is.
A four-person team running EKS because it might be needed at scale later is a team spending its time on cluster upgrades instead of product. If you are not already running Kubernetes and do not have a hard multi-cloud requirement, Fargate is almost always the better call.
The answer is usually both
Most estates we work on end up mixed, and that is fine. The main API sits in containers because traffic is steady and the framework is heavy. Image processing, scheduled reports, S3 event handlers, and Slack integrations sit in Lambda, where they cost almost nothing between invocations.
Pick per workload. The one thing worth avoiding is three different deployment pipelines for three different runtimes because nobody chose a default.