intermediate 2 min answer

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?

serverlesscontainerscost-per-requestcold-startdecision
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.