Cloud & DevOps

Deployment Evolutions: Capistrano to Kamal to Kubernetes to Serverless

Four eras of getting code onto a machine, what each one solved, and the honest answer to which of them your team actually needs.

Four ascending platforms showing scripted deploys, containers, clusters and functions

The short version

  • Each generation solved a real problem, and each was then adopted widely by teams who did not have that problem.
  • Kubernetes is excellent at what it does. What it does is orchestrate many services across many machines, which most applications are not.
  • Kamal is a genuine step forward rather than nostalgia: containers and zero-downtime deploys without a control plane.
  • Choose by the constraint you actually have — team size, service count, traffic shape — not by what the largest companies publish.

Deployment tooling has moved through four broad generations in fifteen years. Reading them in order is useful, because each one was a reasonable answer to the failure mode of the one before, and knowing which failure mode you are actually experiencing tells you where you belong.

Era one: scripted deploys over SSH

Capistrano, Fabric, a shell script somebody wrote and nobody wanted to touch. Connect to the servers, pull the new code, install dependencies, run migrations, restart the process, symlink the release directory.

What it solved: repeatability. Before this, deployment was a person following a wiki page and occasionally skipping a step. Scripted deploys made it one command, and the symlinked-release pattern made rollback a matter of pointing at the previous directory.

Where it broke: configuration drift. The deployment was reproducible; the server was not. Servers accumulated manually installed packages, hand-edited configuration files and undocumented state, and over a few years they became irreplaceable in a way nobody noticed until one failed. “It works on staging” was an environment difference nobody could enumerate.

Era two: containers

Docker changed the unit of deployment from “code onto a configured server” to “a complete image containing the code and everything it depends on”.

What it solved: the environment problem, properly. The image includes the runtime, the system libraries and the dependencies, so what runs in production is what ran on your machine. Servers become interchangeable hosts for images rather than pets with histories.

It also made the build artifact real. You build once, you get a hash, and you can point at exactly what is running.

Where it broke: containers gave you a unit and no way to manage a fleet of them. Which host runs which container, what happens when one dies, how traffic reaches them, how to deploy without dropping requests. Everyone wrote their own partial answer, and the answers were bad.

Era three: orchestration

Kubernetes won that argument decisively. Declare the desired state, and a control loop works continuously to make reality match it: scheduling containers across nodes, restarting failures, rolling out updates, managing service discovery and scaling.

What it solved: running many services across many machines reliably, with a single declarative interface and a genuinely excellent extensibility model. At sufficient scale it is not merely useful, it is close to necessary, and the ecosystem around it is deep.

Where it broke: the operational floor is high and does not scale down. You are now responsible for the cluster, ingress, certificates, secrets, storage classes, network policy, resource requests and limits, and a YAML surface large enough to need its own tooling. A managed control plane removes some of that and not most of it.

The uncomfortable observation from the mid-2020s was how many teams running three services on Kubernetes had acquired a full-time infrastructure burden to solve a distribution problem they did not have.

The honest test for Kubernetes. Do you run enough distinct services, across enough machines, changing often enough, that scheduling them by hand would be genuinely painful? If the answer is no, you are paying the operational cost of a solution to a problem you have not got yet.

Era four, in two directions

The most recent movement went two ways at once, which is why it feels contradictory.

Serverless: remove the server entirely

Functions triggered by events, scaling to zero when idle and scaling out automatically under load. The platform owns everything below your code.

It is genuinely excellent for spiky, intermittent and event-driven work, and it brings its own constraints — cold starts, execution limits, database connection pressure and awkward local development. We covered the trade in detail in Serverless Computing: What You Trade Away.

Kamal: containers without the control plane

The other direction, and the more interesting one for most teams. Kamal takes what containers gave us and pairs it with the deployment model of era one: SSH into your own servers, run the container, use a small reverse proxy to switch traffic between the old and new versions for zero-downtime deploys.

No cluster, no control plane, no YAML surface. A configuration file listing your servers and your image, and a command that deploys. Rollback is redeploying the previous image tag.

This is not nostalgia for simpler tooling. It is the recognition that the container was the valuable part of the last decade and the control plane was the price of running thousands of them — a price that makes no sense at three. Rails 8 shipping Kamal as the default deployment path made the argument concrete for a large community, and it is a good argument regardless of framework.

The relevant question was never which tool is most capable. It is which tool’s operational floor is lower than your team’s capacity to maintain it.

Choosing, by the constraint you actually have

  • One application, one or a few servers, a small team. Kamal or an equivalent container-over-SSH tool. You get containers, zero-downtime deploys and rollback, with an operational surface one person can hold in their head.
  • One application, needing managed infrastructure and no ops appetite at all. A platform-as-a-service. You pay a premium per unit of compute and you buy back the entire operational category, which for a small team is frequently the correct trade.
  • Spiky, event-driven or intermittent workloads. Serverless functions, either wholesale or for the spiky parts of an otherwise conventional system.
  • Many services, many teams, real scale. Kubernetes, with people whose job includes it. At this size the alternatives genuinely are worse.
  • Somewhere in between. A managed container service — ECS, Cloud Run, Container Apps — sits usefully between Kamal and Kubernetes, giving you orchestration without owning a control plane.

What stays true across all four

The tooling changed; the properties that make deployment safe did not.

  • Immutable artifacts. Build once, deploy that exact thing everywhere.
  • Configuration outside the artifact. Environment variables or a secrets manager, never baked in.
  • Backward-compatible migrations. Expand, deploy, migrate, contract. Two versions will run concurrently during any rolling deploy.
  • Health checks that mean something. An endpoint returning 200 unconditionally is worse than no health check, because it makes a broken instance look healthy.
  • A rehearsed rollback. Rollback is only real if someone has done it recently and knows how long it takes.
  • Observability first. Logs, metrics and traces from the beginning. Every generation of tooling makes this more necessary, not less.

Boolean Solutions experience with deployment

We run applications across all four models and we have migrated teams in both directions — onto Kubernetes when the service count genuinely justified it, and off it when a two-person team was spending more time on the cluster than on the product.

The advice we would offer is to pick the simplest thing that meets your actual constraint, and to treat moving up a tier as a decision you make when a specific pain appears rather than in advance of it. Complexity added early is rarely removed later. If you are deciding where your application belongs, we are glad to help you think it through, and our DevOps services page describes how we work.

Further reading

Written by

Udit Mittal

Founder at Boolean Solutions. Twenty years of building and rescuing web, mobile and AI products for SaaS companies and startups — and writing down what actually worked.

Get in touch