DEV Community

Cover image for Serverless vs Containers (2026): How to Choose for Cost, Scale and Speed
softverseAdmin
softverseAdmin

Posted on Edited on Originally published at devopsenginer.com

Serverless vs Containers (2026): How to Choose for Cost, Scale and Speed

Introduction: in 2026, it is rarely either/or

Should you build on serverless, or on containers?

It is still one of the most argued questions in cloud architecture — because the answer decides your cloud bill, how much infrastructure your team has to run, how fast you can ship, and how painful your system is to change later.

You will hear the two standard arguments:

"Serverless is simpler — no servers, no clusters, no ops."

"Containers are more flexible — portable, predictable, and built for complex systems."

Both are true — for different workloads. And in 2026 there is a third point that matters more than either argument: the line between the two has blurred. You can now run a container and pay for it in a serverless way, scaling to zero, with no cluster to manage. For a lot of teams, that middle option is the right starting point, and the old binary debate misses it.

So this guide does not crown a winner. It gives you:

  • A clear comparison of cost, performance, scaling, operations, security, and lock-in
  • A 7-question decision framework you can run any workload through
  • Workload-by-workload recommendations
  • The hybrid patterns most production systems end up with

Most of my own project work sits closer to containers — including the 3D portfolio behind this site — because I like controlling the runtime and deployment shape. Serverless still gets a fair hearing here: for event-driven and spiky workloads, it often wins.

Originally published on DevOps Enginer.

The short story that explains most real systems

Imagine two teams — these are illustrative scenarios, not specific companies:

Team A is small and building a new SaaS product. Speed matters most, traffic is unknown, and nobody wants to run infrastructure. They start serverless — functions behind an API, a managed database, object storage, and an event bus — and ship quickly.

Later, one part of the system becomes a problem: a long-running, steady-traffic workload that is always busy. On a pay-per-request model it never gets a chance to be cheap, and they want more control over its runtime. They move that workload — not the whole system — to containers.

Team B is larger and needs consistency: an internal platform, custom networking, and long-running services with predictable performance. They build on containers and Kubernetes.

Later, they notice a different problem: a pile of small, spiky, event-driven jobs — webhooks, file processing, scheduled clean-ups — that are a poor use of an always-on platform. They move those jobs to serverless.

Notice the pattern: neither team "switched sides". Each moved individual workloads to the model that fit them. That is what mature architectures look like.


TL;DR — the decision in 30 seconds

If your workload is mainly… Start with
Event-driven, spiky, unpredictable, or very low traffic Serverless functions
A normal API/web service and you want low ops without function constraints Serverless containers (e.g. Cloud Run, Fargate, Azure Container Apps)
Long-running, steady, high-volume, or latency-sensitive Containers (managed Kubernetes or a container platform)
GPU-heavy, custom-runtime, or needs special networking Containers
A mix of the above (most real systems) Hybrid: containers for the core, serverless for events and glue

Rule to remember: choose per workload, not per company.


What "serverless" actually means in 2026

"Serverless" does not mean there are no servers. It means you do not provision, patch, or pay for idle servers — the provider runs the infrastructure, scales it, and bills you for use.

Today it covers several different things, and mixing them up causes bad decisions:

1. Functions-as-a-Service (FaaS)

Small units of code that run in response to an event: an HTTP request, a file uploaded, a message on a queue, a schedule.

  • Examples: AWS Lambda, Google Cloud Functions, Azure Functions
  • You get: automatic scaling, pay-per-invocation style billing, minimal operations
  • You accept: execution limits set by the provider, less control over the runtime environment, and a design built around events and managed services

2. Serverless containers

You ship a normal container image, but the platform runs it serverlessly — scaling (often to zero), load balancing, and billing based on the resources your container actually uses while handling requests.

  • Examples: Google Cloud Run, AWS Fargate (with ECS), Azure Container Apps
  • You get: your own runtime and dependencies, longer-running requests than a function typically allows, no cluster to manage
  • You accept: platform-specific configuration, and cold starts when the platform scales from zero

This category is the biggest change to the old debate. A lot of "serverless vs containers" is now really "functions vs serverless containers vs Kubernetes".

3. Serverless back-end services

Managed services you build on rather than run: serverless databases, object storage, queues, event buses, and authentication.

  • Examples: Amazon DynamoDB, Aurora Serverless v2, Google Firestore, Amazon S3, Amazon SQS / EventBridge, Azure Cosmos DB
  • These combine with both models above. Using Lambda does not force you into any one database, and Kubernetes does not prevent you using a serverless database.

4. Edge functions

Small functions that run close to the user, typically for request/response customisation, redirects, header/security logic, A/B routing, or light personalisation.

  • Examples: Cloudflare Workers, AWS Lambda@Edge, Vercel Edge Functions
  • These are a complement to a main back end, not a replacement for one.

What "containers" means in 2026

A container packages your code with its runtime and dependencies so it runs the same way on your laptop, in CI, and in production. That consistency — not Kubernetes itself — is the core value.

In practice, "containers" can mean three levels of control and responsibility:

Level What you run What you manage
Serverless containers A container on a fully managed platform Your image and its settings
Managed Kubernetes EKS, GKE, AKS (often with an autopilot/autoscaling mode) Your workloads; the provider manages much of the control plane and node lifecycle
Self-managed Kubernetes Your own clusters, on cloud or on-premises Almost everything, including upgrades and control-plane reliability

Supporting tools you will commonly see around Kubernetes include cluster/node autoscalers (for example Karpenter), GitOps controllers (for example Argo CD), and infrastructure-as-code tools. They reduce operational effort — they do not remove it.

What containers give you, at every level:

  • Full control over runtime, libraries, and system packages
  • Predictable, always-warm performance once the service is running
  • Portability of the workload format (an OCI container image) across providers and on-premises
  • A natural fit for long-running services, streaming, WebSockets, and background workers
  • GPU and custom-hardware options on the platforms that offer them

The full comparison

Factor Serverless functions Serverless containers Containers on Kubernetes
Unit of deployment A function A container image A container image, orchestrated as services
Scaling Automatic, per event/request Automatic, based on concurrent requests; can scale to zero Autoscaling of pods and nodes; you configure the policies
Idle cost Near zero when unused Near zero if scaled to zero You pay for the cluster/nodes that stay up
Cold starts Possible on new execution environments Possible when scaling from zero No cold start for already-running replicas
Long-running work Constrained by provider execution limits Better suited than functions; still check platform limits Best fit — services run indefinitely
Runtime control Lowest — provider-defined environment High — your image Highest — your image plus platform/network control
Operations burden Lowest Low Highest — upgrades, capacity, networking, platform skills
Portability / lock-in Highest lock-in — events, triggers and managed services are provider-specific Medium — the image is portable, the platform config is not Lowest at the workload level; your surrounding platform tooling may still be provider-specific
Observability Many small units; needs disciplined logging/tracing from day one Similar to a normal service Familiar service-level logs/metrics, but a larger platform to observe
Best at Events, glue, spiky and low-volume work APIs and services for small-to-mid teams Core platforms, steady scale, special requirements

Performance and cold starts

A cold start is the delay when a platform has to prepare a new execution environment before your code runs. It affects functions and any platform that scales to zero.

Practical guidance — without magic numbers:

  • Cold-start impact depends on runtime, package size, memory allocation, and whether the function is attached to a VPC. Heavy runtimes and large dependency bundles are usually slower to start than small, lean ones.
  • If a user-facing API has a strict latency budget, measure cold starts with your code in your region. Do not copy numbers from another article (including the previous version of this one).
  • Mitigations exist (smaller packages, keeping dependencies lean, provisioned/pre-warmed capacity where the provider offers it), but pre-warming usually reintroduces cost — it is a trade-off, not a free fix.
  • Always-on container replicas avoid cold starts for the traffic they are already handling. That is one reason latency-critical core APIs often stay on containers.

Scaling

  • Functions scale by creating more concurrent executions in response to events. That is excellent for bursts, but account/provider concurrency limits exist — check them, and request increases before a launch that depends on them.
  • Serverless containers scale by adding container instances based on concurrency. Tuning the requests-per-instance setting is your main performance/cost lever.
  • Kubernetes scales in two layers: pods (via the Horizontal Pod Autoscaler, or event-driven autoscalers such as KEDA) and nodes (via a cluster autoscaler). You get more control, and more things to configure and test.

Cost: a method, not a myth

The original version of this article gave monthly totals for 10M and 200M requests. Those numbers are removed here, because a responsible cost comparison depends on at least: region, average request duration, memory allocated, concurrency pattern, data-transfer, load-balancer and logging costs, and how much of the day the system is idle. Any single total hides those assumptions.

Use this method instead:

Step 1 — Estimate your serverless cost shape

Function cost ≈ (number of invocations × price per invocation)
              + (invocations × average duration × memory allocated × price per GB-second)
              + API/front-door, database, storage, queue and log costs
Enter fullscreen mode Exit fullscreen mode

Step 2 — Estimate your container cost shape

Container cost ≈ (compute that must stay running, 24×7 or your peak window)
               + load balancer + cluster management (if any)
               + storage, database, data-transfer and log costs
               + the engineering time to run the platform   ← do not leave this out
Enter fullscreen mode Exit fullscreen mode

Step 3 — Ask the three questions that actually decide it

  1. What is my idle ratio? If the workload is idle most of the day, paying per use usually wins. If it is busy around the clock, always-on capacity usually wins.
  2. How spiky is it? Sharp, unpredictable spikes favour platforms that scale automatically without pre-provisioned capacity. Flat, predictable load favours containers you can size and discount.
  3. What does operating it cost in people time? A small team's scarcest resource is attention. A theoretically cheaper Kubernetes setup that consumes a day a month of maintenance may be the more expensive option in reality.

Step 4 — Run both numbers for your real workload in your provider's official pricing calculator, with your region and your measured duration/memory, and record the date and assumptions next to the result. Prices change; an undated cost comparison ages badly.

Operations and team skills

  • Functions push you toward many small deployable units and managed services. Deployment is easy; governing dozens of functions, their permissions, and their observability takes discipline.
  • Kubernetes gives you a standard platform for many services, at the price of needing platform skills: upgrades, node management, ingress, certificates, policies, and incident response for the platform itself.
  • Serverless containers sit between the two, which is why they are a sensible default for a small team that wants its own runtime without running a cluster.

Security: shared responsibility, different surface

  • With serverless, the provider patches and isolates the underlying runtime. Your main risks move upward: over-permissive permissions on a function, insecure event inputs, and secrets handling.
  • With containers, you additionally own image hygiene: base-image patching, vulnerability scanning, least-privilege Kubernetes RBAC, network policies, and keeping node/cluster versions current.
  • In both models: give every unit the least permissions it needs, keep secrets in a managed secrets store (never in code or plain environment files committed to a repo), and log enough to investigate an incident.

Portability and lock-in

Be precise about what is portable:

  • A container image is portable. The platform around it — autoscaling config, ingress, identity integration, service mesh, storage classes — often is not fully portable.
  • Function code is often simple; the triggers, event schemas, IAM model, and managed services around it are provider-specific.
  • Lock-in is not automatically bad. Using a provider's managed services is often exactly why a small team can ship. The mistake is taking on lock-in accidentally, without noticing which parts of your system would be hard to move.

The decision framework: 7 questions

Run each workload through these questions in order. The first clear "yes" often settles it.

1. Is it triggered by an event, and does it finish quickly?

Examples: a file is uploaded and needs a thumbnail/resize; a payment webhook arrives; an order event triggers a confirmation email.

→ Yes: serverless functions first. This is the workload functions were designed for.
→ No, it runs continuously: go to question 2.

2. Does it need to run for a long time, hold connections open, or keep state in memory?

Examples: WebSocket servers, streaming consumers, long batch jobs, game servers, anything holding long-lived connections.

→ Yes: containers. Functions are built for short, stateless executions, and provider limits will fight you.
→ No: question 3.

3. Is traffic steady and substantial for most of the day?

→ Yes: containers (or serverless containers with a minimum number of warm instances) — always-on capacity generally suits always-on load, and you avoid paying per request at volume.
→ Traffic is low, spiky, or unpredictable: serverless — paying for idle capacity is the cost you are trying to avoid.

4. Do you need a custom runtime, system libraries, or a GPU?

→ Yes: containers. You control the image, so you control the stack.
→ No strong requirement: either model works; decide on the other questions.

5. How much platform work can your team actually absorb?

Be honest. Count the people, not the job titles.

→ No dedicated platform capacity: serverless or serverless containers. Running Kubernetes well is a real job.
→ You already have (or are deliberately building) platform skills: Kubernetes becomes a reasonable long-term investment.

6. How tight is the latency budget, and can it tolerate an occasional cold start?

→ Strict, consistent latency: containers with warm replicas, or a serverless setup you have measured and tuned yourself.
→ Ordinary API latency targets: either model can work — measure a prototype instead of guessing.

7. How much does portability matter for this specific workload?

→ A genuine multi-cloud / on-premises requirement: containers, with provider-specific services kept at the edges.
→ Single-cloud is an accepted strategy: use the provider's managed services freely and save the engineering time.

Scoring shortcut

Give one point to serverless and one to containers for each question that points that way. A workload that scores heavily one way is an easy call. A workload that scores close to even is your serverless containers candidate — that middle option exists precisely for it.


Workload-by-workload recommendations

Workload Recommended starting point Why
Webhooks and third-party integrations Serverless functions Event-driven, bursty, short
Image / file processing on upload Serverless functions Triggered by storage events, parallel, short
Scheduled jobs and clean-ups Serverless functions (scheduled trigger) Runs briefly, then should cost nothing
New product / MVP API Serverless containers, or functions Low ops, real runtime, room to grow
Steady production API at real volume Containers, or serverless containers with warm instances Predictable cost and latency
WebSockets / real-time / streaming Containers Long-lived connections and in-memory state
Background workers and queue consumers Either — containers for constant load, functions for spiky queues Decide on the queue's shape, not the label
Data pipelines / ETL Either — managed/serverless services for spiky jobs, containers for long heavy jobs Duration and data volume decide
ML / AI inference Containers for model serving you control; managed/serverless endpoints for occasional inference Check current GPU/endpoint options per provider before deciding
Edge logic (redirects, headers, geo routing) Edge functions Latency is about distance to the user
Internal platform for many teams Containers on Kubernetes Standardisation and control are the product

Practical examples

These are illustrative patterns. Test any code in your own account before using it.

Example 1 — Event-driven file processing with a function

Pattern: a user uploads a file to object storage → the upload event triggers a function → the function processes the file → it writes the result back to storage and/or updates a database record.

Why serverless fits: the work only exists when a file arrives, each file is independent (so it parallelises naturally), and you pay nothing between uploads.

Handler sketch (Python-style pseudocode — adapt to your provider's event format):

import json

def handler(event, context):
    # 1. Read the object details from the storage event
    record = event["Records"][0]
    bucket = record["s3"]["bucket"]["name"]
    key = record["s3"]["object"]["key"]

    # 2. Do the smallest useful unit of work
    #    e.g. read the object, create a thumbnail / extract metadata, write the result

    # 3. Return a clear result for logging/retries
    return {"status": "processed", "bucket": bucket, "key": key}
Enter fullscreen mode Exit fullscreen mode

Design notes worth teaching your readers:

  • Make the handler idempotent — events can be delivered more than once.
  • Keep the function small and single-purpose; put shared logic in a library, not in a mega-function.
  • Send failures to a dead-letter queue so a bad file does not disappear silently.

Example 2 — A long-running API in a container

Pattern: a normal web API packaged as a container, deployed to a container platform or Kubernetes, behind a load balancer, with replicas for availability.

Why containers fit: the service is always on, latency should be consistent, and you choose the runtime, framework and system dependencies.

Minimal Dockerfile sketch (adapt the base image and start command to your app):

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

Design notes:

  • Run as a non-root user in the image, and pin your base image version — then update it on a schedule.
  • The app must handle a shutdown signal gracefully, so the platform can replace instances without dropping in-flight requests.
  • Externalise configuration; do not bake environment-specific values or secrets into the image.
  • Add a health/readiness endpoint — every container platform and Kubernetes rely on it for safe rollouts. That is exactly the self-healing behaviour covered in the companion post linked below.

Example 3 — The hybrid most systems end up with

                        ┌──────────────────────────────┐
   Users ──────────────▶│  CDN + Edge functions        │
                        │  (redirects, headers, cache) │
                        └──────────────┬───────────────┘
                                       │
                        ┌──────────────▼───────────────┐
                        │  Core API — containers        │
                        │  (always-on, steady traffic)  │
                        └──────┬───────────────┬───────┘
                               │               │
                  ┌────────────▼───┐   ┌───────▼──────────────┐
                  │ Queue / Event  │   │ Managed database &   │
                  │ bus            │   │ object storage       │
                  └──────┬─────────┘   └──────────────────────┘
                         │
              ┌──────────▼────────────────────────┐
              │ Functions — webhooks, file jobs,  │
              │ notifications, scheduled tasks    │
              └───────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Reading the diagram: containers carry the predictable core; functions carry the irregular edges; managed services carry the state. Most architecture arguments disappear once you assign each workload its own place like this.


Migration paths (you are not locked into your first answer)

From serverless toward containers — common triggers: a workload outgrows execution limits, a service is busy all day and per-request billing stops making sense, or you need runtime control. The practical path is usually: containerise that one service, put it behind the same API/front door, and move traffic gradually. You do not need to migrate the whole system.

From containers toward serverless — common triggers: a platform is oversized for the actual workload, small event-driven jobs are wasting always-on capacity, or the team's maintenance burden is larger than the value it creates. The practical path is: peel off the smallest, most event-shaped jobs first (webhooks, scheduled tasks, file processing).

Either way: move one workload at a time, keep the old path available until the new one has handled real traffic, and compare the actual bill and latency before and after — with dates and assumptions recorded.


Common mistakes to avoid

  1. Choosing for the whole company instead of per workload. This single decision causes most of the pain described in this article.
  2. Comparing only the compute line of the bill. Load balancers, logs, data transfer, and engineering time frequently matter more.
  3. Copying cost or cold-start numbers from articles (including old versions of this one). Measure your own workload; prices and platforms change.
  4. Building a "serverless monolith" — one giant function containing the whole application. You get the constraints of functions and the coupling of a monolith at the same time.
  5. Running Kubernetes because it is the industry default, before you have the traffic, team size, or platform need to justify operating it.
  6. Ignoring observability until the first incident. Distributed systems — functions especially — need structured logs, correlation IDs, and tracing from the first deployment, not after.
  7. Treating lock-in as either irrelevant or fatal. Know which parts of your system are provider-specific, and make that a conscious trade, not a surprise.

Final verdict

Containers give you control, consistent performance, portability of the workload format, and a home for long-running, custom, or hardware-specific work.

Serverless gives you simplicity, automatic scaling, low idle cost, and the smallest possible operations burden.

Serverless containers give a growing number of teams the workable middle: their own container, without the cluster.

The teams that get this right are not the ones that picked the "winning" technology. They are the ones that can answer, for each workload: What triggers it? How long does it run? How steady is its traffic? And who is going to operate it?

Answer those four questions honestly, and the serverless-versus-containers decision mostly makes itself.

My default today is hybrid thinking with a container lean: containers for the main application I need control over, serverless for small event-driven pieces around it.


Related guides

FAQ

Is serverless cheaper than containers?

It depends mainly on how busy the workload is. Serverless is usually cheaper for low, spiky, or unpredictable traffic because you pay little or nothing when it is idle. Containers are usually cheaper for steady, high-volume workloads because you are paying for capacity that is actually being used. Always model your own duration, memory, and traffic pattern in your provider's pricing calculator rather than trusting a generic comparison.

What is a cold start, and should I worry about it?

A cold start is the extra delay when a platform must prepare a fresh execution environment before handling a request. It matters for latency-sensitive, user-facing APIs and much less for background jobs, webhooks, and scheduled tasks. If it might matter for you, measure it with your real code — its size depends on runtime, package size, and configuration.

Can I run containers in a serverless way?

Yes. Services such as Google Cloud Run, AWS Fargate, and Azure Container Apps run your container image, scale it (often to zero), and bill based on use, without you managing a cluster. For many APIs this is the best starting point: your own runtime, low operations, and a straightforward path to Kubernetes later if you outgrow it.

Is Kubernetes the same thing as containers?

No. Containers are the packaging format. Kubernetes is one way to orchestrate containers at scale — scheduling, scaling, networking, and self-healing them across machines. You can run containers productively on much simpler platforms and never operate Kubernetes yourself.

Does serverless mean no DevOps?

No. It removes server and cluster management, but you still own deployment pipelines, permissions, observability, cost control, and incident response. The work changes shape; it does not disappear. If anything, having more, smaller units makes good automation and discipline more important, not less.

Which is better for a startup or a small team?

Start with the lowest-operations option that fits the workload: functions for event-driven pieces, and serverless containers for your main API. Add Kubernetes when you have a specific reason — scale, custom platform needs, or a team that can operate it well — not as a default.

Can I mix serverless and containers in one system?

Yes, and most production systems do. A common pattern is containers for the core, always-on services, functions for events, webhooks and scheduled jobs, and managed services for data and storage. Choose per workload.

How do I avoid vendor lock-in?

Keep the parts that are most likely to move in portable forms (for example, a container image for your main service), use provider-specific services consciously where their convenience is worth it, and document which components would need work to migrate. Complete portability usually costs more engineering time than it saves; informed lock-in is a legitimate strategy.


Top comments (0)