Cloud & platform

Multi-cloud Terraform: what to abstract, and what to leave alone

The tempting design is one module that deploys a database on any cloud. It almost never ends well. Here is the composition approach I use instead, across AWS, Azure and GCP.

ComparisonSumanta Mukhopadhyay7 min read4 sources
#platform#cloud#terraform#governance
COMPARISON · CLOUD & PLATFORM19 Oct 2026 · 12:30 GST

I have written a lot of Terraform across AWS, Azure and GCP, including an open-source Python helper for generating it across all three. The most expensive lesson in that work is about abstraction. The instinct is to write one "database" module that works on any cloud. It is almost always a mistake.

Why the universal module fails

Managed services differ in ways that matter: networking models, identity, backup semantics, failover, pricing. A module that hides all of that has two options. It exposes only what every cloud supports, so you lose the features you're paying for. Or it grows a flag for every provider difference, until it is harder to use than the raw resources.

HashiCorp's own documentation makes the point that Terraform deliberately doesn't abstract over vendors, and suggests building lightweight multi-cloud abstractions through composition instead1.

Composition instead

The composition pattern keeps modules small and lets a root module wire them together. Child modules receive what they depend on, such as network and subnet IDs, as inputs rather than creating them, so the same blocks can be assembled differently per environment1. Real configurations should almost always be built from modules like this2.

LayerAbstract it?Why
Naming, tagging, labelsYes, fullySame rules everywhere; drives cost allocation and ownership
Policy: encryption, logging, regionsYes, as shared inputs and checksCompliance should not depend on which cloud a team picked
Kubernetes clustersPartly: shared interface, provider modules underneathWorkloads target Kubernetes, not the cloud
NetworkingNo, provider-specificModels differ too much to hide safely
Managed databases and AI servicesNo, provider-specificTheir differences are the reason to use them

Abstract the things that should be the same everywhere: names, tags, policy, and the contract your applications see. Leave the cloud-specific parts cloud-specific.

The shape I use

  1. A conventions module that only computes names and tags from a few inputs. Every other module consumes it.
  2. Provider-specific building blocks for network, cluster, database and secrets, each small and documented.
  3. Thin "product" root modules per environment that compose the blocks and nothing else.
  4. Policy checks in CI that fail a plan which, for example, creates an unencrypted bucket or deploys outside approved regions. This matters for data residency, which I discuss in UAE PDPL and AI.
  5. Kubernetes as the portability layer. If applications need to move between clouds, make them depend on Kubernetes interfaces, not on cloud APIs. Cost controls such as scale-to-zero then work the same everywhere, as in my Kubernetes FinOps playbook.

Terraform or OpenTofu?

In August 2023 HashiCorp moved Terraform from the Mozilla Public License to the Business Source License. The community fork, OpenTofu, was accepted by the Linux Foundation that September and remains MPL-licensed34.

For most companies using Terraform internally, either works. The decision usually comes down to licence policy, whether you build a product that competes with HashiCorp, and which newer features each tool offers. My practical advice is to keep modules free of features specific to one tool unless you need them, so switching later stays cheap. I'd record the choice in an architecture decision record either way.

Signs your IaC needs work

  • Changes are made in the console "just this once" and never reach code.
  • Each environment has its own copy of the configuration instead of composing shared modules.
  • Nobody can say which team owns a resource, because tags are inconsistent.
  • A plan for a small change touches hundreds of resources.

These show up in almost every technical due diligence, and they predict how expensive the next year of operations will be.

How I can help

I design infrastructure-as-code foundations across AWS, Azure and GCP that teams can actually maintain. As a fractional CTO I can also own the platform roadmap. Or analyse your challenge and bring the result to a call.

References
  1. 1
    Module compositionHashiCorp Developer
  2. 2
    Modules overviewHashiCorp Developer
  3. 3
  4. 4
FAQ

Common questions

Should I write one Terraform module that works on every cloud?

Usually not. Terraform deliberately doesn't abstract over providers, and a lowest-common-denominator module hides the features that make each service worth using. Compose small provider-specific modules behind a shared interface instead.

What is module composition in Terraform?

It is a style where a root module assembles small building-block modules and passes dependencies between them as inputs and outputs, rather than each module creating everything it needs. HashiCorp's documentation recommends it.

Should I use Terraform or OpenTofu?

Both remain viable. OpenTofu is an MPL-licensed fork under the Linux Foundation, created after HashiCorp moved Terraform to the Business Source License in 2023. Choose based on licensing needs, ecosystem and the features you rely on.

Keep reading

Related

Open to advisory, fractional CTO & select builds

Let's talk about what you're building.

The fastest route is a free 30-minute call. Prefer to write? Send a message and I'll reply personally within two business days.

Start a conversation

How would you like to reach me?

Book a 30-min callFastest. Pick any open slot on my calendar.→ Write in GmailOpens a pre-filled draft in your browser.→ Use my email appOutlook, Apple Mail or your default client.→

I reply personally within two business days. US & UAE time zones.