A team is choosing between serverless functions and long-running containers for a new workload. What evidence should drive the decision, and which arguments on both sides are usually wrong?
Show the full answer Hide the answer
The evidence that actually decides it
Traffic shape. Spiky, unpredictable, or with long idle periods → serverless, because you are paying for idle capacity otherwise, and scale-to-zero is a genuine economic advantage. Steady, sustained, high-volume → containers, because per-request pricing is a premium over reserved capacity and the premium compounds with volume.
Request duration and memory profile. Short, small, stateless requests fit the model. Long-running, memory- heavy, or stateful-within-a-request work fights it, and per-invocation limits become architectural constraints.
The cost-per-request crossover. This is calculable and rarely calculated: at some request volume, the serverless premium exceeds the cost of a container fleet plus the operational effort. Compute that crossover for your actual workload before deciding, and re-compute it when volume grows by an order of magnitude.
Data locality and chattiness. If the function must exchange large payloads with other steps, each boundary is a network hop and possibly an object-storage round trip — and this is where per-request cost quietly becomes dominated by coordination and transfer rather than compute.
Connection patterns. A function that opens a database connection per invocation destroys a connection-pooled database at scale. This needs a proxy or a data API, and that requirement should be in the decision, not discovered later.
The arguments that are usually wrong
- "Serverless does not scale." It scales extremely well. It sometimes costs too much at scale, which is a different and more tractable statement.
- "Cold starts make it unusable." Cold starts are a real tail-latency effect and are mitigable — provisioned concurrency, smaller packages, runtimes that start faster, and instance reuse. For asynchronous and background work they are close to irrelevant, and much serverless work is asynchronous.
- "Containers mean managing servers." Managed container platforms remove most of that, and the comparison should be against those, not against self-managed virtual machines.
- "Serverless is simpler." It moves complexity rather than removing it: into IAM, into per-function configuration, into cold-path testing, and into local development that no longer resembles production.
- "We will avoid lock-in with containers." Real lock-in is usually in the managed data services and the event plumbing, not the compute layer.
The consolidation trap, stated precisely
Decomposing a workload into one function per step is wrong when the steps are chatty and the payloads are large, because orchestration is billed per transition and intermediate data crosses a network boundary at every step. This is a real and well-documented failure — it is a statement about the granularity of decomposition, not about serverless as a compute model.
The correct granularity is usually "one function per independently-triggered unit of work", not one function per logical step within that unit.
The pragmatic answer
Most systems should be both. Steady, high-volume request serving on containers; event-driven glue, scheduled work, spiky asynchronous processing and integrations on functions. Choosing one for the whole estate is a preference being expressed as an architecture.