If you're building on the Claude API, you've probably noticed your costs don't scale linearly with conversation length. They scale quadratically. This post explains why, walks through four approaches to fix it, and shares benchmark data from a real 40-prompt Sonnet session.
The Problem: Stateless Models, Compounding Tokens
The Claude API is stateless. There is no server-side memory of your conversation. Every request includes the full message history -- every user message, every assistant response, every tool call result, everything.
Here's what that looks like in practice for a Sonnet conversation at $3 per million input tokens:
| Turn | Cumulative Input Tokens | Cost Per Call | Running Total |
|---|---|---|---|
| 1 | ~500 | $0.002 | $0.002 |
| 5 | ~5,000 | $0.015 | $0.04 |
| 10 | ~12,000 | $0.036 | $0.18 |
| 20 | ~28,000 | $0.084 | $0.85 |
| 30 | ~42,000 | $0.126 | $1.70 |
| 40 | ~55,000 | $0.165 | $2.56 |
By turn 40, you've spent $2.56 on input tokens for a single conversation. The per-call cost keeps climbing because each call re-sends everything that came before. Turn 40 includes all 39 previous turns.
For a chatbot serving 1,000 conversations per day that average 20 turns each, that's roughly $850/day in input token costs alone. That's $25,500/month before you count output tokens.
Approach 1: Manual Context Window Management
The most common DIY fix is truncating old messages. Keep the system prompt and the last N turns, drop everything else.
Pythondef trim_messages(messages, max_turns=10):
if len(messages) > max_turns * 2:
system = [m for m in messages if m["role"] == "system"]
recent = messages[-(max_turns * 2):]
return system + recent
return messages
This works, but it's a blunt instrument. You lose context that might be relevant. If the user referenced something from turn 3 in turn 25, that context is gone. The model's responses degrade in ways that are hard to detect and hard to debug.
You also end up maintaining this logic per-application, tuning the window size, handling edge cases (what happens when a tool call result references a previous tool call that got truncated?), and hoping the degradation isn't noticeable.
Approach 2: Prompt Caching
Anthropic offers prompt caching, which avoids re-processing tokens that match a previous request's prefix. If the first 20K tokens of your request are identical to your last request, you pay the cached rate (currently 90% cheaper) for those tokens.
This is genuinely useful when it works. The catch: the prefix must be identical, byte-for-byte. In practice, this means:
- Branching conversations invalidate the cache
- Editing a previous message invalidates the cache
- Tool call results inserted mid-conversation invalidate the cache
- Any system prompt change invalidates the cache
For linear, non-branching conversations with a stable system prompt, caching is effective. For agent-style workloads with tool use, the cache hit rate can be surprisingly low. Anthropic's own documentation notes this limitation.
Prompt caching also doesn't reduce the total tokens sent -- it reduces the processing cost on Anthropic's side. You still transmit the full payload over the network.
Approach 3: Model Switching
Use a cheaper model for earlier turns, then switch to a more capable (and expensive) model for the final response. For example, use Haiku for the first 30 turns of an agent loop, then Sonnet for the final synthesis.
This works for some use cases but introduces complexity:
- You need routing logic to decide when to switch
- The cheaper model might make mistakes that the expensive model has to recover from
- Quality is inconsistent across the conversation
- You're still paying for all those input tokens, just at a lower per-token rate
Approach 4: Proxy-Based Context Compression
This is what PromptCrunch does. A proxy sits between your application and the Claude API. It receives the full conversation history, compresses redundant context in older turns, and forwards the optimized request to Anthropic.
The key constraints:
- Recent messages stay verbatim. The last several turns pass through untouched. Compression only applies to older context where redundancy has accumulated.
- Structured data is preserved. Code blocks, JSON, SQL, tool call results, and other structured content are never compressed. These are too brittle -- even minor changes break functionality.
- The API contract is unchanged. Your application sends and receives the same request/response format. Streaming works. Tool use works. Vision works.
The Benchmark
I ran a 40-prompt session on Claude Sonnet. The conversation was a long, prose-heavy advisory discussion: planning, questions, and iterative back-and-forth, the kind of multi-turn conversational workload PromptCrunch is built for. Worth stating plainly: coding-agent sessions (Claude Code, Codex) are a different story. They are mostly code and tool output that PromptCrunch preserves verbatim, so they largely pass through with 0-7% savings.
Without PromptCrunch:
Total input tokens: ~855,000 (cumulative across all 40 calls)
Total input cost: $2.56
With PromptCrunch:
Total input tokens: ~213,000 (cumulative across all 40 calls)
Total input cost: $0.64
Reduction: 75%
The savings compound with conversation length. Short conversations (under 5 turns) see minimal benefit because there's not enough redundant context to compress. The sweet spot is 15+ turns, where older context has significant overlap with newer messages.
How to Set It Up
PromptCrunch works with both the Anthropic and OpenAI APIs. Setup is a base URL change plus one header.
Python (Anthropic SDK)
Pythonimport anthropic
client = anthropic.Anthropic(
base_url="https://api.promptcrunch.dev",
default_headers={"X-PromptCrunch-Key": "pc_your_key_here"}
)
# Use exactly as before -- no other code changes
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}]
)
Node.js (Anthropic SDK)
JavaScriptimport Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://api.promptcrunch.dev",
defaultHeaders: { "X-PromptCrunch-Key": "pc_your_key_here" }
});
// Use exactly as before
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }]
});
curl
Bashcurl https://api.promptcrunch.dev/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "X-PromptCrunch-Key: pc_your_key_here" \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-4-20250514",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello"}]
}'
Your Anthropic (or OpenAI) API key passes through to the provider. PromptCrunch never stores it.
The Honest Trade-Offs
No tool is perfect. Here's what you should know:
Latency.
Compression adds approximately 250ms per request. For interactive chatbots where every millisecond of time-to-first-token matters, this is a real cost. For batch processing, agent loops, and development tools, it's typically unnoticeable.
Short conversations.
If your average conversation is under 5 turns, PromptCrunch won't save you meaningful money. The overhead of compression outweighs the savings on small payloads. This tool is for multi-turn workloads.
Compression is lossy.
Older context gets compressed, which means some information is reduced to summaries. For most conversational workloads, this doesn't affect response quality. But if your application relies on exact recall of early messages (verbatim quotes, specific numbers mentioned 30 turns ago), test carefully.
Privacy.
PromptCrunch offers a zero-retention mode that never persists prompt content. The proxy processes requests in memory and forwards them. Even the optional optimization cache can be disabled entirely. But the fact remains: your API traffic routes through a third-party proxy. If your compliance requirements prohibit any intermediary, this isn't for you.
Try It
The free tier gives you $5 in credit with no card required and one API key. That's enough to benchmark it against your own workload and see real numbers.
If you're spending more than $50/month on Claude or OpenAI API input tokens and your conversations average 10+ turns, the math is likely in your favor.