Vendor Lock-In
also known as Single-Provider Coupling, Hard-Coded Provider SDK, Provider-Specific Application Code
Anti-pattern: couple application code directly to one model provider's SDK, request shape, and proprietary features so that switching providers requires rewriting application code rather than swapping an adapter.
Context
A team is building an LLM application or agent framework directly against a single provider's SDK — calling its specific request shape, depending on its proprietary streaming chunks, using its particular tool-call format. There is no abstraction layer between the application code and the vendor SDK, because the team has no immediate plan to support a second provider and the SDK exposes useful features that would be diluted by a lowest-common-denominator interface.
Problem
Every provider has its own request schema, its own streaming semantics, its own tool-call shape, and its own rate-limit headers. Application code that has been written directly against one provider cannot be redirected to another without invasive changes through the whole codebase, because the vendor's shape has leaked everywhere. Once that coupling exists, the team can no longer evaluate routing requests to a cheaper or stronger competitor for the same task, cannot fall back to another provider during an outage, and cannot move workloads for compliance reasons. Switching providers is a normal lifecycle event, not a hypothetical one, and vendor lock-in turns it into a rewrite.
Forces
- Provider SDKs are richer than the lowest common denominator and expose useful proprietary features.
- An abstraction layer adds maintenance cost and may lag behind upstream features.
- Per-provider quirks (streaming chunks, tool-call shapes, rate-limit headers) are non-trivial to unify.
- Switching providers for quality, cost, or compliance reasons is a normal lifecycle event, not a hypothetical.
Example
A startup builds its agent product against one provider's SDK, threading provider-specific objects through the agent loop and reading provider-specific error fields in retry logic. Two years later, the provider doubles per-token price and tightens rate limits; the team wants to fall back to a competitor for cheap traffic and keep the incumbent for hard tasks. The migration takes three months because tool-call shapes, streaming chunk formats, and error semantics are all wired into application code. They rebuild against a provider-agnostic adapter and a `provider/model` string router; the next vendor evaluation is a config change.
Diagram
Solution
Therefore:
Don't couple application code to one provider's surface. Use a provider-agnostic abstraction (Vercel AI SDK's language model spec, LiteLLM, Mastra's `provider/model` string, OpenAI-API-compatible adapters) and keep provider-specific extensions behind capability flags. Where a feature only exists on one provider, isolate it in a feature module rather than threading it through the agent loop. See provider-string-routing, provider-fallback, multi-model-routing.
What this pattern forbids. By definition, this anti-pattern imposes no useful constraint; the missing constraint — application code must not depend on provider-specific surface — is the failure mode.
And the patterns that stand alongside it, or against it —
- alternative-toProvider-String Routing★— Select the model and provider for a request through a single namespaced string (`provider/model`) backed by env-var credentials, so the caller specifies what to run with one parameter rather than a typed provider object.
- alternative-toProvider Fallback★★— When one provider's API errors mid-stream, transparently switch to another provider while preserving state.
- alternative-toMulti-Model Routing★★— Send each request to the cheapest model that can handle it well.
- complementsSovereign Inference Stack★— Run the entire agent stack (model weights, inference, tool layer, vector stores, logs) inside a jurisdictional and operational boundary the operator controls, so no request, prompt, or output crosses into a third-party API.
- alternative-toMCP Bidirectional Bridge★— Run a framework as both MCP client (consuming external MCP servers as tools) and MCP server (publishing its own agents, tools, and workflows back over MCP) so capabilities flow both directions across the protocol boundary.
Neighbourhood
Click any neighbour to follow the language. Scroll to zoom, drag to pan.