Headroom: o engenheiro da Netflix que decidiu cortar 90% dos teus tokens, e porque é que a mesma técnica nos dá mais contexto nos nossos LLM particulares.

Nota do autor: este post é para quem já percebeu que a conta da IA não vem da inteligência do modelo, vem da quantidade de tralha que lhe atiramos para cima. Se ainda achas que “context window de 2 milhões de tokens” é uma feature e não uma armadilha de faturação, senta-te e lê na mesma. No fim, prometo, há receita para pôr isto a trabalhar no homelab. E sim, o post foi escrito com ajuda de um LLM particular.

Olá a todos!

Apareceu esta semana no The Register uma daquelas notícias que à primeira vista parece mais uma startup a vender pás durante a corrida ao ouro, mas que quando raspas a tinta tem mais miolo do que aparenta. O título é provocador à maneira deles: um “wiz” da Netflix criou uma app para cortar as faturas de IA e depois abriu o código. O projecto chama-se Headroom, e a história de como nasceu é, francamente, a história de metade das pessoas que leem este blog.

O autor é o Tejas Chopra, engenheiro sénior na Netflix. O Headroom não é um projecto oficial da Netflix, mas há várias equipas lá dentro que já o usam, e há projectos externos a depender dele. E o gatilho de tudo, segundo o próprio, foi uma fatura de 287 dólares do Claude Sonnet. Uma conta de projecto de fim de semana: um bocado de debugging, uns refactors, umas ferramentas MCP a martelar uma base de dados. Nada de exótico. E mesmo assim, 287 dólares a evaporarem-se.

A maioria das pessoas paga e segue em frente. O Chopra fez o que qualquer engenheiro com sangue na guelra faria: foi ver para onde é que o dinheiro estava a ir. E o que encontrou é o tema central deste post.

O problema: estamos a pagar para enviar lixo aos modelos

Quando o Chopra abriu o capô daquela conta, a conclusão foi cirúrgica. As instruções que ele próprio tinha escrito à mão quase não pesavam. O que pesava era tudo o resto: schemas de JSON desnecessariamente verbosos, templates aninhados dentro de respostas de API, colunas de base de dados idênticas repetidas vezes sem conta, metadata de máquina que viaja agarrada aos dados como lapas. A frase dele resume tudo, e vou traduzi-la à letra porque é boa demais para parafrasear mal: isto não é prosa, não é escrita criativa, é dados compressíveis disfarçados de texto.

Ele estima que até 90% dos tokens que mandamos para o modelo são redundantes. Noventa por cento. E não está sozinho nesta conta: um grupo de investigadores concluiu em 2025 que a leitura do input do utilizador representa cerca de 76% de todo o consumo de tokens. Ou seja, a fatia gigante da fatura não é o modelo a pensar nem a responder. É o modelo a ler a porcaria que lhe enfiámos pela goela abaixo.

E aqui está a parte que muita gente ignora porque está demasiado ocupada a olhar para o cifrão: enviar lixo não é só caro, é contraproducente. Há investigação de Stanford a mostrar que os LLMs prestam mais atenção ao início e ao fim da janela de contexto e tendem a ignorar o meio. Há um grupo da Chroma que analisou 18 modelos diferentes e cunhou um termo que devias gravar a fogo: “context rot”, a degradação do desempenho à medida que o input cresce. Traduzindo para português de homelab: quanto mais entopes a janela de contexto, mais burro o modelo fica. Pagas mais para teres pior resposta. É o pior negócio do mundo, e fazemo-lo todos os dias sem dar conta.

O que é o Headroom, sem o canva do costume

Vamos ao que interessa. O Headroom é uma camada de compressão de contexto que se mete entre a tua aplicação e o LLM. Comprime tudo o que o teu agente lê (histórico de conversa, logs, outputs de ferramentas, ficheiros, os chunks que o RAG decidiu que eram relevantes) antes de isso chegar ao modelo. A promessa que vem escrita no repositório é de 60 a 95% menos tokens com as mesmas respostas. Licença Apache 2.0, escrito maioritariamente em Python com uma boa fatia de Rust por baixo, local-first, e reversível. Guarda bem esta última palavra, que é a que faz toda a diferença. Nota-se que estou a fazer dieta de novo não?

Os números que o Chopra apresentou na talk do Open Source Summit são daqueles que fazem levantar a sobrancelha: o Headroom já terá poupado cerca de 700 mil dólares aos seus utilizadores, que ficaram com algo na ordem das centenas de milhares de milhões de tokens para gastar noutro sítio. O projecto está disponível desde Janeiro, vai na versão 0.22 (ainda cru, e o próprio admite isso), e já passou das milhares de stars no GitHub à data em que escrevo, com centenas de forks. Para uma ferramenta com meses de vida, é tracção a sério.

A forma de o usar é desarmantemente simples e tem vários sabores, o que é precisamente o que me agrada:

  • Como biblioteca: chamas compress(messages) em Python ou TypeScript, inline, dentro da tua app.
  • Como proxy: corres headroom proxy --port 8787 e apontas o teu cliente para lá. Zero mudanças no código, funciona com qualquer linguagem.
  • Como wrap de agente: headroom wrap claude (ou codex, cursor, aider, copilot) e está feito.
  • Como servidor MCP: expõe headroom_compress, headroom_retrieve e headroom_stats para qualquer cliente MCP.

Repara num detalhe que para mim é decisivo: tudo isto corre localmente, na tua máquina. Os teus dados não vão dar uma voltinha por um serviço de terceiros para serem “comprimidos” e depois devolvidos. Ficam em casa. Para quem me lê há algum tempo, sabe que este é exactamente o tipo de arquitectura que me faz dormir descansado.

Como funciona por dentro, e porque é que isto não é um gzip com esteróides

Aqui é onde a engenharia fica bonita. O Headroom não faz uma compressão burra do tipo “tira metade das letras e reza”. Faz um pipeline com etapas que percebem o que estão a comprimir.

A primeira peça chama-se CacheAligner, e é a mais subtil de todas. As fronteiras (Anthropic, OpenAI) têm KV caches do lado delas: se o início do teu prompt for igual ao da chamada anterior, elas reutilizam o trabalho e cobram-te uma fracção. O problema, nas palavras do Chopra, é que se o teu system prompt tiver um campo de data ou um UUID que muda a cada sessão, estás efectivamente a apanhar um cache miss de cada vez. E isso, cito, faz explodir os teus custos. O CacheAligner estabiliza os prefixos e envia só aquilo que mudou, para que o cache do fornecedor acerte de verdade em vez de te cobrar tudo outra vez.

Depois entra o ContentRouter, que cheira o tipo de conteúdo e despacha-o para o compressor certo. Código vai para o CodeCompressor, que é AST-aware (entende a árvore de sintaxe de Python, JS, Go, Rust, Java, C++) e não anda a cortar à toa. JSON vai para o SmartCrusher, que sabe lidar com arrays de dicts, objectos aninhados e tipos misturados. Prosa vai para o Kompress-base, um modelo próprio publicado na HuggingFace, treinado em traces de agentes reais. Há ainda “squashers” estatísticos que decidem que pedaços de texto ou JSON são de facto relevantes, e que aprendem num feedback loop se estão a comprimir de mais ou de menos, com base na frequência com que o modelo tem de ir buscar o original.

E chegamos à jóia da coroa: o CCR, ou Compress Cache and Retrieve. Esta é a tal reversibilidade que mencionei. O Headroom não deita fora os originais. Comprime, mete um marcador onde cortou, e guarda o material intacto localmente (em Redis ou SQLite). Se o modelo, a meio do raciocínio, decidir que precisa do pedaço completo que foi comprimido, chama uma ferramenta MCP do Headroom e vai buscá-lo. Isto muda completamente a equação de risco. A compressão é, por natureza, com perdas (lossy). Mas com o CCR tens uma rede de segurança: o detalhe não desaparece do universo, fica em pausa, à distância de uma chamada. É a diferença entre rasgar uma página e dobrá-la.

Os benchmarks que o repositório publica sustentam a tese de “mesmas respostas”. No GSM8K (matemática) a accuracy fica exactamente igual, 0.870 contra 0.870. No TruthfulQA até sobe ligeiramente. No SQuAD mantém 97% com 19% de compressão, e no BFCL (uso de ferramentas) 97% com 32%. E nos workloads reais é onde se vê o dinheiro: uma pesquisa de código de 17.765 tokens cai para 1.408 (92% menos), um caso de debugging de SRE de 65.694 desce para 5.118 (também 92%), e por aí fora. O demo do repositório mostra 10.144 tokens a comprimirem para 1.260, e o tal “FATAL” do log continua lá, encontrado na mesma. Que é o que interessa: poupar tokens sem perder o sinal.

A parte de que quase ninguém fala: isto é ouro para o teu LLM local

Toda a cobertura do Headroom, incluindo a do The Register, está focada no ângulo óbvio: poupar dinheiro nas APIs de frontier. E está certíssima. Mas há um segundo ângulo, muito mais interessante para quem corre modelos em casa, que ninguém parece estar a explorar. E é por isso que decidi escrever sobre isto.

Pensa no que limita um LLM local. Não é só o tamanho do modelo. É a janela de contexto. E a janela de contexto, em hardware pessoal, tem um custo brutal que muita gente esquece: o KV cache. À medida que enches a janela com tokens, o KV cache cresce de forma mais ou menos linear com o comprimento da sequência, e devora VRAM. Num cenário típico de homelab, um contexto longo pode comer tanta ou mais memória do que os próprios pesos do modelo. É por isso que corres um modelo lindo de 8k ou 32k de contexto e, quando lhe atiras um repositório inteiro ou meia dúzia de logs, ou rebenta com out-of-memory, ou abranda até parecer melaço.

Agora junta dois e dois. Se o Headroom comprime o input em 60 a 90% antes de ele chegar ao modelo, o que estás de facto a fazer é multiplicar a quantidade de informação útil que cabe na mesma janela. Uma janela de 32k tokens passa a conseguir carregar o conteúdo informativo de 100k, 200k, às vezes 300k tokens de logs, JSON e código em bruto. Não aumentaste a janela. Aumentaste a densidade do que lá meteste. É a diferença entre encher uma mala com a roupa atirada à pressa e enchê-la com tudo enrolado e organizado: a mala é a mesma, mas levas o triplo.

E os ganhos não param aí. Menos tokens no input significam menos prefill para o modelo mastigar, ou seja, time-to-first-token mais rápido e menos pressão de memória. Na prática, isto traduz-se em três coisas concretas para quem tem uma RTX a fazer das suas: ou corres o mesmo modelo com contexto efectivo muito maior, ou corres um modelo maior no mesmo hardware porque sobra VRAM que estava a ser desperdiçada em tralha, ou simplesmente tens respostas mais rápidas. As três opções são vitórias.

O CCR, que para o utilizador de API é uma rede de segurança contra cortes agressivos, no homelab transforma-se em algo ainda mais poderoso: uma memória de trabalho paginada e local. O modelo pequeno mantém na janela só o destilado, o essencial, e quando precisa do detalhe completo vai buscá-lo ao Redis ou ao SQLite que está a correr na tua própria máquina. É, no fundo, dar a um modelo de contexto curto a sensação de ter uma memória enorme, sem pagar o preço em VRAM por isso. Quem leu o meu post sobre o OpenMythos vai reconhecer o padrão: não é “mais parâmetros”, é arquitectura mais esperta. Aqui a versão é “não é mais janela de contexto, é contexto mais denso”.

E há um bónus que liga directamente ao “context rot” de que falei lá em cima. Os modelos pequenos sofrem ainda mais com o lixo no contexto do que os grandes. Um modelo de 7B ou 13B distrai-se com uma facilidade impressionante quando lhe enches o meio da janela com boilerplate. Ao comprimir o input para só o que importa, não estás apenas a poupar memória: estás a dar ao teu modelo local uma hipótese real de prestar atenção ao que interessa. Comprimes a fatura e melhoras a resposta ao mesmo tempo. É raro na engenharia conseguir as duas coisas de uma vez.

A receita para o homelab

Certo, sócio. Vamos pôr as mãos na massa. A boa notícia é que o Headroom foi desenhado precisamente para se intrometer em qualquer stack sem dramas, e os blocos que provavelmente já tens no homelab encaixam que nem uma luva.

O plano é simples: tens o teu motor de inferência local (Ollama, vLLM ou llama.cpp), metes o Headroom à frente como proxy ou como callback, e apontas o teu agente ou cliente para lá. Nada sai da rede local.

Passo 1, instalar o Headroom. Precisas de Python 3.10 ou superior.

# Python, com tudo
pip install "headroom-ai[all]"

# Ou via Docker
docker pull ghcr.io/chopratejas/headroom:latest

Passo 2, levantar o teu motor local. Se ainda não tens, o Ollama resolve isto em segundos:

curl -fsSL https://ollama.ai/install.sh | sh
ollama pull qwen2.5:14b      # ou o que a tua VRAM aguentar

Passo 3, meter o Headroom no meio. A forma mais limpa, e que não exige tocar no código de nada, é o proxy:

headroom proxy --port 8787

A partir daqui, qualquer cliente compatível com a API da OpenAI pode falar com o proxy do Headroom, que comprime e reencaminha. Se o teu agente for um dos suportados, ainda mais directo:

headroom wrap claude        # ou codex, cursor, aider, copilot

Passo 4, para quem já vive no LiteLLM. Eu já aqui falei do LiteLLM como camada de orquestração entre modelos locais e APIs externas, e a boa notícia é que o Headroom integra-se com ele via callback. Isto é praticamente plug-and-play:

import litellm
from headroom.integrations.litellm import HeadroomCallback

litellm.callbacks = [HeadroomCallback()]
# A partir daqui, tudo o que passa pelo LiteLLM é comprimido
# antes de chegar ao modelo, seja ele local ou remoto.

Passo 5, a interface. Por cima de tudo isto, o Open WebUI dá-te uma interface de chat decente em cinco minutos com um docker compose, a apontar para o Ollama. O resultado final é um stack completo: Ollama a servir o modelo, Headroom a comprimir o contexto, LiteLLM a balancear, Open WebUI a dar a cara. E o ponto que mais me agrada repito-o porque merece: nem um byte sai da tua rede. Comprimes em casa, serves em casa, guardas os originais em casa.

Passo 6, ver a poupança. Não acredites em mim, mede:

headroom stats

Erm… publicidade gratuita?

Antes que alguém me acuse de estar a fazer publicidade, vamos à parte de review, que é a que dá credibilidade a tudo o resto.

Primeiro: o Headroom está na versão 0.22 e o próprio autor admite que ainda há trabalho a fazer, sobretudo em testes de precisão. A compressão é com perdas. O CCR existe precisamente porque o sistema pode, num caso ou outro, cortar algo que afinal fazia falta, e a aposta é que o modelo o consiga ir buscar a tempo. Na esmagadora maioria dos casos funciona, mas “esmagadora maioria” não é “sempre”, e há cargas de trabalho onde vais querer testar com cuidado antes de confiar cegamente.

Segundo: o Headroom brilha em logs, JSON, outputs de ferramentas, árvores de ficheiros, dados estruturados, ou seja, naquilo que é “dados disfarçados de texto”. Em prosa pura e escrita criativa os ganhos são modestos, porque aí não há redundância estrutural para espremer. Se o teu uso é maioritariamente conversa em linguagem natural, baixa as expectativas.

Terceiro: o compressor de texto baseado em ML (o Kompress-base) precisa do extra [ml] e consome alguns recursos. No homelab isto é uma troca a pensar: gastas um bocado de compute a comprimir para poupares muito mais compute e VRAM no modelo grande. Quase sempre compensa, mas é uma conta que deves fazer para o teu hardware, não assumir.

E quarto, o detalhe filosófico: por muito que o The Register tenha posto “lossless” num subtítulo, sejamos rigorosos, isto não é compressão sem perdas no sentido do gzip. É compressão com perdas e uma rede de recuperação. A magia não está em não perder nada, está em perder só aquilo que provavelmente não fazia falta, e em poder desfazer o engano. É uma distinção importante para gerires expectativas.

Porque é que isto encaixa na tese deste blog

Se andas por aqui, já percebeste o padrão. Os grandes labs adoram que acreditemos que o caminho é sempre “mais”: mais parâmetros, mais janela de contexto, mais GPUs, mais fatura. E eu já aqui escrevi, mais do que uma vez, sobre o que acontece quando dependemos disso, desde a Anthropic a cortar a ração de chocolate até aos developers a fugirem do Copilot por causa do billing por consumo, que aliás saiu no mesmo dia que esta notícia.

O Headroom é a prova de que existe outro eixo. Em vez de comprar mais janela, espremes a que tens. Em vez de mandar tudo para a cloud para ser “tratado”, tratas em casa. E o mais bonito é que a mesma técnica que poupa milhares de dólares a uma equipa da Netflix nas APIs de frontier é exactamente a que te dá fôlego no LLM local que corre na tua cave. É o mesmo princípio dos posts anteriores sobre modelos locais: tamanho não é diploma, e janela de contexto não é inteligência. O que conta é a engenharia que decide o que merece estar lá dentro.

A independência tecnológica não é paranoia, é prudência de engenharia. E ferramentas como o Headroom são exactamente o tipo de tijolo que torna essa independência prática em vez de teórica. Local-first, reversível, código aberto, e a resolver um problema real que toda a gente tem mas poucos param para medir.

Espero que tenham gostado do post. Como sempre, estejam à vontade para me contactar se já andaram a brincar com o Headroom, especialmente se o puseram à frente de modelos locais e mediram o ganho de contexto efectivo. Esse é o tipo de número que ainda quase ninguém partilhou, e é onde acho que está a parte mais interessante desta história. Se alguém tiver resultados de campo, mande, que faço a continuação com dados reais.

Abraço!
Nuno

Links úteis:

  • Headroom no GitHub: https://github.com/chopratejas/headroom
  • Documentação do Headroom: https://headroom-docs.vercel.app/docs
  • Kompress-base na HuggingFace: https://huggingface.co/chopratejas/kompress-base
  • Artigo do The Register que motivou este post: https://www.theregister.com/ai-ml/2026/05/31/netflix-wiz-creates-app-to-slash-ai-bills-then-open-sources-it/5248702
  • Post original do Tejas Chopra sobre o Headroom: https://tejaschopra.substack.com/p/headroom-llm-cost-savings
  • Investigação sobre “context rot” da Chroma: https://www.trychroma.com/research/context-rot
  • Ollama: https://ollama.ai
  • Open WebUI: https://github.com/open-webui/open-webui