Skip to content

Cost Management and Analytics for Claude Code

Core Concept LearningAugust 18, 202610 min read

Claude Code scales usage across teams—hundreds of engineers running thousands of sessions daily. Without visibility into costs, bills surprise you. With visibility, you can allocate budgets, compare models, and optimize spending.

This guide covers cost tracking: token accounting, per-team and per-developer breakdown, spend limits and alerts, model cost differences, and budget forecasting. You'll learn how extended thinking and prompt caching affect costs, and how to build dashboards that empower teams to optimize. For the broader enterprise rollout this cost data feeds into, see Claude Code enterprise setup; for the compliance controls that pair with spend limits, see enterprise security and compliance.

Token Usage Tracking: Prompt and Completion

Every Claude request consumes tokens: prompt tokens (input) and completion tokens (output). Costs differ by model and token type. Tracking token usage is the foundation of cost management.

The pipeline: runner captures tokens (via SDK metrics), sends to analytics collector, data warehouse aggregates by hour/day, and dashboards query warehouse. Token counts come from API responses; models report prompt_tokens and completion_tokens in usage fields.

Pricing varies: Claude Sonnet costs $3 per 1M prompt tokens, $15 per 1M completion tokens. Opus costs 3x more. Tracking per-model spending lets you make cost/quality tradeoffs.

Quick reference

  • Prompt tokens: input context + user message; varies per request.
  • Completion tokens: model output; can be 1–4K for typical responses.
  • Cache tokens (with prompt caching): cached input tokens cost 10% of normal; cache hits save 90% on prompt cost.
  • Price per model: Sonnet $3/$15; Opus $15/$75; Haiku $0.80/$4 (prices as of Aug 2026).
  • Track per: session, user, team, model, feature_used (e.g., extended_thinking=true).
Token Capture
1# Capture token usage from API response2 3import anthropic4import json5from datetime import datetime6 7client = anthropic.Anthropic()8 9response = client.messages.create(10    model="claude-3-5-opus",11    max_tokens=2048,12    messages=[13        {"role": "user", "content": "Analyze this code..."}14    ]15)16 17# Extract token usage18token_usage = {19    "timestamp": datetime.utcnow().isoformat(),20    "user_id": "user-123",21    "team": "engineering",22    "model": "claude-3-5-opus",23    "prompt_tokens": response.usage.input_tokens,24    "completion_tokens": response.usage.output_tokens,25    "cache_creation_input_tokens": response.usage.cache_creation_input_tokens or 0,26    "cache_read_input_tokens": response.usage.cache_read_input_tokens or 0,27    "session_id": "sess-xyz",28    "feature_flags": {"extended_thinking": True}29}30 31# Send to analytics collector32requests.post(COLLECTOR_URL + "/events", json=token_usage)
Aggregation Query
1# Aggregate tokens by model (SQL)2 3SELECT4    DATE_TRUNC('day', timestamp) as date,5    team,6    model,7    SUM(prompt_tokens) as total_prompt_tokens,8    SUM(completion_tokens) as total_completion_tokens,9    SUM(cache_creation_input_tokens) as cache_new_tokens,10    SUM(cache_read_input_tokens) as cache_hit_tokens,11    COUNT(*) as request_count12FROM token_usage_events13WHERE timestamp >= CURRENT_DATE - INTERVAL '90 days'14GROUP BY date, team, model15ORDER BY date DESC, total_prompt_tokens DESC

Remember this

Capture prompt + completion tokens per request, aggregate by day/team/model, and query to understand usage patterns and model choice tradeoffs.

Per-Project and Per-Developer Breakdown

Teams run multiple projects: "codebase-analysis" consumes high tokens; "comment-generation" low. Developers within teams have different usage patterns. Granular breakdown shows which projects and developers drive costs.

Tag events with project_id and developer_id at collection time. Aggregate to show cost per project (product teams see which projects are expensive), and per developer (for chargeback or kudos).

For chargeback: assign each developer a monthly budget ($100–200). Charge projects to cost centers. This incentivizes optimization.

Quick reference

  • Project tag: add to token_usage event; e.g., project_id='analysis-engine'.
  • Developer tag: user_id already present; optionally add name for dashboards.
  • Cost calc: cost_usd = (prompt_tokens prompt_rate + completion_tokens completion_rate) / 1e6.
  • Chargeback: allocate cost back to developer/project; bill monthly.
  • Threshold alerts: if developer exceeds $50 in a day, alert them.
Cost Breakdown Query
1# Breakdown dashboard query2 3SELECT4    project_id,5    user_id,6    COUNT(DISTINCT session_id) as sessions,7    SUM(prompt_tokens) as prompt_tokens,8    SUM(completion_tokens) as completion_tokens,9    SUM(prompt_tokens * model_rate.prompt_cost +10        completion_tokens * model_rate.completion_cost) / 1e6 as cost_usd11FROM token_usage_events12LEFT JOIN model_rates ON token_usage_events.model = model_rates.model13WHERE timestamp >= CURRENT_DATE - INTERVAL '30 days'14GROUP BY project_id, user_id15ORDER BY cost_usd DESC
Monthly Chargeback
1# Chargeback logic (monthly)2 3def calculate_chargeback(month: str):4    events = query_events_for_month(month)5 6    # Group by developer7    by_dev = defaultdict(float)8    for event in events:9        cost = calculate_cost(event)10        by_dev[event['user_id']] += cost11 12    # Create charge records13    charges = []14    for user_id, cost in by_dev.items():15        charges.append({16            'user_id': user_id,17            'month': month,18            'cost_usd': cost,19            'budget_usd': 150,  # Example budget20            'over_budget': cost > 15021        })22 23    # Send alerts for over-budget developers24    for charge in charges:25        if charge['over_budget']:26            send_slack_alert(27                f"Developer {charge['user_id']} exceeded budget: "28                f"\${charge['cost_usd']:.2f} > \${charge['budget_usd']}"29            )30 31    return charges

Remember this

Tag events with project and developer; aggregate costs per project/developer; set per-developer budgets and alert on overspend.

Spend Limits: Soft and Hard Caps

Two types of limits: soft caps (warn but allow) and hard caps (reject). A team with $1000/month budget: at $800 (80%), send warning; at $1000 (100%), reject new sessions.

Soft caps encourage optimization without disruption. Hard caps prevent runaway costs. For aggressive teams, you can adjust daily: if a team is tracking to overspend by month-end, lower their daily allowance for remaining days.

Implement at the gateway: before sending a request to Claude, check if the user's team (or individual) is over budget. If yes, return 429 Too Many Requests with a message explaining the limit.

Quick reference

  • Soft cap: at 80% of monthly budget, send warning email to team lead.
  • Hard cap: at 100%, reject new sessions; return 429; tell user to wait until next billing cycle.
  • Daily smoothing: if monthly budget is $1000 and we're on day 20 of 30, daily allowance is $1000 * (remaining_days / total_days) = $333.
  • Override: allow managers to override hard cap (e.g., for critical project) with approval log.
  • Grace period: last 3 days of month, allow up to 10% over budget (catch-up for business needs).
Spending Limit Check
1# Soft and hard cap enforcement (gateway)2 3def check_spending_limit(user_id: str, team: str) -> Tuple[bool, Optional[str]]:4    budget = get_team_budget(team)5    current_month_spend = get_month_to_date_spend(team)6 7    hard_cap = budget8    soft_cap = budget * 0.89 10    if current_month_spend >= hard_cap:11        return False, f"Monthly budget limit reached (\${hard_cap:.2f})"12 13    if current_month_spend >= soft_cap:14        # Warn but allow15        logger.warning(f"Team {team} at {current_month_spend / hard_cap * 100:.0f}% of budget")16 17    return True, None18 19# In route handler20allowed, reason = check_spending_limit(user_id, team)21if not allowed:22    return JSONResponse(23        status_code=429,24        content={"error": reason}25    )
Daily Budget Allocation
1# Daily budget smoothing2 3import datetime4 5def get_daily_allowance(team: str) -> float:6    budget = get_team_budget(team)7 8    today = datetime.date.today()9    month_start = today.replace(day=1)10 11    # Last day of month12    if today.month == 12:13        month_end = today.replace(year=today.year + 1, month=1, day=1) - datetime.timedelta(days=1)14    else:15        month_end = today.replace(month=today.month + 1, day=1) - datetime.timedelta(days=1)16 17    total_days = (month_end - month_start).days + 118    remaining_days = (month_end - today).days + 119 20    # Allocate budget proportionally across remaining days21    daily_allowance = budget * remaining_days / total_days22 23    return daily_allowance

Remember this

Soft caps warn; hard caps reject; daily smoothing allocates budget fairly across remaining days; override with approval.

Model Cost Differences: Sonnet vs Opus

Cost-quality tradeoff: Sonnet is 3x cheaper but slower. Opus is 3x more expensive but smarter. Haiku is 10x cheaper but limited. Choosing the right model per task saves 70% of costs.

For most tasks (summarization, routing, simple code review), Sonnet is fine and saves $. For complex reasoning (design decisions, advanced analysis), Opus is worth the premium.

Track cost per model to show which teams overspend on Opus when Sonnet would do. Give teams the choice, but highlight the impact.

Quick reference

  • Haiku: $0.80 / $4 (input/output) — good for simple routing, classification.
  • Sonnet: $3 / $15 — balanced cost/quality; default for most work.
  • Opus: $15 / $75 — expensive; use for complex reasoning, customer-facing.
  • Cost ratio: Opus costs ~8x more than Haiku for same task.
  • Latency: Haiku ~200ms, Sonnet ~500ms, Opus ~800ms (approximate).
Model Cost Comparison
1# Model cost comparison2 3models = {4    "claude-3-5-haiku": {5        "prompt_cost_per_mtok": 0.80,6        "completion_cost_per_mtok": 4.0,7        "latency_ms": 200,8        "quality": 19    },10    "claude-3-5-sonnet": {11        "prompt_cost_per_mtok": 3.0,12        "completion_cost_per_mtok": 15.0,13        "latency_ms": 500,14        "quality": 315    },16    "claude-3-5-opus": {17        "prompt_cost_per_mtok": 15.0,18        "completion_cost_per_mtok": 75.0,19        "latency_ms": 800,20        "quality": 521    }22}23 24# Example: summarize 100K tokens, expect 500 token output25task = {"input_tokens": 100000, "output_tokens": 500}26 27for model_name, specs in models.items():28    cost = (29        task["input_tokens"] / 1e6 * specs["prompt_cost_per_mtok"] +30        task["output_tokens"] / 1e6 * specs["completion_cost_per_mtok"]31    )32    print(f"{model_name}: \${cost:.2f} (latency {specs['latency_ms']}ms, quality {specs['quality']}/5)")
Model Selection
1# Recommendation: choose model based on task requirements2 3def recommend_model(task_type: str, accuracy_required: bool) -> str:4    if task_type in ["summarize", "extract", "classify"]:5        return "claude-3-5-sonnet"  # Good quality, reasonable cost6    elif task_type in ["route", "filter", "identify_intent"]:7        return "claude-3-5-haiku"  # Fast, cheap8    elif task_type in ["reason", "design", "complex_analysis"] and accuracy_required:9        return "claude-3-5-opus"  # High quality, expensive10    else:11        return "claude-3-5-sonnet"  # Default safe choice

Remember this

Sonnet ($3/$15) is best for most work; use Opus ($15/$75) only for complex reasoning; Haiku ($0.8/$4) for simple routing.

Extended Thinking Cost Impact

Extended thinking (letting the model reason internally before responding) improves accuracy but increases token consumption and cost. A task might consume 2x tokens with extended thinking.

Track separately: tag events with extended_thinking=true. Calculate cost impact: "This team spent $50K; with extended thinking, they'd spend $100K." Show the tradeoff: better answers, higher cost.

Extended thinking is worth it for complex reasoning (system design, algorithm decisions) and customer-facing responses, not routine work.

Quick reference

  • Extended thinking: model reasons internally; final answer is shorter but more accurate.
  • Token cost: reasoning tokens count same as output tokens; ~2–5x more tokens for typical tasks.
  • Quality gain: accuracy improves ~5–15% on hard tasks (software design, math).
  • Cost/quality: calculate ROI—if accuracy improves 10% but cost increases 200%, not worth it.
  • Tag: extended_thinking_enabled, reasoning_tokens in events.
Extended Thinking Request
1# Extended thinking request2 3response = client.messages.create(4    model="claude-3-5-opus",5    max_tokens=8000,6    thinking={7        "type": "enabled",8        "budget_tokens": 5000  # Max reasoning tokens9    },10    messages=[11        {"role": "user", "content": "Design a distributed consensus algorithm..."}12    ]13)14 15# Cost tracking16token_event = {17    "extended_thinking": True,18    "reasoning_tokens": response.usage.input_tokens - initial_context_tokens,19    "completion_tokens": response.usage.output_tokens,20    "cost_usd": calculate_cost(response.usage, model="claude-3-5-opus")21}
Extended Thinking Cost Breakdown
1# Cost impact analysis (SQL)2 3SELECT4    DATE_TRUNC('day', timestamp) as date,5    COUNT(CASE WHEN extended_thinking THEN 1 END) as reasoning_requests,6    COUNT(*) as total_requests,7    SUM(CASE WHEN extended_thinking THEN reasoning_tokens ELSE 0 END) as reasoning_tokens,8    SUM(completion_tokens) as output_tokens,9    SUM(CASE WHEN extended_thinking THEN cost_usd ELSE 0 END) as reasoning_cost,10    SUM(cost_usd) as total_cost11FROM token_usage_events12WHERE timestamp >= CURRENT_DATE - INTERVAL '30 days'13GROUP BY date14ORDER BY date DESC

Remember this

Extended thinking costs 2–5x more tokens but improves accuracy; tag separately and track ROI by task type.

Prompt Caching Savings

Prompt caching stores large context blocks (e.g., entire codebase, documentation) at the API layer. Subsequent requests reuse the cached context for 10% of normal prompt token cost. This is huge: if you analyze the same codebase 10 times, you pay prompt cost only once.

Track cache creation tokens (first request) and cache read tokens (subsequent). Monitor cache hit rate: high hit rate means big savings; low hit rate means you're not caching effectively.

For teams repeatedly analyzing the same context (e.g., QA testing against the same codebase), caching can reduce costs by 80%.

Quick reference

  • Cache write: first request to a context; counted as full prompt tokens.
  • Cache read: subsequent requests to same context; prompt tokens cost 1/10th normal rate.
  • Cache TTL: 5 minutes for API cache; expired caches are re-created (cost reset).
  • Hit rate: (cache_read_tokens / (cache_read_tokens + normal_prompt_tokens)) * 100.
  • Ideal for: analyzing same codebase/docs repeatedly, e.g., QA, security review.
Prompt Caching
1# Enable prompt caching in API calls2 3response = client.messages.create(4    model="claude-3-5-sonnet",5    max_tokens=1024,6    system=[7        {8            "type": "text",9            "text": "You are a code reviewer."10        },11        {12            "type": "text",13            "text": LARGE_CODEBASE_CONTENT,  # e.g., 50K tokens14            "cache_control": {"type": "ephemeral"}15        }16    ],17    messages=[18        {"role": "user", "content": "Review this pull request..."}19    ]20)21 22# Capture cache tokens23cache_tokens = {24    "cache_creation_input_tokens": response.usage.cache_creation_input_tokens or 0,25    "cache_read_input_tokens": response.usage.cache_read_input_tokens or 0,26}
Caching ROI Calculation
1# Calculate caching ROI2 3def calculate_caching_roi(team: str, days: int = 30):4    events = query_events_for_team(team, days)5 6    total_cache_writes = sum(e['cache_creation_input_tokens'] for e in events)7    total_cache_reads = sum(e['cache_read_input_tokens'] for e in events)8 9    # Cost if no caching: all tokens at full rate10    full_cost = (11        (total_cache_writes + total_cache_reads) * PROMPT_RATE / 1e612    )13 14    # Cost with caching: writes at full rate, reads at 10%15    cached_cost = (16        total_cache_writes * PROMPT_RATE / 1e6 +17        total_cache_reads * PROMPT_RATE * 0.1 / 1e618    )19 20    savings = full_cost - cached_cost21    hit_rate = total_cache_reads / (total_cache_reads + total_cache_writes + 1) * 10022 23    print(f"Cache hit rate: {hit_rate:.1f}%")24    print(f"Cost without caching: \${full_cost:.2f}")25    print(f"Cost with caching: \${cached_cost:.2f}")26    print(f"Savings: \${savings:.2f} ({savings/full_cost*100:.1f}%)")

Remember this

Prompt caching reduces subsequent requests to 10% cost; ideal for teams repeatedly analyzing same context (80% savings for QA teams).

Analytics Dashboard Walkthrough

A dashboard should answer: "What are we spending? On what? Who? Is it growing? Which models? Is caching working?" Key charts:

1. Total spend (daily) — trend over time. 2. Spend by team — which teams drive costs. 3. Spend by model — are we using the right models? 4. Spend by feature (extended thinking, caching) — ROI on expensive features. 5. Per-developer spending — chargeback view. 6. Cache hit rate — is caching effective? 7. Budget vs actual — are we on track?

Quick reference

  • Daily spend chart: x=date, y=spend_usd; trend line shows growth rate.
  • Team breakdown: stacked bar chart; team colors; hover for details.
  • Model distribution: pie chart; Sonnet %, Opus %, Haiku %; cost per model.
  • Feature ROI: extended_thinking spend vs total; cache_savings vs cache_cost.
  • Developer leaderboard: top spenders; filter by team or project.
  • Budget tracking: gauge chart; % of monthly budget consumed; days remaining.

Remember this

A cost dashboard shows spend trends by team, model, and feature; enables data-driven budget decisions and optimization.

Budget Forecasting Patterns

Given 30 days of history, predict month-end spend. Simple method: daily average * days in month. Better: fit a trend line (spend growing 5%/day?) and extrapolate.

For teams with seasonal patterns (e.g., spike during launch prep), use historical month patterns or allow manual forecasting adjustments.

Alert if forecast > budget: "Your team is on track to spend $1200 this month; budget is $1000. Adjust model choices or extend budget."

Quick reference

  • Simple forecast: avg_daily_spend * days_in_month.
  • Trend-based: fit line to daily spend; extrapolate to month-end.
  • Seasonal adjustment: compare to same month last year; adjust for growth rate.
  • Confidence: low (day 5), high (day 25).
  • Alert threshold: if forecast > budget * 0.9, warn team.
Simple Forecast
1# Simple forecasting2 3import numpy as np4from datetime import datetime, date5 6def forecast_month_end_spend(team: str) -> float:7    today = date.today()8    month_start = today.replace(day=1)9    days_elapsed = (today - month_start).days + 110 11    # Get historical daily spend12    daily_spend = query_daily_spend(team, month_start, today)13 14    # Calculate average15    avg_daily_spend = np.mean(daily_spend[-7:])  # Last 7 days16 17    # Forecast18    total_days_in_month = 30 if today.month in [4, 6, 9, 11] else 3119    forecast = avg_daily_spend * total_days_in_month20 21    return forecast
Trend-Based Forecast
1# Trend-based forecasting with linear regression2 3def forecast_with_trend(team: str) -> Tuple[float, float]:4    today = date.today()5    month_start = today.replace(day=1)6 7    daily_spend = query_daily_spend(team, month_start, today)8 9    # Fit line: y = mx + b10    x = np.arange(len(daily_spend))11    coeffs = np.polyfit(x, daily_spend, 1)12    slope, intercept = coeffs13 14    # Extrapolate to month-end (day 30)15    total_days = 3016    remaining_days = total_days - len(daily_spend)17 18    forecast = sum(daily_spend)  # What we've spent19    for day in range(len(daily_spend), total_days):20        forecast += slope * day + intercept21 22    confidence = len(daily_spend) / 30  # Higher confidence on day 30 vs day 523 24    return forecast, confidence

Remember this

Forecast month-end spend using daily average or trend; alert teams if forecast exceeds budget; adjust confidence based on days elapsed.

Key takeaway

Cost analytics are the backbone of enterprise Claude Code operations. Track token usage per request, aggregate by team/developer/model, enforce budgets, and forecast spend.

Start simple: collect token events, aggregate daily, show total spend. Add per-team breakdown. Layer in model recommendations and caching ROI.

The key insight: visibility enables optimization. Teams that see their costs and model choices optimize naturally. Teams without visibility tend to over-spend.

Next: combine cost analytics with enterprise security to ensure you're not only tracking spend, but also compliance and data residency.

Share:
PK

Polo Khan

Lead Author & Systems Architect

Software engineer and distributed systems architect specializing in backend scalability, cloud-native infrastructure, databases, and AI engineering workflows. Author and maintainer of Core Concept Learning.

Human-Engineered & Fact-CheckedOriginal Visual DiagramsEditorial Standards →Send Feedback

Related Articles

Enterprise teams running Claude Code across 100+ developers face a critical problem: how do you enforce company policies

Read

When Claude Code traffic grows from 10 to 1000 concurrent users, a single endpoint breaks. You need a gateway: a single

Read

Healthcare, finance, and legal teams cannot send data to third-party APIs unless those APIs are certified compliant. Cla

Read

Keep learning

Follow a structured path or browse all courses to go deeper.