Cost Optimization for LLM APIs: Reducing Token Usage Without Sacrificing Quality | SoniNow Blog

Limited TimeLearn More

llmcost optimizationapitoken usageai

Cost Optimization for LLM APIs: Reducing Token Usage Without Sacrificing Quality

Published

2026-06-23

Read Time

5 mins

Cost Optimization for LLM APIs: Reducing Token Usage Without Sacrificing Quality

LLM API costs can spiral out of control faster than any other cloud expense. A single production application processing 10M tokens per day costs $300-600/month with GPT-4o-mini, or $3,000+ with GPT-4o. With optimization, you can reduce that by 60-80% without noticeable quality degradation. Here's how.

Model Tiering: The Biggest Lever

The single most effective cost optimization is routing queries to the cheapest model that can handle them. Not every query needs a frontier model:

class ModelRouter:
    def __init__(self):
        self.models = {
            "cheap": "gpt-4o-mini",      # $0.15/M tok input
            "medium": "claude-3-5-haiku", # $0.80/M tok input
            "premium": "gpt-4o",          # $2.50/M tok input
            "expert": "o3-mini",          # $1.10/M tok input (but reasoning)
        }
    
    def route(self, query, context):
        # Simple classification to determine model tier
        complexity = self.estimate_complexity(query)
        
        if complexity == "simple" and len(query) < 200:
            return self.models["cheap"]
        elif complexity == "moderate":
            return self.models["medium"]
        elif context.get("requires_reasoning"):
            return self.models["expert"]
        else:
            return self.models["premium"]

Routing examples:

  • "What's the weather?" → GPT-4o-mini
  • "Explain this customer's billing issue" → Claude Haiku
  • "Write a complex SQL query with joins and window functions" → GPT-4o or o3-mini
  • "Debug this production incident" → o3-mini with reasoning

This tiered approach typically saves 40-60% compared to using a single premium model for everything.

Prompt Compression

LLM pricing is token-based, and many prompts are bloated with irrelevant context:

from llminify import PromptCompressor

compressor = PromptCompressor()

def compress_prompt(messages):
    """Remove redundant instructions and compress verbose prompts."""
    compressed = compressor.compress(
        messages,
        ratio=0.5,  # Target 50% reduction
        condition="keep_meaning_and_instructions",
        keep_blocks=["constraints", "format", "examples"]
    )
    return compressed

Practical compression techniques:

  1. Remove redundant instructions: Once the model learns a pattern from few-shot examples, you don't need the natural language instruction too.
  2. Shorten system prompts: Boil down verbose system instructions. "You are a {role}. Follow {rules}. Output {format}." is often enough.
  3. Truncate conversation history: Keep only messages essential to the current query. A sliding window of 5-10 recent messages is usually sufficient.
  4. Summarize context: Instead of passing 5 full documents, pass a 2-sentence summary of each.

Measured savings: 30-45% token reduction on typical customer support prompts with 95%+ instruction retention.

Semantic Caching

The most expensive LLM call is one you've already made. Cache responses for semantically similar queries:

import hashlib
import numpy as np
from redis import Redis

class SemanticCache:
    def __init__(self, redis_client, similarity_threshold=0.95):
        self.redis = redis_client
        self.embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")
        self.threshold = similarity_threshold
        self.ttl = 3600  # 1 hour default
    
    async def get(self, query, context_hash=""):
        query_embedding = self.embedding_model.embed_query(query)
        cache_key = f"sem_cache:{context_hash}"
        
        # Get all cached embeddings for this context
        cached = await self.redis.hgetall(cache_key)
        
        best_match = None
        best_score = 0
        
        for stored_query, response in cached.items():
            stored_embedding = np.frombuffer(eval(stored_query))
            similarity = cosine_similarity([query_embedding], [stored_embedding])[0][0]
            
            if similarity > best_score:
                best_score = similarity
                best_match = response
        
        if best_score >= self.threshold:
            return json.loads(best_match)
        
        return None
    
    async def set(self, query, response, context_hash=""):
        query_embedding = self.embedding_model.embed_query(query)
        cache_key = f"sem_cache:{context_hash}"
        
        await self.redis.hset(
            cache_key,
            str(query_embedding.tobytes()),
            json.dumps({"response": response, "query": query})
        )
        await self.redis.expire(cache_key, self.ttl)

Cache hit rates by use case:

  • Customer support (frequent questions): 40-60% hit rate
  • Content generation (unique queries): 5-15% hit rate
  • Code generation (repeated patterns): 25-35% hit rate
  • Classification tasks: 60-80% hit rate

Prompt Optimization for Token Efficiency

Small prompt changes produce large cost savings:

# EXPENSIVE: Verbose system prompt (320 tokens)
"""
You are a helpful AI assistant for SoniNow, a company that provides
IT services, web development, SEO, and marketing automation. You help
customers with their questions about our services. Please provide
detailed, thorough answers that cover all aspects of the customer's
question. If you don't know something, say so. Be polite and professional.
"""

# OPTIMIZED: Concise system prompt (85 tokens)
"""
You are a SoniNow support agent.
- Answer concisely and accurately
- Admit when you don't know
- Be professional but not verbose
"""

Token savings: 235 tokens saved per call. At 10M calls/month, that's 2.35B tokens saved = $352/month with GPT-4o-mini.

Batching and Request Optimization

API calls have overhead costs. Batch similar operations:

# INEFFICIENT: Individual requests
responses = []
for query in queries:
    responses.append(llm.call(model="gpt-4o-mini", messages=[{"role": "user", "content": query}]))

# EFFICIENT: Batched via OpenAI's batch API
batch = client.batches.create(
    input_file_id=uploaded_file.id,
    endpoint="/v1/chat/completions",
    completion_window="24h",
    metadata={"task": "content-classification"}
)
# Batch API gives 50% discount

Batching savings:

  • OpenAI Batch API: 50% discount on API costs
  • Anthropic Message Batches: 50% discount
  • Use for async tasks where latency isn't critical (classification, summarization, data extraction)

Monitoring and Optimization Dashboard

Track these metrics weekly:

-- Model cost breakdown
SELECT 
    model,
    COUNT(*) as requests,
    SUM(tokens_prompt + tokens_completion) as total_tokens,
    ROUND(SUM(cost)::numeric, 2) as total_cost,
    ROUND(AVG(cost_per_request)::numeric, 4) as avg_cost_per_request
FROM llm_usage
WHERE date_trunc('week', timestamp) = date_trunc('week', NOW())
GROUP BY model
ORDER BY total_cost DESC;

Target metrics:

  • Average cost per request: < $0.002 (GPT-4o-mini range)
  • Cache hit rate: > 25%
  • Model tier distribution: 60% cheap, 30% medium, 10% premium/expert
  • Cost per user per month: < $0.50 for active users

The 80/20 Rule of LLM Cost Optimization

  1. Model tiering: 50% savings (biggest impact)
  2. Semantic caching: 20-40% savings on repeatable queries
  3. Prompt optimization: 15-30% savings through compression
  4. Batch processing: 50% on applicable workloads
  5. Token budgeting: 10-15% through max_tokens limits

Start with model tiering—it's the easiest to implement with the biggest impact. Add caching next for the highest-repeat queries. Optimize prompts iteratively.

At SoniNow, we build cost-efficient LLM architectures that optimize for quality per dollar. Our AI automation services include cost analysis, model routing, caching infrastructure, and ongoing optimization.

Don't let API costs limit your AI ambitions. Contact us to build a cost-optimized LLM pipeline that scales affordably.