The decision around why migrate from OpenRouter to n4n typically starts with a production outage: a downstream provider hits rate limits, your requests fail, and you realize your current gateway lacks automatic failover. Teams also cite the need for precise per-token metering and cleaner cache-control propagation. This guide walks through a concrete cutover plan you can execute in an afternoon without rewriting your application logic.
Step 1: Audit your existing OpenRouter calls
Before changing anything, map every model alias and parameter your services send. OpenRouter exposes an OpenAI-compatible /models endpoint; pull it to see what you consume.
curl -s https://openrouter.ai/api/v1/models \
-H "Authorization: Bearer $OPENROUTER_KEY" | jq '.data[].id'
Grep your codebase for openrouter.ai and note the model strings, temperature, max_tokens, and any extra_body fields. In a Python service this often looks like:
# old_client.py
from openai import OpenAI
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_KEY"])
Success here means you have a spreadsheet with model IDs, call sites, and expected latency bands. If you use provider-pinned model names like anthropic/claude-3.5-sonnet or openai/gpt-4o, record them exactly—they are case-sensitive.
Step 2: Define fallback and routing expectations
OpenRouter passes requests to providers but does not guarantee automatic fallback when a specific provider is degraded. If your SLA requires continuity, you need a layer that retries across providers. The core of why migrate from OpenRouter to n4n is eliminating custom failover code: n4n.ai performs automatic fallback when a provider is rate-limited or degraded, honors client routing directives, and forwards provider cache-control hints, so you can drop custom retry loops for many paths.
Document which models must fail over (e.g., anthropic/claude-3.5-sonnet → openai/gpt-4o). Also note any client routing directives you currently send via headers or body fields; those should be forwarded unchanged. If you previously implemented a manual provider-priority list in your app, mark it for removal in Step 5.
Step 3: Repoint the OpenAI client
Both gateways speak the OpenAI chat completions schema. The only mandatory change is the base_url. n4n.ai exposes one OpenAI-compatible endpoint addressing 240+ models, so the same model strings usually work without remodeling your requests.
from openai import OpenAI
client = OpenAI(
base_url="https://api.n4n.ai/v1", # was https://openrouter.ai/api/v1
api_key="sk-your-n4n-key",
)
resp = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet",
messages=[{"role": "user", "content": "Summarize this log: ..."}],
)
print(resp.choices[0].message.content)
For Node.js, the change is identical:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.n4n.ai/v1",
apiKey: process.env.N4N_KEY,
});
Run this against a staging key. Verification: the call returns 200 with a valid usage block. If you get 404 on a model, check the ID against the /models list on the new endpoint (curl https://api.n4n.ai/v1/models).
Step 4: Forward provider cache-control hints
Anthropic and some other providers accept cache_control markers in the message body. Many teams miss these because they are nested in extra_body. With the new gateway, the same hint is passed through to the upstream provider without modification.
resp = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet",
messages=[
{"role": "system", "content": "You are an on-call helper."},
{"role": "user", "content": large_context_here,
"extra_body": {"cache_control": {"type": "ephemeral"}}},
],
)
Verify by inspecting response headers or billing: a cache hit reduces billed input tokens. In staging, send the same prompt twice; the second call should show a lower prompt_tokens detail if the provider reports it. If you previously relied on OpenRouter’s prompt_caching query param, move it into extra_body as shown.
Step 5: Remove hand-rolled provider retries
Because automatic fallback covers rate limits, your exponential backoff code for 429 responses may now be redundant. Keep retries only for transport errors (connection reset, timeout). A minimal guard:
import tenacity
@tenacity.retry(
stop=tenacity.stop_after_attempt(3),
retry=tenacity.retry_if_exception_type(ConnectionError),
)
def complete(messages):
return client.chat.completions.create(model="openai/gpt-4o", messages=messages)
Do not retry on 429 or 5xx from the gateway—those are handled internally by failover. Success metric: your error budget for provider throttling drops to near zero in dashboards, and your retry logs shrink.
Step 6: Validate per-token metering
Accurate cost attribution requires token-level usage. The new endpoint returns per-token usage metering in the standard usage object, matching OpenAI’s shape. Log it explicitly:
usage = resp.usage
print(f"prompt={usage.prompt_tokens} completion={usage.completion_tokens}")
# Example usage object:
# {
# "prompt_tokens": 1820,
# "completion_tokens": 64,
# "total_tokens": 1884
# }
Compare a day of traffic on OpenRouter vs the new endpoint for the same inputs. You are done when the totals differ only by provider pricing, not by missing fields. If you aggregate usage for internal chargebacks, pipe these fields to your metrics pipeline as before.
Step 7: Cut over production
Flip the base_url via environment variable, not a code rewrite per service.
export OPENAI_BASE_URL="https://api.n4n.ai/v1"
export OPENAI_API_KEY="$N4N_KEY"
Then restart pods. Keep the old key active for 24 hours in case of rollback. Monitor p99 latency and error rate; if fallback kicks in, you’ll see provider switches in logs without user-visible failures. After cutover, the why migrate from OpenRouter to n4n decision proves its worth when a provider incident causes zero customer-facing errors.
Common pitfalls
- Model ID drift: Some aliases differ slightly between gateways. Always validate against
/models. - Header loss: Custom auth headers for specific providers should be sent as
extra_headersin the OpenAI client, not as global requests config. - Cache mismatch: If you cached responses at the app layer assuming no failover, introduce a request ID check to avoid serving stale fallbacks.
Verification checklist
- All model IDs from Step 1 return 200 on new endpoint.
- Cache-control hints appear in provider billing as cache reads.
- Usage objects contain both prompt and completion tokens.
- No 429s surface from a single provider for >5 minutes (fallback engaged).
- Cost report matches expected token volumes.
The why migrate from OpenRouter to n4n question reduces to operational resilience and metering clarity. Follow these steps and you keep the OpenAI client code while gaining fallback and transparent usage.