Multi-cloud guide

Why cloud abstraction layers rarely deliver portability

An abstraction layer moves the work rather than removing it. Kubernetes makes your application portable and leaves the surrounding platform provider-specific. Terraform makes your workflow portable and leaves the resource definitions provider-specific. An in-house wrapper over both makes the differences invisible to developers by making them somebody's full-time job. None of these is a mistake, but each is commonly bought under a description of what it does not do.

Does Kubernetes make workloads portable?

It makes the application portable and stops at the boundary of the cluster. A container, a deployment manifest and a service definition will run on any conformant cluster, and that is a genuine and useful property. What does not travel is everything the cluster touches: how a load balancer is provisioned, how storage classes map to underlying disks, how pods obtain credentials for cloud services, how nodes scale, how the registry authenticates, and how ingress is terminated.

Those differences are not cosmetic. On one provider a service of type LoadBalancer produces a network load balancer with one set of annotations; on another the annotations, the health check semantics and the timeout defaults differ. Pod-level identity is implemented differently on each platform, which means the mechanism by which your application gets a database credential is one of the least portable parts of the system. Storage is worse, because volume snapshot and resize behaviour vary and stateful workloads depend on the details.

The practical consequence is that a Kubernetes estate is perhaps eighty percent portable at the manifest level and much less than that in operations. The remaining portion is where the incidents are, and it is exactly the part a team has to learn again on the second provider. Kubernetes is worth using for many reasons. Treating it as a completed multi-cloud strategy is the error.

What does Terraform actually give you?

One workflow, one state model and one review process across providers. That is valuable and it is not portability. A Terraform configuration for a virtual network on one provider shares no resource types, no arguments and no structure with the equivalent on another, because each provider's resources are modelled separately. Moving a stack between clouds means rewriting the configuration, not changing a variable.

The value is real in a different place. Having every environment defined in code, reviewed, and reproducible is the single largest determinant of how quickly you could stand up anywhere else, because the alternative is discovering that production contains years of console-made changes nobody recorded. Teams that keep this discipline can rebuild an environment; teams that do not cannot, regardless of how many providers they use.

Modules are where expectations go wrong most often. An internal module that presents a uniform interface across providers has to model the intersection of their capabilities, and that intersection is smaller and less stable than it appears. The usual outcome is a module with provider-specific escape hatches, at which point the abstraction is documentation with extra indirection.

What stays provider-specific whatever you use?

Identity, networking, cost structure and the operational surface. These are the four layers no tool abstracts convincingly, and they are also the four that consume most platform engineering time, which is why abstraction saves less than the diagram suggests.

LayerPortable with tooling?What actually differs
Application containerYesBase image and registry authentication only
Orchestration manifestsMostlyLoad balancer annotations, storage classes, ingress
Workload identityNoHow a pod or function obtains a credential at all
Permission modelNoPolicy evaluation, deny semantics, boundary concepts
NetworkingNoAddress planning, DNS resolution, peering, egress paths
Observability and billingPartlyEvent schemas, metric names, cost allocation granularity

What happens when you build your own abstraction?

It becomes an internal product, and internal products need owners, roadmaps, documentation, support and a deprecation policy. Teams rarely plan for this. The wrapper is written during a project, it works, and then a provider ships a feature that the abstraction cannot express, a developer needs it, and an escape hatch appears. After a few of those the abstraction constrains without protecting.

There is a second failure that is harder to see. Because the layer must work everywhere, it can only expose what every target supports, so the platform your developers experience is the intersection of the providers rather than the best of them. That cost is paid continuously by every team building on it, and it is invisible because nobody compares the internal platform to what they could have used directly.

The third failure is staffing. The abstraction has to keep pace with several providers' release cycles, and the people who understand it become the constraint on every project. When they leave, the layer is a system nobody wants to own, sitting between every application and the infrastructure. This is the most common way multi-cloud programmes leave permanent damage even after the multi-cloud goal is abandoned.

When is an abstraction layer the right call?

When you ship software into other people's clouds. A vendor whose customers require installation into their own AWS, Azure or Google accounts genuinely needs one packaging and deployment model across all three, and the abstraction is part of the product rather than overhead on top of it. The cost is justified because it is amortised over customers, not absorbed by one platform team.

It is also reasonable when the abstraction is deliberately narrow and covers a single concern. A thin internal interface for object storage, or for publishing a message, is a small piece of code with an obvious boundary, and swapping the implementation is a contained change. What fails is the general-purpose platform that abstracts everything, because the surface never stops growing.

The third legitimate case is regulatory repeatability, where an organisation must demonstrate that a service can be stood up in another environment on a defined timeline. Even then, the cheaper route is usually a rehearsed and documented rebuild rather than a permanent layer, because the requirement is evidence of capability rather than continuous readiness.

What should you do instead?

Contain the provider-specific parts rather than hiding them. Put the calls that touch a provider behind interfaces your own code defines, keep a written list of where those interfaces exist, and accept the platform's native tools everywhere else. This gives you the same replaceability that an abstraction promises, without a layer between every team and the infrastructure.

Then apply a test before adding any general-purpose layer. Ask what the layer would have to expose for the three most demanding workloads you run, and whether it can express the provider features those workloads actually depend on. If the answer requires an escape hatch on day one, the abstraction will not survive contact with your roadmap, and building it anyway converts a portability goal into technical debt.

A useful afternoon exercise: pick one running service and list every provider-specific dependency it has, including how it authenticates, where its secrets come from, how it is routed to, where its logs land and how its data is backed up. The list is nearly always longer than the team expected and it is almost never the application code. That list, kept current, is worth more than any wrapper you could write against it.

Common questions

Does Kubernetes make applications cloud portable?
It makes the application portable and stops at the cluster boundary. Containers and manifests run anywhere conformant, but load balancer provisioning, storage class behaviour, pod identity, node autoscaling, registry authentication and ingress termination differ by provider. Those differences are where operational incidents happen, so a Kubernetes estate is far more portable on paper than in practice and cannot be treated as a finished multi-cloud strategy.
Does Terraform make infrastructure portable between clouds?
No. It gives one workflow, one state model and one review process, while resource definitions remain entirely provider-specific: different resource types, different arguments, different structure. Moving a stack means rewriting it. The genuine value is that everything is defined in code and reproducible, which is the largest single factor in how quickly an organisation could stand up elsewhere, but that is repeatability rather than portability.
Should we build an internal cloud abstraction layer?
Only if you ship software into customers' own cloud accounts, where the abstraction is part of the product and amortised across customers, or if it is narrow enough to cover a single concern such as object storage. General-purpose internal platforms over multiple providers become products with roadmaps, bugs and maintainers, expose only the intersection of what all targets support, and become the constraint on every project once their authors move on.
What cannot be abstracted across cloud providers?
Identity, networking, cost structure and the operational surface. How a workload obtains a credential differs fundamentally between platforms, permission evaluation and deny semantics differ, address planning and DNS resolution differ, and audit and billing data arrive with different schemas and granularity. These four consume most platform engineering time, which is why abstraction saves less effort than an architecture diagram implies.
What is the alternative to a cloud abstraction layer?
Containment rather than concealment. Put provider-specific calls behind interfaces defined by your own code, keep a maintained list of where those interfaces are, and use native tooling everywhere else. Before adding any general layer, check whether it could express the provider features your three most demanding workloads depend on. If an escape hatch is needed immediately, the layer will not survive the roadmap.

More on Multi-cloud solutions

Let’s create something out of this world together.

Have a project in mind? Contact us for expert design and development solutions. Let’s discuss how we can help grow your business.

Azaadi Offer

Claim a free security assessment

Until 31 August we're covering the cost of a full vulnerability assessment and penetration test. Mention it in your message and we'll scope it with you.

  • Web application testing, authenticated and unauthenticated
  • Mobile application testing across iOS and Android
  • External network and infrastructure assessment
  • Manual exploitation by engineers, not scanner output

Testing and the report are free. Fixing what we find is quoted separately, with no obligation to accept.

Read the full offer

Tell us what you are trying to build and we will tell you plainly whether we are the right people for it. Book a call with an expert to work through the detail, or ask for a fixed quote if the scope is already clear. No obligation either way.

Four fields is all we need to get started.

Fastnexa Logo

© 2026 fastnexa. All rights reserved.