
Migração do Firestore para SQL só ficou rápida ao mover a agregação ao servidor
Trocar o banco não mudou a página lenta
Uma plataforma interna de currículos saiu do Firestore e foi para o PostgreSQL, por meio do Firebase SQL Connect. Dois dias depois, a página de agregação que motivou a troca ainda baixava 18,6 MB e ficava travada por cerca de 55 segundos, com 41 requisições para rotular nomes, a maioria chamadas a um LLM. A página carregava todo o corpus de currículos visíveis para o gestor e agregava os dados no navegador. Como o navegador não sabe qual banco está por trás, a migração, sozinha, não alterou esse fluxo.
Por que o Firestore Standard não resolvia a agregação
Segundo o texto, as consultas de agregação do Firestore Standard (count, sum e average) retornam um único valor por consulta, não um valor por grupo. Um detalhamento por grupo exigiria uma agregação por grupo, o que obriga a conhecer antes a lista de grupos. Também não há joins, e a cobrança é por documento lido. Seria possível construir um modelo derivado no próprio Firestore, com a lista aninhada espalhada em uma coleção própria, mas isso traria custos de escrita, cópias desatualizadas e muitas leituras.
O Firestore Enterprise, cujas operações de pipeline chegaram à disponibilidade geral em 20 de abril de 2026, oferece agregação agrupada e joins. O autor afirma que ele provavelmente resolveria o caso, mas não o avaliou, e por isso não faz uma comparação com o PostgreSQL.
O que foi feito de fato
A solução foi uma tabela derivada, com uma linha por item de cada lista aninhada, gerada a cada salvamento de currículo. Um endpoint no servidor consulta essa tabela pela janela de datas escolhida, usando uma condição de sobreposição: conta a linha que começou antes do fim da janela e que não tinha terminado quando a janela começou, tratando as linhas sem data final como ainda em andamento. O rótulo canônico é resolvido uma vez, no salvamento, e guardado na linha. A leitura não agrupa nem chama o modelo de linguagem.
O SQL Connect foi escolhido, em parte, porque mantém o Firebase Auth, que já sustentava sessões, middleware e regras de acesso. Mover dados e autenticação ao mesmo tempo seria duas migrações difíceis de uma vez.
Há custos declarados. A instância Cloud SQL fica sempre ligada e é cobrada mesmo sem uso, o que o autor aceitou para uma ferramenta interna com carga previsível em dias úteis. A escrita no pior caso ficou em 15 operações no SQL Connect, contra 106 gravações de documentos no Firestore, medidas nos emuladores.
Resultados medidos
As medições foram feitas em produção, com uma execução cada, sem limitação de banda. Em filtros de janela com a página aberta, os tempos passaram de 10,2 s para 2,8 s em um ano, de 29,1 s para 3,4 s em cinco anos e de 56,0 s para 3,7 s em dez anos. As requisições caíram de 31 para 1 no caso de dez anos. O bloqueio da thread principal em dez anos caiu de cerca de 55,7 s para 542 ms. O corpus da caixa de busca foi de 18,27 MB para 1,63 MB.
Há ressalvas. A regressão de DOMContentLoaded na página de agregação, de 2,5 s para 3,7 s, não foi explicada pelo autor. O tempo até o primeiro byte é de 62 ms, então o problema não está no servidor. A busca vetorial deve ser melhor com índice HNSW, mas não foi medida em produção.
Lições e o que ficou pendente
O autor afirma que é preciso planejar tabelas derivadas, leituras no servidor e índices como parte da migração, no mesmo pull request, e medir tudo junto. Também relata quatro bugs que passaram despercebidos porque as contagens de linhas batiam. Um deles: vetores do Firestore não são reconhecidos por Array.isArray, e a checagem pulou silenciosamente os 6.500 embeddings. Outro: toISOString().slice(0, 10) converte para UTC, e uma data de 1 de maio à meia-noite em Amsterdã foi gravada como 30 de abril.
O trabalho não terminou. A página /overview, para gestores, ainda baixa todo o corpus visível, agora com 22,98 MB decodificados, porque os indicadores são calculados no navegador. Ela é hoje a página mais lenta do aplicativo, com 6,5 s. A consulta no servidor que resolveria isso é possível desde a troca, mas ainda não foi escrita.
A conclusão do texto é que uma migração de banco não torna nada mais rápido por si só. Ela muda quais consultas podem ser escritas, e o ganho depende de escrever essas consultas.