500 pessoas online. Banco offline. A história de como quase perdi a Git City.
A Git City é uma cidade 3D onde cada prédio representa um dev do GitHub. Altura = commits, largura = repos, janelas acesas = atividade recente. Hoje são mais de 60 mil prédios.
Mas teve uma semana em que quase perdi tudo. O banco caiu duas vezes.
Como funcionava
No começo eu carregava a cidade em chunks de 1.000 prédios. Cada usuário que abria o site disparava uma série de requests em paralelo:
GET /api/city?chunk=1 → 1.000 prédios
GET /api/city?chunk=2 → 1.000 prédios
GET /api/city?chunk=3 → 1.000 prédios
...
Com 10 mil devs na cidade, eram 10 requests por usuário. Funcionava perfeitamente.
O dia que explodiu
De um dia pro outro, a Git City viralizou. Saiu de 12 mil pra 30 mil devs. E com a viralização, vieram os acessos simultâneos.
- 30K prédios na cidade
- 500 pessoas online ao mesmo tempo
- 30 requests por usuário
Faz a conta: 500 x 30 = 15.000 queries simultâneas no banco.
O Supabase não aguentou. Banco fora do ar. Cidade offline. Ninguém conseguia acessar.
A tentativa "certa"
Minha primeira reação foi fazer o que qualquer dev faria: criei uma RPC no Postgres que retornava todos os 30 mil devs em uma única query. Menos requests, menos overhead, certo?
Errado. Piorou. A query era pesada demais, o banco travou e caiu de novo.
Duas quedas na mesma semana.
A solução mais simples
Depois de quebrar a cabeça, percebi que o problema real era outro: eu não precisava que cada usuário consultasse o banco. A cidade não muda a cada segundo. Os dados mudam quando alguém faz um commit no GitHub, não quando alguém abre o site.
A solução:
- Um cron roda a cada 5 minutos e gera um snapshot da cidade inteira
- O snapshot é salvo como arquivo estático no Supabase Storage
- A Vercel faz cache na edge e serve pra todo mundo
Resultado: zero queries no banco, não importa se tem 1 ou 10 mil pessoas online. A cidade carrega em 2 segundos.
Mas aí veio outro problema
Com 60 mil prédios, o snapshot JSON ficou grande. Muito grande. 54 MB.
O Supabase Storage tem um limite padrão de 50 MB por arquivo. O upload passou a falhar silenciosamente e a cidade ficou desatualizada sem eu perceber.
A solução? Uma linha de código.
Gzip. Compacta no servidor antes de salvar, descompacta no navegador quando carrega. De 54 MB pra 4 MB. O usuário nem percebe.
O que eu aprendi
Quando o banco caiu pela primeira vez, meu instinto foi criar uma solução mais sofisticada (a RPC). Quando isso piorou tudo, eu parei e pensei no problema real.
A resposta não era uma query mais inteligente. Era não fazer query nenhuma.
A solução mais simples resolveu tudo:
- Um cron de 5 minutos
- Um arquivo estático
- Cache na edge
- Gzip quando ficou grande demais
Nem sempre a solução mais complexa é a melhor. Na maioria das vezes, a mais simples resolve.
A Git City é open source. Se quiser ver seu prédio na cidade, é só conectar o GitHub.