Anthropic says Claude Code averages $13 per developer per active day. At 20 working days, that's $260/month per engineer. We had 80 engineers on Claude Code. Do the math.
The CFO did the math. We had two weeks to fix it or lose the rollout entirely.
Here's exactly what we did, config files included. No hand-waving.
The Setup Before
We started the way everyone does. Direct API keys per developer, no proxy, no visibility. Each engineer had their own Anthropic API key in their .claude/settings.json. Some were burning through Opus 4 for trivial file renames. Others ran the same 4,000-token system prompt on every single turn, never cached.
Total monthly spend: north of $20,000 for 80 developers. Finance was not amused.
Step 1: Put a Proxy in Front
First thing: route every Claude Code request through LiteLLM. Two environment variables per developer. That's it.
export ANTHROPIC_BASE_URL="https://llm-gateway.internal.company.com"
export ANTHROPIC_AUTH_TOKEN="sk-dev-jsmith-a8f3b2"
The proxy config is a single YAML file:
model_list:
- model_name: claude-sonnet-4-5
litellm_params:
model: anthropic/claude-sonnet-4-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: claude-opus-4
litellm_params:
model: anthropic/claude-opus-4
api_key: os.environ/ANTHROPIC_API_KEY
litellm_settings:
cache: true
cache_params:
type: redis
host: redis.internal
port: 6379
Now every request flows through one gateway. We can see who's calling what, how much they're spending, and on which models.
Step 2: Virtual Keys With Budgets
This is where it gets interesting. Instead of handing out raw API keys, we generate virtual keys per developer through the LiteLLM API:
curl -X POST "https://llm-gateway.internal.company.com/key/generate" \
-H "Authorization: Bearer sk-master-key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "jsmith@company.com",
"team_id": "backend-team",
"max_budget": 120,
"budget_duration": "30d",
"models": ["claude-sonnet-4-5", "claude-opus-4"],
"metadata": {"department": "engineering"}
}'
That max_budget: 120 is in USD. When a developer hits $120 in a 30-day window, requests start failing with a clear error. No silent overruns. No surprise invoices.
We set different tiers: $120/month for regular engineers, $200/month for team leads working on complex refactors, $50/month for interns and part-time contractors. The budget resets every 30 days automatically.
Step 3: Team-Level Guardrails
Individual budgets are good. Team budgets are better. If one person is frugal and another burns through tokens, the team budget catches total overrun:
curl -X POST "https://llm-gateway.internal.company.com/team/new" \
-H "Authorization: Bearer sk-master-key" \
-H "Content-Type: application/json" \
-d '{
"team_alias": "backend-team",
"max_budget": 2000,
"budget_duration": "30d",
"models": ["claude-sonnet-4-5", "claude-opus-4"]
}'
Now the backend team can't exceed $2,000/month collectively, regardless of individual budgets. The hierarchy works: organization > team > user > key. A request that would push any level over budget gets blocked.
Step 4: Prompt Caching (The Big Win)
This was the single largest cost reduction. Claude Code sends the same system prompt and context on every turn in a conversation. Without caching, you're paying full input price for identical tokens over and over.
LiteLLM enables Anthropic prompt caching automatically:
model_list:
- model_name: claude-sonnet-4-5
litellm_params:
model: anthropic/claude-sonnet-4-5
api_key: os.environ/ANTHROPIC_API_KEY
cache_control_injection_points:
- location: message
role: system
Cache-hit tokens cost 90% less than cache-miss tokens on Anthropic's API. For Claude Code sessions where the system prompt and file context stay stable across turns, this cut our per-session cost roughly in half.
We measured before and after over two weeks. Average cost per developer-day dropped from $13.20 to $7.40 just from prompt caching. Nothing else changed.
Step 5: Spend Visibility
You can't manage what you can't measure. The LiteLLM dashboard shows spend per key, per team, per model, per day. But the API is where it gets useful for automation:
curl "https://llm-gateway.internal.company.com/spend/logs" \
-H "Authorization: Bearer sk-master-key" \
-G -d "user_id=jsmith@company.com" \
-d "start_date=2026-07-01" \
-d "end_date=2026-07-11"
We built a Slack bot that posts weekly spend reports per team. When the mobile team spiked 3x one week, we caught it the same day. Turned out a new engineer was using Opus 4 for everything, including linting suggestions. Switched their key to Sonnet-only. Problem solved in five minutes.
Step 6: Model Access Control
Not every task needs Opus 4. Most Claude Code work (autocomplete, simple refactors, test generation) runs perfectly fine on Sonnet 4.5 at a fraction of the cost.
We restricted Opus 4 to senior engineers working on architecture-level changes. Everyone else gets Sonnet 4.5 by default:
# Junior/mid-level key: Sonnet only
curl -X POST ".../key/generate" \
-d '{
"user_id": "intern@company.com",
"models": ["claude-sonnet-4-5"],
"max_budget": 50,
"budget_duration": "30d"
}'
# Senior key: Sonnet + Opus
curl -X POST ".../key/generate" \
-d '{
"user_id": "senior@company.com",
"models": ["claude-sonnet-4-5", "claude-opus-4"],
"max_budget": 200,
"budget_duration": "30d"
}'
This alone knocked another 15-20% off total spend. Most engineers didn't even notice the difference in output quality for their day-to-day coding.
The Numbers
After four weeks with all six steps running:
Before LiteLLM: $260/developer/month average, $20,800 total for 80 engineers.
After: $89/developer/month average, $7,120 total. That's a 66% reduction.
The breakdown: prompt caching contributed roughly 40% of the savings. Model access control contributed 20%. Budget enforcement prevented the long-tail spikes that used to inflate the average. The remaining savings came from visibility alone. When engineers can see their own spend, they self-correct.
What I'd Do Differently
I'd start with the proxy from day one. We wasted three months of uncontrolled spend because "we'll add governance later." Later always means after the CFO sends the email.
I'd also set up JWT integration instead of distributing virtual keys manually. LiteLLM supports mapping SSO claims directly to virtual keys, so developers authenticate with their existing corporate identity. No key distribution, no key rotation headaches:
litellm_settings:
enable_jwt_auth: true
general_settings:
master_key: sk-master-key
enable_jwt_auth: true
The whole setup took one engineer about two days. The proxy runs on a single docker compose up with a Postgres database for spend tracking. We haven't touched it since, except to add new team budgets.
The Point
Claude Code is worth the money. The productivity gains are real. But without a proxy layer handling budgets, caching, and access control, you're flying blind. The $260/month average isn't a Claude Code problem. It's an infrastructure problem.
Two environment variables per developer. One YAML config. That's the entire governance layer between "we're canceling Claude Code" and "this is our most productive tooling investment this year."
The config files from this post are on LiteLLM's Claude Code docs. The proxy is open source. Start there.
Top comments (0)