PL · PolskiFree intro call

DevOps and infrastructureAnalysis

When Docker Swarm still makes sense, and when it starts costing too much

Choosing an orchestrator is rarely about the technology. It comes down to how many people can fix it in the middle of the night, and how much your traffic fluctuates. This piece is my list of criteria, not a ranking of tools.

Who it’s forFor developers and tech leads on teams of up to a dozen or so people who run their own infrastructure and are wondering whether it’s “time for Kubernetes yet.”

Every few months, someone asks me why we don’t move everything to Kubernetes. It’s a fair question. The answer: for now, it wouldn’t pay off. Below I explain how I reach that conclusion and what would have to change for me to change my mind.

Where I start: who’s going to run it

The first question isn’t about the tool. It’s about people. How many people on the team understand the infrastructure well enough to diagnose an outage on their own? If the answer is “one, maybe two,” then every layer of abstraction I add is debt taken out in their name.

Swarm is built into Docker Engine. If you know docker compose, you’ll understand docker stack deploy in an afternoon. Kubernetes gives you much more, but it also demands much more: its own object model, its own tooling, its own way of thinking about networking and configuration.

Where Swarm works well

In my experience, Swarm is a sensible choice when three conditions are met:

  • Traffic is predictable. You know roughly how many replicas each service needs, and you don’t have to add more automatically every few minutes.
  • You run a handful of services, or a dozen or so, not hundreds. You can still read the stack file from top to bottom.
  • The team is small and prefers simplicity over full control.

In that setup, you get what you actually need: rolling updates with automatic rollback, secrets, overlay networks, health checks and simple label-based routing through Traefik.

services:
  api:
    image: registry.example.com/api:1.42.0
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
        failure_action: rollback
      restart_policy:
        condition: on-failure
      labels:
        - traefik.enable=true
        - traefik.http.routers.api.rule=Host(`api.example.com`)
        - traefik.http.services.api.loadbalancer.server.port=8080
    healthcheck:
      test: ['CMD', 'wget', '-qO-', 'http://localhost:8080/health']
      interval: 10s
      timeout: 3s
      retries: 3
    secrets:
      - db_password

secrets:
  db_password:
    external: true

Two lines matter most here: order: start-first and failure_action: rollback. The new replica starts before the old one is stopped, and if the health check fails, Swarm rolls back to the previous version on its own. For most web applications, that’s enough to turn deploys into a non-event.

Where it starts to hurt

Swarm has its limits, and it’s worth knowing them before you hit them.

No autoscaling. There’s no equivalent of the Horizontal Pod Autoscaler. You can work around it with a script that reads metrics and changes the replica count, but then you’re maintaining your own autoscaler.

A smaller ecosystem. Many tools today are built with Kubernetes in mind: database operators, ready-made Helm charts, integrations with observability systems. With Swarm, you end up assembling things yourself more often.

Stateful services. You can run databases in Swarm, but it takes discipline: pinning them to specific nodes, well-planned volumes and backups. I usually keep them outside the cluster.

Criterion Docker Swarm Kubernetes
Barrier to entry Low, if you know Compose High, a whole new set of concepts
Autoscaling None built in Built in (HPA, VPA)
Tooling ecosystem Modest Very large
Maintenance cost in a small team Low High
Flexibility as you grow Limited Very high

How I record a decision like this

I record every decision of this kind in one place, together with the conditions under which it stops applying. That way, a year from now we don’t argue from scratch. We just check whether the conditions have changed.

Decision
We’re staying on Docker Swarm for the next 12 months.
Why
A small team, predictable traffic, a dozen or so services. Swarm covers our needs, and everyone on the team understands how it works.
Costs
No autoscaling and fewer ready-made tools. Some things (e.g., backups of stateful services) we put together ourselves.
Revisit when
we need per-service autoscaling, we expand into multiple regions, or the number of services no longer fits in a single stack file.

What this means

I’m not saying Swarm is better than Kubernetes. I’m saying that for many small teams it’s good enough, and the difference in maintenance cost is bigger than feature comparisons suggest.

If you’re weighing the same choice, start with three questions: who’s going to fix it, how much does your traffic fluctuate, and how many services will you have a year from now? The answers usually settle it faster than a feature table.

Sources and documentation

  1. Docker Docs: Swarm mode overviewdocs.docker.com
  2. Docker Docs: Deploy a stack to a swarmdocs.docker.com
  3. Traefik Docs: Swarm providerdoc.traefik.io

About the author

Jacek Sultan

CTO at Dock, programmer and entrepreneur. I write about technology decisions and offer 1:1 mentoring.

More about me