AI workloads make vendor lock-in easier to fall into than most infrastructure decisions, because the fastest path to a working demo usually runs straight through a single provider's managed AI service. That's a reasonable trade for a prototype. It's a much riskier one for a production system a client expects to run for years, especially as pricing, model availability, and regional capacity shift between providers.
Containerize the inference layer from day one
The single highest-leverage decision for portability is packaging model inference behind a container with a stable internal API, rather than calling a provider's proprietary SDK directly from application code. It costs a small amount of extra setup early and buys the ability to swap the underlying compute — a different cloud, a different GPU tier, even a self-hosted option — without touching the application layer. We treat this as non-negotiable for any workload expected to run more than a few months.
Separate the things that are actually provider-specific
Not everything needs to be portable, and treating every layer as equally at risk of lock-in leads to over-engineering. We split infrastructure into three tiers:
- Commodity layers (compute, container orchestration, object storage) — build these to be portable by default; the abstraction cost is low and the switching cost without it is high.
- Differentiated managed services (a provider's specific vector search offering, a proprietary fine-tuning pipeline) — use them deliberately when they offer a real advantage, but isolate them behind an interface so the rest of the system doesn't know which provider is behind it.
- Genuinely irreplaceable capabilities (access to a specific frontier model only available on one platform) — accept the lock-in consciously, as a business decision with a named owner, not a default.
GPU scheduling is a cost problem before it's a performance problem
Idle GPU capacity is one of the most common silent cost leaks we find in client audits. Autoscaling policies built for stateless web traffic don't map well onto GPU workloads, where cold-start time is much higher and the cost of an idle instance is much steeper. Patterns that work well in practice: batching inference requests where latency tolerance allows it, scaling to zero for workloads with predictable idle periods, and separating training or fine-tuning jobs — which can often tolerate spot or preemptible capacity — from real-time inference, which usually can't.
Monitoring costs the same way you monitor uptime
Teams that treat cost as a monthly finance report rather than a live signal consistently discover problems weeks after they started. We wire cost anomaly alerts alongside performance alerts from the start — a sudden spike in inference cost is often the earliest signal of a bug (a retry loop, an oversized batch, a caching layer that silently stopped working) long before it shows up as a user-facing issue.
The real question to ask before committing
Before signing a long-term commitment with any single cloud or AI provider, we ask clients one question: if this provider changed pricing or discontinued this specific service tomorrow, what would it cost us to move, and how long would it take? If nobody on the team can answer that with a real number, that's the gap to close first — before the architecture, not after.