Back

Como cortar seus custos de API LLM em 90%: Caching, Routing e Otimização de Prompts que realmente funcionam

Sua fatura de API LLM bateu 2,400esseme^s.Me^spassadofoi2,400 esse mês. Mês passado foi 800. O anterior, $300. Seu produto tá crescendo, os usuários adoram as funcionalidades de IA, e o time financeiro tá começando a fazer perguntas desconfortáveis.

Soa familiar? Você não tá sozinho. Em 2026, o produto SaaS com IA médio gasta entre 30 e 50% do orçamento de infraestrutura em chamadas de API LLM. E a maior parte desse gasto é completamente desnecessária.

A verdade desconfortável: a maioria das aplicações manda queries redundantes, usa modelos caros pra tarefas triviais e transmite muito mais tokens do que precisa. A solução não é usar menos IA — é usar de forma mais inteligente.

Nesse guia a gente cobre cinco estratégias testadas em produção que cortam custos de API LLM em 70-90% sem degradar qualidade. Não são truques teóricos. Cada técnica vem com código pronto pra produção, cálculos reais e análise honesta de trade-offs.

Primeiro: Entender a estrutura de custos

Antes de otimizar qualquer coisa, você precisa entender como tá sendo cobrado de verdade. A maioria dos devs tem uma noção vaga de que "tokens custam dinheiro" sem entender o panorama completo.

A economia dos tokens

Todos os provedores principais cobram por token, mas a conta não é tão simples:

Snapshot de preços 2026 (por 1M de tokens):

┌─────────────────────────┬──────────┬───────────┐
│ Modelo                  │  Input   │  Output   │
├─────────────────────────┼──────────┼───────────┤
│ GPT-4.1                 │  $1.00   │   $4.00   │
│ GPT-4.1 mini            │  $0.20   │   $0.80   │
│ GPT-4.1 nano            │  $0.05   │   $0.20   │
│ Claude Opus 4.6         │  $5.00   │  $25.00   │
│ Claude Sonnet 4.6       │  $3.00   │  $15.00   │
│ Claude Haiku 4.5        │  $1.00   │   $5.00   │
│ Gemini 2.5 Pro          │  $1.25   │  $10.00   │
│ Gemini 2.5 Flash        │  $0.30   │   $2.50   │
│ DeepSeek V4             │  $0.30   │   $0.50   │
└─────────────────────────┴──────────┴───────────┘

Duas coisas saltam aos olhos:

  1. Tokens de saída custam 3-5x mais que os de entrada. Um prompt de 200 tokens que gera uma resposta de 2,000 tokens custa muito mais do que você imaginaria olhando só a entrada.
  2. A diferença entre tiers é absurda. Claude Opus 4.6 custa 125x mais por token de saída que GPT-4.1 nano. E pra muitas tarefas, o modelo barato funciona igualmente bem.

Onde o dinheiro realmente vai

Numa aplicação com IA típica, os custos se distribuem assim:

Distribuição típica de custos LLM:

  Queries repetidas/similares:           35-45%  ← Cacheável
  Tarefas simples em modelos premium:    20-30%  ← Redirecionável pra modelos baratos
  Prompts inchados:                      15-20%  ← Comprimível
  Queries únicas complexas inevitáveis:  10-20%  ← Otimizar tamanho da saída

Isso significa que 60-80% do seu gasto com LLM é reduzível sem afetar a qualidade do produto. Vamos estratégia por estratégia.

Estratégia 1: Semantic Caching

A otimização com maior retorno que você pode fazer. Se sua aplicação lida com padrões repetitivos — suporte ao cliente, geração de conteúdo, assistência de código, busca — provavelmente tá fazendo chamadas idênticas ou quase idênticas milhares de vezes.

O problema do cache tradicional

Cache tradicional usa matching exato de string. Mas queries pra LLMs quase nunca são idênticas. Olha essas três entradas do usuário:

"Como reseto minha senha?"
"Como mudo minha senha?"
"Esqueci minha senha, como faço pra recuperar?"

Semanticamente são idênticas — deveriam retornar a mesma resposta. Mas um cache de matching exato trata como três chamadas faturáveis separadas.

Como funciona o Semantic Caching

Converte queries em vetores de embedding e usa similaridade cosseno pra achar respostas cacheadas "parecidas o suficiente" em significado:

import { OpenAI } from 'openai'; import { createClient } from 'redis'; import { Index } from '@upstash/vector'; const openai = new OpenAI(); const redis = createClient(); const vectorIndex = new Index({ url: process.env.UPSTASH_VECTOR_URL!, token: process.env.UPSTASH_VECTOR_TOKEN!, }); interface CachedResponse { response: string; model: string; timestamp: number; hitCount: number; } const SIMILARITY_THRESHOLD = 0.92; // Calibre isso com cuidado const CACHE_TTL = 86400; // 24 horas async function queryWithSemanticCache( prompt: string, systemPrompt: string, model: string = 'gpt-4.1-mini' ): Promise<{ response: string; cached: boolean; savings: number }> { // 1. Gerar embedding da query recebida const embedding = await openai.embeddings.create({ model: 'text-embedding-3-small', input: `${systemPrompt}\n${prompt}`, }); const vector = embedding.data[0].embedding; // 2. Buscar queries cacheadas semanticamente similares const results = await vectorIndex.query({ vector, topK: 1, includeMetadata: true, }); // 3. Checar se tem match próximo o suficiente if (results.length > 0 && results[0].score >= SIMILARITY_THRESHOLD) { const cacheKey = results[0].id; const cached = await redis.get(`llm:${cacheKey}`); if (cached) { const parsed: CachedResponse = JSON.parse(cached); parsed.hitCount++; await redis.set(`llm:${cacheKey}`, JSON.stringify(parsed), { EX: CACHE_TTL, }); return { response: parsed.response, cached: true, savings: estimateCost(prompt, parsed.response, model), }; } } // 4. Cache miss — fazer a chamada real const completion = await openai.chat.completions.create({ model, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: prompt }, ], }); const response = completion.choices[0].message.content!; // 5. Salvar no vector index e Redis const cacheId = crypto.randomUUID(); await vectorIndex.upsert({ id: cacheId, vector, metadata: { prompt: prompt.slice(0, 200) }, }); await redis.set( `llm:${cacheId}`, JSON.stringify({ response, model, timestamp: Date.now(), hitCount: 0, } satisfies CachedResponse), { EX: CACHE_TTL } ); return { response, cached: false, savings: 0 }; }

O threshold de similaridade é tudo

O SIMILARITY_THRESHOLD é o parâmetro de ajuste mais crítico. Se errar:

  • Alto demais (>0.97): Quase nada dá match. Hit rate perto de zero. Você construiu um no-op caro.
  • Baixo demais (<0.85): Queries sem relação retornam respostas cacheadas. Usuários recebem respostas erradas.

O ponto ideal depende do caso de uso:

Caso de UsoThreshold RecomendadoMotivo
FAQ / Suporte0.90 - 0.93Perguntas se agrupam por tema
Geração de código0.95 - 0.97Diferenças mínimas geram código diferente
Resumo de conteúdo0.88 - 0.92Mesmo documento → mesmo resumo independente da formulação
Escrita criativaNão cachearCada resposta precisa ser única

Impacto real nos custos

A conta pra um chatbot de suporte processando 100,000 queries/mês:

Sem cache:
  100,000 queries × ~500 tokens input × ~800 tokens output
  = 50M input + 80M output tokens
  GPT-4.1 mini: (50 × $0.20) + (80 × $0.80) = $74/mês

Com semantic caching (65% hit rate):
  35,000 chamadas API reais + 65,000 cache hits
  Embeddings: $0.04
  API: (17.5M × $0.20 + 28M × $0.80) / 1M = $25.90/mês
  Vector DB: ~$10 / Redis: ~$5
  Total: ~$41/mês → 45% de economia

E isso com um hit rate conservador de 65%. Aplicações com padrões repetitivos costumam passar de 80%, com economia acima de 70%.

Estratégia 2: Routing Inteligente de Modelos

A otimização que a maioria dos times pula porque parece complexidade à toa. Mas a matemática convence: provavelmente você tá usando um modelo de 15/Mtokenspratarefasqueummodelode15/M tokens pra tarefas que um modelo de 0.05/M resolve igualmente bem.

A arquitetura de routing

A ideia é simples: antes de mandar uma request pro modelo caro, classifica ela e redireciona pro modelo mais barato que dê conta.

type ComplexityLevel = 'trivial' | 'simple' | 'moderate' | 'complex'; interface RouteConfig { model: string; maxTokens: number; temperature: number; costPer1MInput: number; costPer1MOutput: number; } const MODEL_ROUTES: Record<ComplexityLevel, RouteConfig> = { trivial: { model: 'gpt-4.1-nano', maxTokens: 256, temperature: 0.1, costPer1MInput: 0.05, costPer1MOutput: 0.20, }, simple: { model: 'gpt-4.1-mini', maxTokens: 1024, temperature: 0.3, costPer1MInput: 0.20, costPer1MOutput: 0.80, }, moderate: { model: 'claude-haiku-4.5', maxTokens: 2048, temperature: 0.5, costPer1MInput: 1.00, costPer1MOutput: 5.00, }, complex: { model: 'claude-sonnet-4.6', maxTokens: 4096, temperature: 0.7, costPer1MInput: 3.00, costPer1MOutput: 15.00, }, }; async function classifyComplexity(prompt: string): Promise<ComplexityLevel> { // Usar o modelo mais barato pra classificar — meta-otimização! const classification = await openai.chat.completions.create({ model: 'gpt-4.1-nano', max_tokens: 10, temperature: 0, messages: [ { role: 'system', content: `Classify the user query complexity. Respond with ONLY one word: - "trivial": greeting, yes/no question, simple lookup - "simple": single-step task, basic Q&A, formatting - "moderate": multi-step reasoning, comparison, analysis - "complex": creative writing, code generation, deep research Respond with the single classification word only.`, }, { role: 'user', content: prompt }, ], }); const level = classification.choices[0].message.content! .trim().toLowerCase() as ComplexityLevel; return MODEL_ROUTES[level] ? level : 'simple'; } async function routedQuery( prompt: string, systemPrompt: string ): Promise<{ response: string; model: string; cost: number }> { const complexity = await classifyComplexity(prompt); const route = MODEL_ROUTES[complexity]; const response = await callModel(route.model, systemPrompt, prompt, { maxTokens: route.maxTokens, temperature: route.temperature, }); const inputTokens = estimateTokens(systemPrompt + prompt); const outputTokens = estimateTokens(response); const cost = (inputTokens / 1_000_000) * route.costPer1MInput + (outputTokens / 1_000_000) * route.costPer1MOutput; return { response, model: route.model, cost }; }

O paradoxo do custo de classificação

"Pera — você tá fazendo uma chamada API extra só pra classificar. Isso não custa mais?"

Vamos às contas. A classificação usa GPT-4.1 nano com ~100 tokens input e ~5 output:

Custo de classificação por query:
  (100 / 1M) × $0.05 + (5 / 1M) × $0.20 = $0.000006

Sem routing (tudo pro Claude Sonnet 4.6):
  (500 / 1M) × $3.00 + (800 / 1M) × $15.00 = $0.0135

Com routing (40% Sonnet, 30% Haiku, 20% Mini, 10% Nano):
  = (0.4 × $0.0135) + (0.3 × $0.0045) + (0.2 × $0.00074) + (0.1 × $0.000185) + $0.000006
  = $0.0069 por query

Economia: 49% por query

O classificador se paga 1000 vezes. E isso é conservador.

Avançado: Routing com validação de qualidade e fallback

A versão mais esperta não só roteia — valida que o modelo barato deu um resultado aceitável:

async function routedQueryWithFallback( prompt: string, systemPrompt: string, qualityThreshold: number = 0.7 ): Promise<{ response: string; model: string; attempts: number }> { const complexity = await classifyComplexity(prompt); const route = MODEL_ROUTES[complexity]; const response = await callModel(route.model, systemPrompt, prompt, { maxTokens: route.maxTokens, }); // Pra rotas não complexas, verificar qualidade com check barato if (complexity !== 'complex') { const qualityScore = await quickQualityCheck(prompt, response); if (qualityScore < qualityThreshold) { // Escalar pro próximo tier const nextTier = getNextTier(complexity); const betterResponse = await callModel( MODEL_ROUTES[nextTier].model, systemPrompt, prompt, { maxTokens: MODEL_ROUTES[nextTier].maxTokens } ); return { response: betterResponse, model: MODEL_ROUTES[nextTier].model, attempts: 2 }; } } return { response, model: route.model, attempts: 1 }; }

Estratégia 3: Compressão de Prompts

A maioria dos prompts tá inchada. System prompts especialmente tendem a crescer com o tempo. Um prompt que começou com 200 tokens se infla pra 2,000 — e esse custo se multiplica a cada request.

Audite seus system prompts

Antes (847 tokens):

You are a helpful customer support assistant for our e-commerce platform.
You should always be polite and professional in your responses.
When a customer asks about their order, you should look up the order
details and provide them with relevant information about the status
of their order, including the tracking number if available...
(continua por mais 400 tokens)

Depois (189 tokens):

E-commerce support agent. Rules:
- Lookup order details, provide status + tracking if available
- If no access to order data, direct to support team
- Match customer's language
- Never reveal internal systems/pricing/employee info
- For frustrated customers: acknowledge → empathize → solve
- Tone: professional, warm, concise

Mesmo comportamento, 78% menos tokens. A 100,000 queries/mês com GPT-4.1 mini:

Economia de tokens: 658 tokens × 100,000 = 65.8M tokens/mês
Economia de custo: (65.8 / 1M) × $0.20 = $13.16/mês só no input

13/me^sparecepouco,masacumula.Com10featuresdeIAepromptsinchados,sa~o13/mês parece pouco, mas acumula. Com 10 features de IA e prompts inchados, são 130/mês — $1,560/ano — só de podar system prompts.

Compressão programática de prompts

Pra prompts dinâmicos que incluem contexto (RAG, histórico de conversa), comprima antes de enviar:

function compressConversationHistory( messages: Array<{ role: string; content: string }>, maxTokens: number = 2000 ): Array<{ role: string; content: string }> { const estimated = messages.reduce( (sum, m) => sum + estimateTokens(m.content), 0 ); if (estimated <= maxTokens) return messages; // Estratégia: manter primeira msg (contexto) e últimas N // Resumir as do meio const first = messages[0]; const last3 = messages.slice(-3); const middle = messages.slice(1, -3); if (middle.length === 0) return messages; const middleSummary = middle .map(m => `${m.role}: ${m.content.slice(0, 50)}...`) .join('\n'); return [ first, { role: 'system', content: `[Resumo da conversa: ${middleSummary}]`, }, ...last3, ]; }

A armadilha do token de saída

Lembra: tokens de saída custam 3-5x mais que os de entrada. Configurar max_tokens é a forma mais fácil de controlar custos:

// ❌ Ruim: Deixar o modelo se estender const response = await openai.chat.completions.create({ model: 'gpt-4.1-mini', messages: [{ role: 'user', content: 'Resume esse artigo' }], // Sem max_tokens = modelo decide o tamanho }); // ✅ Bom: Restringir tamanho da saída const response = await openai.chat.completions.create({ model: 'gpt-4.1-mini', messages: [{ role: 'user', content: 'Resume esse artigo em 3 frases.' }], max_tokens: 200, // Limite duro como rede de segurança });

Pra saídas estruturadas, use modo JSON com schemas — gera respostas consistente mais curtas e previsíveis:

const response = await openai.chat.completions.create({ model: 'gpt-4.1-mini', response_format: { type: 'json_schema', json_schema: { name: 'sentiment_analysis', schema: { type: 'object', properties: { sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] }, confidence: { type: 'number' }, keywords: { type: 'array', items: { type: 'string' }, maxItems: 5 }, }, required: ['sentiment', 'confidence', 'keywords'], }, }, }, messages: [{ role: 'user', content: `Analise: "${text}"` }], max_tokens: 100, });

Estratégia 4: Processamento Batch

Se seu workload não precisa de tempo real, batch APIs oferecem descontos pesados. A Batch API da OpenAI cobra 50% menos que chamadas real-time. Pra processamento em segundo plano — geração noturna de conteúdo, classificação em massa, enriquecimento de dados — é dinheiro grátis.

Quando usar batch

Precisa de tempo real:
  ✗ Chat com o usuário
  ✗ Autocompletar código ao vivo
  ✗ Busca interativa

Apto pra batch:
  ✓ Resumos noturnos de conteúdo
  ✓ Classificação em massa de emails
  ✓ Geração de relatórios semanais
  ✓ Rotulagem e enriquecimento de dados
  ✓ Backlog de moderação de conteúdo
  ✓ Lotes de tradução

Implementação

import { OpenAI } from 'openai'; import * as fs from 'fs'; const openai = new OpenAI(); interface BatchItem { custom_id: string; method: 'POST'; url: '/v1/chat/completions'; body: { model: string; messages: Array<{ role: string; content: string }>; max_tokens: number; }; } async function submitBatchJob( items: Array<{ id: string; prompt: string }>, systemPrompt: string, model: string = 'gpt-4.1-mini' ): Promise<string> { // 1. Criar arquivo JSONL const batchLines: string[] = items.map(item => { const batchItem: BatchItem = { custom_id: item.id, method: 'POST', url: '/v1/chat/completions', body: { model, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: item.prompt }, ], max_tokens: 1024, }, }; return JSON.stringify(batchItem); }); const filePath = `/tmp/batch-${Date.now()}.jsonl`; fs.writeFileSync(filePath, batchLines.join('\n')); // 2. Upload do arquivo const file = await openai.files.create({ file: fs.createReadStream(filePath), purpose: 'batch', }); // 3. Criar batch const batch = await openai.batches.create({ input_file_id: file.id, endpoint: '/v1/chat/completions', completion_window: '24h', }); return batch.id; } async function checkBatchStatus(batchId: string) { const batch = await openai.batches.retrieve(batchId); if (batch.status === 'completed') { const file = await openai.files.content(batch.output_file_id!); const text = await file.text(); const results = text .split('\n') .filter(Boolean) .map(line => JSON.parse(line)); return results; } return { status: batch.status, progress: `${batch.request_counts.completed}/${batch.request_counts.total}` }; }

Impacto nos custos

Pra um job noturno que processa 10,000 itens:

API real-time (GPT-4.1 mini):
  10,000 × (500 input + 800 output tokens)
  = (5M × $0.20 + 8M × $0.80) / 1M = $7.40

Batch API (50% desconto):
  = $3.70

Economia mensal: ~$111 (execução diária)
Economia anual: ~$1,332

Estratégia 5: Gateway LLM e Observabilidade

Não dá pra otimizar o que não se mede. Um gateway LLM fica entre sua aplicação e os provedores, te dando:

  • Atribuição de custo por feature — saiba qual feature tá queimando dinheiro
  • Retry automático e failover — se OpenAI cair, redireciona pra Anthropic
  • Rate limiting — previna custos descontrolados por bugs ou abuso
  • Analytics de uso — encontre oportunidades de otimização

Construindo um gateway leve

interface LLMRequest { featureId: string; prompt: string; systemPrompt: string; model?: string; maxTokens?: number; userId?: string; } interface LLMMetrics { featureId: string; model: string; inputTokens: number; outputTokens: number; cost: number; latencyMs: number; cached: boolean; timestamp: number; } class LLMGateway { private metrics: LLMMetrics[] = []; private rateLimiter: Map<string, { count: number; resetAt: number }> = new Map(); async query(request: LLMRequest): Promise<string> { // 1. Rate limiting this.enforceRateLimit(request.featureId); // 2. Checar orçamento await this.checkBudget(request.featureId); const startTime = Date.now(); // 3. Tentar semantic cache primeiro const cached = await queryWithSemanticCache( request.prompt, request.systemPrompt, request.model ); if (cached.cached) { this.recordMetrics({ featureId: request.featureId, model: request.model || 'gpt-4.1-mini', inputTokens: 0, outputTokens: 0, cost: 0, latencyMs: Date.now() - startTime, cached: true, timestamp: Date.now(), }); return cached.response; } // 4. Rotear pro modelo ótimo const result = await routedQuery(request.prompt, request.systemPrompt); // 5. Registrar métricas this.recordMetrics({ featureId: request.featureId, model: result.model, inputTokens: estimateTokens(request.prompt + request.systemPrompt), outputTokens: estimateTokens(result.response), cost: result.cost, latencyMs: Date.now() - startTime, cached: false, timestamp: Date.now(), }); return result.response; } getFeatureCosts(period: 'day' | 'week' | 'month'): Record<string, number> { const cutoff = { day: 86400000, week: 604800000, month: 2592000000, }[period]; const recent = this.metrics.filter( m => Date.now() - m.timestamp < cutoff ); return recent.reduce((acc, m) => { acc[m.featureId] = (acc[m.featureId] || 0) + m.cost; return acc; }, {} as Record<string, number>); } private enforceRateLimit(featureId: string) { const limit = this.rateLimiter.get(featureId); const now = Date.now(); if (limit && now < limit.resetAt && limit.count >= 1000) { throw new Error(`Rate limit exceeded for feature: ${featureId}`); } if (!limit || now >= limit.resetAt) { this.rateLimiter.set(featureId, { count: 1, resetAt: now + 60000 }); } else { limit.count++; } } private async checkBudget(featureId: string) { const monthlyCosts = this.getFeatureCosts('month'); const featureBudget = await getFeatureBudget(featureId); if ((monthlyCosts[featureId] || 0) >= featureBudget) { throw new Error( `Monthly budget exceeded for ${featureId}: $${monthlyCosts[featureId]?.toFixed(2)} / $${featureBudget}` ); } } private recordMetrics(metrics: LLMMetrics) { this.metrics.push(metrics); // Em produção: enviar pro seu pipeline de analytics } }

O dashboard que você precisa

No mínimo, rastreie isso por feature, por dia:

┌─────────────────────────────────────────────┐
│ Dashboard de Custos LLM - Março 2026       │
├──────────────┬────────┬────────┬────────────┤
│ Feature      │ Calls  │ Custo  │ Cache Hit  │
├──────────────┼────────┼────────┼────────────┤
│ Chat Suporte │ 45,231 │ $89.40 │    72%     │
│ Code Review  │ 12,847 │ $67.20 │    34%     │
│ Resumos      │  8,392 │ $12.10 │    81%     │
│ Busca        │ 31,094 │ $23.40 │    68%     │
│ Tradução     │  3,201 │  $8.90 │    45%     │
├──────────────┼────────┼────────┼────────────┤
│ Total        │100,765 │$201.00 │    63%     │
└──────────────┴────────┴────────┴────────────┘

 Mês anterior sem otimizações: $890
 Mês atual com todas as estratégias: $201
 Economia total: $689 (77%)

Juntando tudo: O stack de otimização

Essas estratégias se potencializam:

Request LLM chegando
        │
        ▼
  ┌─────────────┐
  │ Rate Limiter │─── Excedeu? → Erro
  └──────┬──────┘
         │
         ▼
  ┌──────────────┐
  │ Budget Check  │─── Excedeu? → Erro
  └──────┬───────┘
         │
         ▼
  ┌────────────────────┐
  │ Semantic Cache      │─── Hit? → Retorna cacheado
  └──────────┬─────────┘
             │ Miss
             ▼
  ┌────────────────────┐
  │ Compressão Prompt   │─── Reduzir tokens
  └──────────┬─────────┘
             │
             ▼
  ┌────────────────────┐
  │ Model Router        │─── Escolher o modelo mais barato que dê conta
  └──────────┬─────────┘
             │
             ▼
  ┌────────────────────┐
  │ API Call + Métricas │─── Registrar tudo
  └──────────┬─────────┘
             │
             ▼
  ┌────────────────────┐
  │ Cachear Resposta    │─── Guardar pra hits futuros
  └────────────────────┘

Economia combinada realista

Modelando uma aplicação real — assistente de documentação processando 200,000 queries/mês com Claude Sonnet 4.6 pra tudo:

Baseline (sem otimização):
  200,000 queries × 600 avg input × 1,200 avg output tokens
  Input: 120M tokens × $3.00/1M = $360
  Output: 240M tokens × $15.00/1M = $3,600
  Total: $3,960/mês

Com o stack completo:
  1. Semantic caching (70% hit rate): 140,000 queries eliminadas
     Restantes: 60,000 / Embeddings: $0.24 / Cache infra: $15/mês

  2. Routing do restante:
     - 15% complex → Claude Sonnet 4.6 (9,000 queries)
     - 25% moderate → Claude Haiku 4.5 (15,000 queries)
     - 40% simple → GPT-4.1 mini (24,000 queries)
     - 20% trivial → GPT-4.1 nano (12,000 queries)

  3. Compressão de prompts: 30% menos tokens

  Cálculo de custo:
     Sonnet: $124.74 / Haiku: $69.30
     Mini: $18.14 / Nano: $2.27
     Classificação: $0.36 / Cache infra: $15 / Embeddings: $0.24

  Total: ~$230/mês

  Economia: $3,730/mês (94% de redução)

De 3,960pra3,960 pra 230 por mês. São $44,760 por ano. Pra muitas startups, essa é a diferença entre ser rentável e ficar sem runway.

Erros comuns pra evitar

1. Cache sem invalidação

Respostas cacheadas ficam velhas. Se sua info mudou, o bot não deveria servir respostas de ontem. Implemente TTLs e cache busting manual quando o conteúdo mudar.

2. Routing excessivo pra modelos baratos

Se 5% dos seus usuários recebem respostas degradadas porque uma query foi mal classificada, você economizou grana mas perdeu confiança. Monitore quality scores e use o padrão de fallback descrito acima.

3. Comprimir demais

Tirar contexto pode degradar qualidade de formas sutis. Sempre faça A/B testing com métricas de qualidade antes de aplicar mudanças de prompt em produção.

4. Ignorar diferenças entre provedores

Cada provedor tem pontos fortes. Claude se destaca em análise longa. GPT-4.1 nano é imbatível pra classificação. Gemini Flash tem o melhor custo-benefício pra tarefas gerais. Não se prenda a um provedor só.

5. Esquecer dos custos de embeddings

Semantic caching precisa embeddar cada query. Em escala, acumula. Use text-embedding-3-small (não large) e faça batch dos embeddings quando possível.

Conclusão

Custos de API LLM não são leis da física — são problemas de engenharia com soluções de engenharia. As cinco estratégias desse guia — semantic caching, routing inteligente, compressão de prompts, batch processing e observabilidade — cortam seu gasto em 70-90% sem degradar a experiência do usuário.

Ordem de prioridade pra implementação:

  1. Semantic caching — maior ROI, implemente primeiro
  2. Compressão de prompts — ganho rápido, audite seus system prompts hoje
  3. Routing de modelos — economia significativa, complexidade moderada
  4. Observabilidade — precisa disso pra achar a próxima otimização
  5. Batch processing — economia fácil pra workloads em segundo plano

Comece com uma estratégia, meça o impacto e empilhe a próxima em cima. Na minha experiência, times que implementam as cinco passam de "precisamos de uma rodada só pra pagar a OpenAI" pra "nosso custo de LLM é erro de arredondamento."

Sua fatura de API não precisa assustar. Torna ela chata.

AILLMOpenAIAnthropiccost-optimizationsemantic-cachingprompt-engineeringTypeScript

Explore ferramentas relacionadas

Experimente estas ferramentas gratuitas do Pockit