Moving an application from one LLM provider to another is more than changing an API key. To migrate LLM provider safely you need a clear inventory, tests that validate behavior rather than only surface outputs, and a rollout plan that prevents production regressions. This checklist focuses on the practical steps, contract considerations, and tests engineering teams should run when replacing OpenAI with Anthropic, Google, or any other provider.
1. Define scope and success criteria
Start by deciding what you’re actually switching. Are you replacing only text completions, or also embeddings, streaming, function calling, or fine-tuning? For each capability, define measurable success criteria: latency targets (P95), allowed cost per 1,000 requests, minimum semantic similarity for embeddings, acceptable hallucination rates, and user-facing uptime.
2. Inventory every integration point
Build an API contract matrix so nothing is missed. For each integration, record:
- Endpoint and operation (e.g., chat completion, embeddings, moderation)
- Authentication method and rotation process
- Request and response shapes (including error codes and retry semantics)
- Model parameters your app relies on (temperature, max tokens, top_p)
- Streaming protocol and chunk format
- Rate limits and concurrency expectations
- Data handling and retention requirements
This inventory is the single most useful artifact during a migration: it guides tests, contracts to negotiate, and the adapter work you’ll need.
3. Introduce an adapter layer (don’t swap provider calls everywhere)
Wrap provider-specific calls behind a stable interface. An adapter isolates provider differences and makes rollbacks or multi-provider operation feasible. Keep the interface minimal and focused on your app’s needs.
// Pseudocode: provider adapter interface
interface LLMProvider {
generate(prompt, options): Promise<Response>;
embed(texts): Promise<Embeddings>;
streamGenerate(prompt, options, onChunk): void;
}
// At runtime choose adapter by config
const provider = config.provider === 'anthropic' ? new AnthropicAdapter() : new OpenAIAdapter();4. Translate contract differences (practical checklist)
- Parameter mapping: map temperature/top_p/token limits and verify semantics align.
- Tokenization differences: test token counts for identical inputs to adjust max_tokens and cost estimates.
- Streaming behavior: confirm chunk boundaries, finalization events, and reconnection behavior.
- Embeddings: compare vector dimensions and similarity baselines; you may need to reindex or re-compute thresholds.
- Error handling: map provider-specific error codes to your retry policy so you don’t over-retry or silently drop traffic.
5. Build a targeted test suite
Tests should validate the behaviour your product depends on—not just identical text. Create three tiers:
- Unit tests for adapter edge cases (auth failure, timeouts, malformed responses).
- Golden regression tests: store representative prompts and expected properties of responses (e.g., contains entities, returns JSON that validates against schema). Don’t assert exact tokens when models legitimately vary.
- Behavioral tests: measure hallucination rate, safety filters, and semantic correctness across a representative corpus. Use automated acceptance tests that score outputs against ground truth or heuristics.
6. Shadowing and offline comparison before sending production traffic
Before routing traffic to a new provider, run shadow requests in production: send the same input to both providers but only use the incumbent’s response in production. Capture both responses for automated comparison. This reveals differences in latency, token usage, output format, and content quality under real load.
7. Performance, load testing, and cost modeling
Run realistic load tests that mirror your production concurrency and payload sizes. Measure:
- P95 and P99 latency under expected concurrency
- Token consumption per transaction
- Time to first byte for streaming endpoints
- Failure modes under backpressure (timeouts, rate-limit responses)
Use these numbers to estimate operational cost. Different providers bill and throttle differently; capture cost per typical request and worst-case cost during retries.
8. Prompt and instruction tuning
Different models respond to prompts differently. Treat prompt text and templates as versioned configuration: keep them in a repo, run automated evaluations when you change prompts, and maintain a prompt-performance baseline for each provider. For structured outputs (JSON, function calls), use strict schema validation and add fallback handlers when the model returns malformed content.
9. Special integrations: embeddings, function calling, and streaming
Each capability has its own migration considerations:
- Embeddings: Compare vector norms and cosine similarity distributions on a sample corpus. If dimensions differ, plan reindexing or dual-indexing strategies and recalibrate similarity thresholds used by your RAG/retrieval logic.
- Function calling / tools: Confirm how the new provider handles tool invocation, schemas, and partial failures. Test that your orchestration still recognizes and handles tool return values safely.
- Streaming: Validate reconnection semantics, chunk ordering, and how partial results are delivered to clients (use real clients where possible).
10. Privacy, compliance, and contract items to confirm
Before cutting over, review and obtain written confirmation for:
- Data usage and retention policies—ensure prompts and responses will not be used for model training without consent.
- SLA terms for uptime and escalation processes.
- Security controls (IP allow-listing, VPC/Private Networking options) if required.
- Auditability: access to logs or request metadata for incident investigation.
- Intellectual property terms relevant to your generated content.
Don’t assume identical policies across vendors—get explicit, written terms when compliance matters.
11. Deployment and rollout strategy
Use a staged rollout to limit risk:
- Internal alpha: route to dev/test accounts only and validate end-to-end workflows.
- Canary: send a small percentage of live users or requests to the new provider with a feature flag controlling exposure.
- Gradual ramp: increase traffic while monitoring quality and system metrics.
- Full cutover: only after meeting the agreed success criteria and a cooling-off period with no regressions.
Consider a permanent multi-provider strategy where traffic is split by use case: for example, cheaper models for low-risk tasks and a higher-quality provider for critical user flows.
12. Observability and alerting
Instrument both functional and quality signals:
- API-level metrics: error rate, latency (P50/P95/P99), token usage, and retries.
- Quality metrics: schema validation failures, hallucination or misinformation detections, and user-facing error reports.
- Business metrics: conversion, completion rates, and support tickets correlated to provider changes.
Integrate prompt and response telemetry into your logging pipeline, but redact sensitive content before it leaves your system. If you haven’t already, review observability practices tailored to LLM apps so you can detect behavioral drift quickly.
13. Rollback plan and safety nets
Design fast rollback capabilities before you start the rollout:
- Feature-flag and config-based provider selection to flip traffic immediately.
- Automated health checks that revert traffic when thresholds are breached.
- Retention of both providers’ logs for at least the period necessary to investigate issues after rollback.
14. Post-migration validation checklist
- All adapter tests pass and shadowing comparisons show acceptable differences.
- Performance and cost are within the defined targets.
- Embeddings and retrieval quality meet semantic thresholds; indexes are updated if needed.
- Streaming and function-calling behavior match client expectations.
- Security, privacy, and contractual requirements are confirmed in writing.
- Alerts and dashboards are in place and monitored for at least one full business cycle.
Compact migration checklist
- Create an API contract matrix and inventory all LLM interactions.
- Implement an adapter layer to isolate provider specifics.
- Write unit, golden, and behavioral tests for prompts and outputs.
- Shadow production traffic and compare outputs offline.
- Load test for latency, throughput, and cost modeling.
- Version prompts and validate structured outputs with schemas.
- Verify embeddings, streaming, and any fine-tuning/tool integrations.
- Confirm privacy, data-use, and SLA terms in writing.
- Roll out gradually with feature flags and canaries; keep rollback ready.
- Monitor quality and business metrics post-cutover.
Takeaway: A safe migration is a sequence of small, testable steps. Treat provider differences as contractual risks to be measured and monitored, not guesses to be fixed after users notice a regression.
Frequently Asked Questions
How should I test prompts when I replace OpenAI with Anthropic?
Run a mix of golden tests and behavioral tests. Don't assert exact tokens—validate structured output with schemas, check for required entities, and score semantic similarity against ground truth. Use shadowing to collect real-world comparisons before cutover.
Can I run two providers in production during migration?
Yes—use shadowing (send the same request to both but only return the incumbent’s response) or traffic-splitting with feature flags. Shadowing is safest for evaluating differences without exposing users to regressions.
What are common pitfalls when switching LLM APIs?
Common issues are tokenization differences affecting cost and max_tokens, mismatched streaming semantics, embedding-dimension changes, insufficient tests for structured outputs, and assuming identical data-use policies without written confirmation.
How do I handle embedding differences between providers?
Compare vector dimensions and similarity distributions on a representative dataset. If dimensions differ, plan to reindex or maintain separate indexes and recalibrate similarity thresholds used by your retrieval layer.