Execution Model Fit
Matching a workload's traffic shape, duration and state requirements to the execution model that suits it, rather than choosing one model for everything.
The decision turns on the shape of the workload, and the answers are usually clear once it is described honestly.
Serverless functions suit spiky or infrequent traffic, event-driven processing, short-lived work and small teams that want no infrastructure. The economics are excellent for low or bursty utilisation — scale to zero means paying nothing when idle — and poor for sustained high utilisation, where a running container is considerably cheaper.
The constraints that decide it in practice: cold starts (mitigated but not eliminated by provisioned concurrency, which also removes the scale-to-zero economics), execution time limits, statelessness between invocations, connection management — a function per request against a relational database exhausts connections without a pooler — and local development and debugging friction.
Containers suit steady traffic, long-running processes, workloads with substantial memory or specialist dependencies, and anything needing portability across environments.
The realistic answer for most estates is both: containers for core services, functions for glue, event handling and scheduled work. Choosing one model as a standard produces either expensive functions running constantly or containers idling to serve an occasional event.