Migrating Claude Code to a custom backend in 2 lines (and what to actually watch for) Anthropic's Claude Code can be redirected to any compatible backend using a single environment variable, `ANTHROPIC_BASE_URL`, enabling caching, rate-limit pooling, multi-vendor routing, and audit logging without code changes. A developer demonstrated that a proxy server can inject `cache_control` markers server-side to cut costs by 60-80% on long sessions, and round-robin across multiple API keys to avoid rate limits. However, the proxy must pass through SSE chunks without buffering and preserve critical headers like `anthropic-version` and `anthropic-beta` to prevent silent feature breakage. TL;DR: Claude Code's ANTHROPIC BASE URL env var lets you redirect every request to any compatible backend in one shell line. Almost no one does it, but it unlocks caching, rate-limit pooling, multi-vendor routing, audit logging, and billing routing without rewriting any code. Here's the 2-line setup, the things that quietly break, and the production checklist for actually running it. export ANTHROPIC BASE URL=https://your-proxy.example.com export ANTHROPIC API KEY=your-key claude That's it. The Anthropic SDK which Claude Code is built on doesn't care where it's sending requests, as long as the response comes back in Anthropic Messages format. It'll append /v1/messages automatically, forward all your anthropic-version and anthropic-beta headers, and stream SSE the same way. Same trick works with Cursor, Cline, Continue, and anything else that builds on the Anthropic SDK. I've found five patterns that justify a custom backend: Anthropic's prompt cache feature requires manual cache control markers that most teams skip. A proxy can inject them server-side on every system message. For a Claude Code session with a 20-30K-token system prompt and 50+ turns, this cuts your bill by 60-80%. Most teams have 3-5 API keys spread across projects. Without a proxy, each is rate-limited independently — you can hit 429 on one while another sits idle. A proxy can round-robin across keys, exposing one virtual key with the combined rate budget. Want to route claude-haiku-4-5 calls to one provider and claude-opus-4-7 calls to another maybe one offers Haiku throughput discounts ? A proxy inspects the model field and routes accordingly. Your Claude Code config doesn't change. Claude Code makes a lot of requests. Without instrumentation, you have no idea what each session cost. A proxy can log per-request metadata model, tokens, latency, session id to a warehouse. Different team members hitting different cost centers? A proxy can map API keys to billing tags and forward usage to finance. The 2-line setup works for the happy path. In practice, here's what bites you. Anthropic returns chunked SSE for stream: true . If your proxy buffers responses or doesn't flush each chunk immediately, you'll see massive perceived latency — Claude Code will spin while waiting for the full response. Fix: pass through SSE chunks without buffering. In Caddy, that means flush interval -1 . In Cloudflare Workers, use TransformStream with explicit .write per chunk. In Node, set noDelay: true on the response socket. Anthropic's SDK sends headers like: anthropic-version anthropic-beta for prompt cache, batches, etc. x-api-key auth x-stainless- SDK telemetry If your proxy strips any of these before forwarding to the real upstream, certain features break silently: anthropic-version → SDK gets default-version response which may not match its expectations anthropic-beta → prompt cache headers ignored, you wonder why caching isn't working x-stainless- → harmlessRule of thumb: forward everything except host and authorization since you're rewriting those . Claude Code uses tool calling heavily. A typical session has 30-50 tool call rounds, each one a separate API call with the full conversation history. If your proxy is rate-limited at 60 RPM per source IP, a single Claude Code session can blow through it in 30 seconds. Fix: rate-limit per API key, not per source IP. And budget for high burst rates 200+ RPM during heavy tool-call sessions . If you want to inject cache control or rewrite request bodies, you have to parse the JSON, modify, re-serialize. Be careful: large requests 50K+ tokens of context as JSON-encoded strings take noticeable CPU time to parse. Minimal injection in Node: js const body = JSON.parse rawBody ; // Inject cache control on the first system message if body.system && typeof body.system === 'string' { body.system = { type: 'text', text: body.system, cache control: { type: 'ephemeral' }, } ; } const newRawBody = JSON.stringify body ; For Claude Code's typical traffic this adds <5ms per request. For very large workloads, consider stream-parsing. Anthropic sends error SSE events mid-stream when something fails rate limit, content filter, etc. . Most naive proxies forward the body as opaque bytes, which works. If your proxy tries to be "smart" and parse the SSE, you have to handle error events without breaking the connection. The safe path: don't parse SSE in your proxy unless you absolutely have to. If you're building this proxy yourself: host / authorization That's not "2 lines" anymore. The 2-line part is the SDK config; the checklist is the actual cost of running it in production. When you put a proxy in front of Claude Code, you get observability for free . You can see: Anthropic's dashboard tells you the bill. Your proxy tells you why . For any team running Claude Code at scale, that's often more valuable than the cost optimization itself. A few cases where a custom backend is more trouble than it's worth: claude once a day — direct API is fineThe break-even point is roughly: Below that, just use the real Anthropic API and pocket the engineering time. I built MidRelay https://midrelay.com precisely because this checklist took 6 weeks to get right and I figured other teams shouldn't repeat it. Hosted proxy with both Anthropic and OpenAI surfaces, prompt cache injection on by default, per-key usage logs, CORS enabled for browser clients. Pointing Claude Code at it is the 2-line setup at the top of this post. But honestly: the techniques here work whether you use MidRelay, build your own, or pick any of the other gateways. The interesting thing is almost nobody knows you can point Claude Code at a custom backend, even though Anthropic explicitly documented it. If this post does nothing else but make you realize that capability exists, that's worth your reading time. If you've built something similar, drop a comment with what bit you in production — I'm collecting patterns for a follow-up post on multi-vendor LLM routing.