Skip to main content
Back to all posts

Against multi-cloud by default

Multi-cloud is not a strategy, it is a cost. Sometimes a cost worth paying — but never before you can say precisely what you are buying.

2 min readBy Platform Admin

Nearly every team we work with has a line in its architecture document reading "Do we accept vendor lock-in? No." Almost none of them have priced that sentence.

The cost nobody counts

Multi-cloud means you can no longer use any managed service without an exact counterpart on the other provider. Queues, databases, secret management, routing — you run all of it yourself. In practice you have not adopted two clouds. You have built a third one and are now operating it on top of the other two.

We inherited three estates from teams that went down this road. All three had the same shape:

  • The shared infrastructure had collapsed to the lowest common denominator of both providers.
  • Deploying to the second provider was always about to be tested, and never had been.
  • Nobody had documented the abstraction layer the team had written itself.

A standby environment that has never taken real traffic is not a standby. It is a hypothesis.

When it does make sense

There are real cases, and every one of them is a commercial reason rather than an architectural one:

  • A legal requirement to keep data inside a particular jurisdiction.
  • A large customer whose contract requires deployment into their own cloud account.
  • A genuinely independent workload — nightly batch processing, say — that is simply cheaper elsewhere.

Notice that none of these is "in case the provider goes down." A full regional outage at a major provider is, empirically, rarer than the outages you will cause yourself with the extra abstraction layer you wrote to avoid it.

What to do instead

Do not be multi-cloud. Be migration-ready. Declare infrastructure in Terraform, keep state portable, and for every managed service you adopt, write down what replaces it and roughly how long the move would take.

# Not an abstraction — just candour about what is not portable, and why.
resource "aws_sqs_queue" "ingest" {
  name = "ingest"
  # exit-plan: rabbitmq via helm, ~2 weeks, see docs/migrations/sqs.md
}

That takes a few days. Real multi-cloud takes quarters. And if the day ever comes, you will have a current plan rather than a rotting abstraction.