Multi-cloud vs. actually portable: they're not the same thing

"We're multi-cloud" is one of the most overloaded claims in infrastructure. In practice it usually means one of three very different things, and only one of them is actually multi-cloud.

The three claims of multi-cloud: theoretical portability, accidental multi-cloud, and actually portable by design

Claim one: "we could move if we had to"

This usually means the team picked boring, portable primitives - containers instead of a proprietary compute service, a standard SQL engine instead of a fully managed one with a unique API. Nobody has actually tested moving anything. The portability is theoretical until a migration forces the question, and that's usually the worst possible time to find out the theory was wrong.

The difference is usually visible right in the manifest. One of these is portable by construction. The other only runs where it was written.

# Portable primitive - runs on any Kubernetes cluster, any cloud
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inference-api
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: inference-api
          image: registry.internal/inference-api:1.4.2
          resources:
            requests: { cpu: "2", memory: "4Gi" }

---

# Proprietary primitive - runs on exactly one cloud, one way
Resources:
  InferenceFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: provided.al2
      Handler: bootstrap
      Role: !GetAtt InferenceExecutionRole.Arn
      Environment:
        Variables:
          MODEL_BUCKET: !Ref ModelArtifactBucket

The Deployment moves to any cluster on any cloud unchanged. The Lambda function doesn't move at all - it gets rewritten, every time, for wherever it's going next.

Claim two: "we run a few things on a second cloud"

This is genuine multi-cloud in the narrow sense - workloads exist on more than one provider - but it's often accidental rather than architected. A team spins up a second cloud account for one project, for one client requirement, or because a service the primary cloud doesn't offer well exists on the other. The two environments don't share tooling, secrets management, or observability. Operating both costs more than operating one, and the "multi-cloud" framing oversells the coordination between them.

Claim three: "the same platform runs on either, on purpose"

This is the version that's actually valuable, and it's rarer than the marketing suggests. It means the application and platform layer - service mesh, secrets, event backbone, observability - are built on Kubernetes-native components rather than cloud-managed services, so the same Helm releases deploy unchanged to any provider. Moving isn't a rewrite; it's a new set of Terraform variables and a new cluster.

Accidental multi-cloud versus architected multi-cloud: two disconnected environments with no shared tooling, compared to one platform running on two clouds by design

The test that actually matters

Ask this question honestly: if you had to stand up a full copy of production on a different cloud next month, would that be a configuration change or a project? If it's a project, you're not multi-cloud in any way that protects you - you're single-cloud with a migration you haven't done yet.

The test that actually matters: could you stand up a full copy of production on a different cloud next month, as a configuration change or as a project

Getting to "configuration change" isn't about avoiding managed services altogether. It's about being deliberate over which capabilities you own versus rent, and building the ones you own on the cluster rather than the cloud. That's the difference between a slide with "multi-cloud" on it and infrastructure that actually is.