Back to all posts

cat posts/spotify-cut-claude-code-tokens-90-copy-the-pattern.md --category "AI & Cloud Infrastructure" --views 13

Spotify cut Claude Code tokens 90%: copy the pattern

Spotify routes bulk file reads and boilerplate generation out of Claude Code to a cheaper worker model, cutting Claude token usage on those reads by 90% in tests on a Java monorepo. The pattern needs no Portal licence: Claude Code hooks, two wrapper scripts and a flash-class model in Microsoft Foundry rebuild it inside your own Azure tenant, with the boundaries Spotify itself draws around editing and reasoning.

  • --author By Falak Mahmood
  • --date September 8, 2026
  • --read 9 min read
  • --views 13 views

On 3 September 2026, Spotify principal product manager Dimitri Mazmanov published a number that every team paying for AI coding agents should sit with: 90% of the Claude Code tokens he was burning on bulk file reads disappeared when those reads were routed to a cheaper model. The test bed was a Java monorepo. The mechanism is three layers of plumbing: Claude Code hooks that block expensive reads before they happen, wrapper scripts that hand the work to Gemini 2.5 Flash, and skill files that teach Claude when to delegate. Spotify ships the pattern through Portal, its commercial Backstage product, but nothing in the pattern itself is proprietary. You can rebuild it on Azure this week.

What Spotify actually built

Portal by Spotify is the company's hosted, no-code edition of Backstage, the open-source developer portal Spotify donated to the CNCF. Portal ships with AiKA, Spotify's internal AI knowledge assistant, and AiKA recently gained Modes: declarative agents that run on ephemeral runtimes. Mazmanov describes a mode as "a declarative agent that runs on an ephemeral runtime - think AWS Lambda, but for agents." You define instructions, pick a model, set parameters like temperature and attach MCP tools. No infrastructure, no API keys to manage.

Two modes carry the token-saving pattern, and both are public in Portal's actions registry:

  • bulk-reader reads multiple large files to answer a single question and returns "structured bullets only. No greetings, no prose, no preambles."
  • code-writer generates boilerplate, tests and configuration by matching existing patterns in the repo, returning bare code with no explanations and no markdown fences.

Both default to Gemini 2.5 Flash as the worker model, though the model field accepts anything configured in the Portal instance. The frontier model, Claude, never stops being the orchestrator. It just stops doing the reading.

The three layers that make Claude comply

Telling an agent to delegate in a CLAUDE.md file is a suggestion. Spotify's setup makes it an enforced default, in three layers.

Layer 1: hooks that block the expensive path

Claude Code hooks intercept tool calls before they execute. A check-file-size hook blocks any Read of a file over 350 lines (configurable through a SHUNT_MIN_LINES variable) and tells Claude to use the bulk-reader instead. A companion check-bash-read hook catches the workaround every agent tries next: reading the file through a shell command instead of the Read tool. The threshold matters. Delegation adds 10 to 30 seconds of latency per call, so shunting a 40-line file would cost time and save nothing.

Layer 2: wrapper scripts that do the handoff

Two bash wrappers, bulk-read and code-write, invoke the Portal CLI, pass the question and file paths to the mode, and report token usage back so the savings are measurable rather than assumed.

Layer 3: skills as the fallback

Markdown skill files describe when and how to delegate, so that even when a hook does not fire, Claude knows the delegation route exists. Hooks enforce, skills educate. The combination is what produced consistent behaviour.

Why the math works

Agentic coding is input-heavy. When Claude Code answers "how does retry handling work in this service", it may read four files of 1,500 lines each. Code runs roughly 10 to 15 tokens per line, so that is in the region of 80,000 input tokens ingested to produce a ten-line answer. The tokens do not just cost money once: everything read stays in the context window and is re-sent on every subsequent turn of the session.

Model Input / MTok Output / MTok
Claude Sonnet 5 (orchestrator) $2.00 $10.00
Gemini 2.5 Flash (Spotify's worker) $0.30 $2.50
Gemini 3.8 Flash (until 31 Dec 2026) $0.75 $3.75

Run the 80,000-token read through the table. Ingested by Sonnet 5 at $2 per million input tokens, it costs 16 cents up front, then keeps costing as cached context on every later turn. Delegated to Gemini 2.5 Flash at $0.30, the same read costs about 2.4 cents, and Claude receives a summary of a few hundred tokens instead of the raw files. The per-read saving is real but modest. The compounding saving is the one that matters: Claude's context stays small, so every subsequent turn in a long session sends fewer tokens, and the model stays sharper because it is not reasoning across tens of thousands of tokens of raw Java it needed for one answer.

Mazmanov frames the stakes bluntly: engineering leaders he talks to are spending $200 to $500 per developer per month on tokens, some well past $2,000, and on current trends AI coding costs are heading past the average developer salary by 2028. Whether or not that extrapolation holds, the per-seat numbers match what we see in Swedish teams adopting agentic coding at scale.

What Spotify refused to delegate

The limitations section of the Spotify post deserves as much attention as the headline number, because it is a map of where this pattern breaks.

  • Editing stays with Claude. Worker summaries do not carry reliable line numbers, and an agent editing a file needs line-accurate context. Delegating reads that feed directly into edits produced worse results.
  • Reasoning stays with Claude. In testing, the worker model missed subtle thread-safety bugs that Claude caught with direct file access. Debugging, architectural decisions and safety-critical code are explicitly excluded from delegation.
  • Small files stay with Claude. The 10-to-30-second delegation overhead exceeds the saving below the line threshold, which is why the hook has one.

This is the same division of labour we recommended in our August piece on workhorse models: frontier model for judgment, cheap model for volume. Spotify has now published production evidence for where that boundary sits in agentic coding.

Rebuilding the pattern on Azure, without Portal

Portal is a licensed product, and its modes run on Spotify's hosted runtimes. If you are a Backstage shop already, evaluating Portal is worth doing on its own merits. But the token pattern needs none of it. Claude Code hooks are a public feature, and a flash-class worker model deployed in Microsoft Foundry gives you the same delegation target inside your own tenant.

Register the hook in your project's Claude Code settings:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/check-file-size.sh"
          }
        ]
      }
    ]
  }
}

The hook script reads the tool call from stdin, counts lines, and blocks with exit code 2 when the file is large. Whatever it writes to stderr is fed back to Claude as instructions:

#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
[ -z "$FILE" ] && exit 0
LINES=$(wc -l 2>/dev/null < "$FILE" || echo 0)
LIMIT=350
if [ "$LINES" -gt "$LIMIT" ]; then
  echo "$FILE has $LINES lines. Do not read it directly." >&2
  echo "Run: .claude/hooks/bulk-read.sh 'your question' $FILE" >&2
  exit 2
fi
exit 0

The bulk-read script is a thin wrapper around your Foundry deployment's chat completions endpoint. It concatenates the files, prepends the question, pins the system prompt to structured bullets, and prints the worker's answer for Claude to consume:

#!/bin/bash
QUESTION=$1; shift
CONTENT=$(cat "$@")
jq -n --arg q "$QUESTION" --arg c "$CONTENT" \
  '{messages: [
     {role: "system",
      content: "Answer with structured bullets only. No prose, no preamble."},
     {role: "user", content: ($q + "\n\n" + $c)}
   ]}' \
  | curl -s -X POST "$WORKER_ENDPOINT" \
      -H "api-key: $WORKER_KEY" -H "Content-Type: application/json" -d @- \
  | jq -r '.choices[0].message.content'

Add a matching hook for the Bash tool that pattern-matches cat, head and tail against large files, and a short skill file explaining the delegation route. Log token counts from the worker's response so you can prove the saving instead of asserting it. That is the whole pattern: two hooks, two scripts, one cheap deployment.

How delegation interacts with prompt caching

A fair objection: prompt caching already discounts re-sent context heavily. Anthropic charges cache reads at a tenth of the base input price, so the "80,000 tokens re-sent every turn" problem costs 1.6 cents per turn on Sonnet 5, not 16. If your sessions are short and your reads are few, caching alone may make delegation not worth the latency.

The two techniques compose rather than compete. Caching lowers the price of context you carry; delegation stops the context from existing. Only delegation keeps the working set small enough that a two-hour agentic session does not degrade into long-context drift, and only delegation protects you when a session restarts and the cache is cold. Spotify's 90% figure is a token reduction on bulk reads, not a 90% bill reduction, and Mazmanov never claims otherwise. Measure your own mix: a team doing many short sessions benefits mostly from caching, a team running long autonomous sessions on a monorepo benefits from both.

The Swedish and EU angle

Spotify is the most-watched engineering organisation in Sweden, and Backstage is embedded in platform teams across the Nordics. When Spotify publishes a cost pattern with public, reusable modes, it tends to become the default architecture in Swedish platform engineering within a couple of quarters. Expect this one in your next platform-team planning discussion.

Before copying it, note what delegation does to your data flows. Every shunted read sends source code to a second model provider. If your worker is a third-party API, that is a new data processor touching your codebase, with its own DPA, retention terms and transfer assessment. For teams whose code falls under NIS2 supplier-security reviews or plain IP caution, the cleaner route is the one sketched above: deploy the worker model in your own Microsoft Foundry project, in the same region and tenant as the rest of your Azure estate, so the delegation never leaves your compliance boundary. The EU Data Zone deployments we covered in September make that placement explicit. Portal itself is a hosted SaaS, so evaluating it lands in normal procurement territory; the do-it-yourself version adds no new vendor at all.

Where to start

  • 1. Measure before building. Pull a week of Claude Code usage and find what share of input tokens comes from file reads. If it is under a third, stop here; caching tuning will pay better.
  • 2. Deploy a worker. One flash-class model in Foundry, same tenant, temperature low, system prompt fixed to structured output.
  • 3. Add the read hook first. Start with a 350-line threshold like Spotify, then tune against your own latency tolerance.
  • 4. Close the bash loophole. Agents route around blocks; the second hook is not optional.
  • 5. Keep edits and debugging on the frontier model. Spotify tested the boundary so you do not have to rediscover it in production incidents.
  • 6. Log both sides. Worker tokens, orchestrator tokens, and wall-clock latency per delegation. Savings you cannot show are savings that get reversed in the next budget round.

subscribe # the AI news that matters, minus the noise

Book a Call

Tags

Related posts