# Why multi‑cloud fails in practice
Teams usually start multi‑cloud projects focused on connectivity and architecture diagrams. Practical work quickly exposes a different reality: providers make different design choices about how services behave. Examples include whether deleting a nonexistent object returns success or a 404 error, how pagination tokens are presented, and how retries or timeouts operate. These are semantic differences that ripple into application logic and test suites.
# Why REST‑first abstractions fall short
Past efforts tried to standardize on REST as the common layer. In practice, providers evolve APIs, authentication, and performance behavior continuously. A REST abstraction lags unless it constantly chases provider changes. Official provider SDKs already absorb vendor changes and solve low‑level concerns like signing, endpoint discovery, header handling, and retries. Building your abstraction on top of vendor SDKs lets you rely on that maintenance work and focus on normalization instead of reimplementing plumbing.
# A practical layered architecture
- Portable client layer: stable, cloud‑neutral APIs used by application teams.
- Driver layer: validation, coordination, and orchestration across calls.
- Provider implementations: translate provider responses into the normalized model used by the driver and client.
Provider implementations are responsible for mapping status codes, unifying pagination patterns, and standardizing error shapes. Applications interact only with the top layer, which keeps provider complexity hidden.
# How to decide what to abstract
Treat roughly 90% of services as commodities: compute, object storage, and pub/sub messaging tend to be consistent enough that abstraction helps reduce duplication and technical debt. The remaining 10% are differentiators: if a provider offers a feature that materially reduces cost or delivers a competitive capability, integrate natively for that use case rather than forcing it through the abstraction. Portability should enable deliberate choices, not be the default goal.
# Testing and CI considerations
Conformance testing is essential. Write test suites against your abstract driver interfaces and run the same tests against each provider implementation. This makes behavioral deviations visible early. Running these tests in CI introduces the practical problem of managing live provider credentials and the associated security risks. The article mentions this operational concern as a common challenge when validating implementations across clouds.
# Tradeoffs and engineering costs
free. The main benefits are reduced duplication, fewer provider‑specific code paths in application logic, and faster adoption of provider SDK improvements. The main costs are the initial development of the driver and provider layers, and maintaining conformance tests and providers as clouds evolve. Using SDKs minimizes manual upkeep because vendor updates propagate through the SDKs instead of requiring constant changes to a custom REST layer.
# Bottom line