Muito bom o post.
O que eu mais gostei é que não ficou naquela ladainha de “Go é rápido” como se a linguagem fosse fazer milagre sozinha.
Pra mim o ponto forte aí é outro: você respeitou o caminho dos dados.
Em problema desse tamanho, a galera geralmente quer começar pelo final: cache, Redis, fila, microsserviço, arquitetura bonita no desenho. Aí vai ver o básico está errado: INSERT linha por linha, arquivo gigante carregado inteiro em memória, encoding tratado de qualquer jeito, índice ruim, parse frágil e banco apanhando por culpa da aplicação.
Go encaixa bem nesse tipo de problema justamente porque ele não tenta ser mágico. Lê stream, valida, transforma, joga no Postgres com COPY e segue. É simples, previsível e bruto no bom sentido.
Mas acho que a parte mais importante é: responder em 10ms é bonito, mas responder a base certa é mais importante.
Com dump mensal da Receita, eu teria paranoia com ingestão. Não trataria isso só como “rodei o importador e funcionou”. Eu colocaria validação pesada no processo: versão da base carregada, quantidade de linhas lidas, linhas rejeitadas, checksum dos arquivos, detecção de mudança de layout, carga em staging e só depois swap para a base final.
Porque performance em cima de dado errado é só mentira rápida.
Também gostei da parte de não cair automaticamente em denormalização. “Tabela larga é mais rápida” parece técnico, mas muitas vezes é só chute com confiança. Antes de duplicar dado e aumentar custo de rebuild mensal, tem que medir com EXPLAIN ANALYZE, consulta real e índice real.
E Redis nesse caso também precisa pagar aluguel. Se a tabela auxiliar é pequena, Postgres provavelmente já resolve bem, ou até um map em memória no boot da API. Colocar Redis para economizar lookup barato pode ser só adicionar mais uma peça para quebrar.
No fim, o que eu achei mais forte no projeto foi isso: pouca firula, pipeline streaming, Postgres bem usado e benchmark com número.
Go ajudou, claro. Mas o que ganhou o jogo foi não fazer burrice no caminho quente.