ADR-0012 — Retenção de dados: histórico curado + coleta bruta comprimida
- Status: Aceito
- Data: 2026-07-18
Contexto
A fonte (Caixa) é volátil: preços mudam entre 1ª/2ª praça, imóveis são re-listados e desaparecem quando vendidos (ver RN-09). Precisamos decidir o que guardar, por quanto tempo e em que formato, sem inflar o banco à toa.
Dois artefatos são frequentemente confundidos, mas têm custo e propósito muito diferentes:
historico_preco— timeline curada e pequena: sóvalor,desconto_pct,statusecapturado_em, gravada apenas quando muda (RN-02). É a base de "baixou X%", alertas, tendência e auditoria de venda. Valor alto, custo baixo.coleta_bruta— payload cru (linha CSV ou HTML da página) para reprocessar/auditar. É o que realmente pesa (HTML de detalhe é grande e há um por imóvel).
Decisão
- Manter
historico_precocomo histórico curado (write-on-change, só preço/desconto/status). Retenção longa/indefinida — é barato e é parte do produto. - Não versionar todos os campos. Endereço, áreas, leiloeiro etc. não têm histórico próprio; se necessário, reconstrói-se a partir do
coleta_bruta. coleta_brutacomprimido: o payload é armazenado comobyteacomprimido com zstd (nível ~3–6) pelo coletor — não base64 (base64 é codificação e aumenta ~33%, não comprime). Metadados:payload_hash(SHA-256, integridade/dedup),compressao(zstd|gzip|none),tamanho_bytes. O Postgres ainda aplica TOAST por cima, mas comprimir na origem dá ratio muito melhor para HTML e evita reprocessar texto gigante.- Retenção do
coleta_bruta: manter 90 dias em banco (janela de reprocesso/depuração). Depois: descartar ou arquivar frio em object storage (MinIO/S3) — configurável. Purga porCronJob(DELETE ... WHERE coletado_em < now() - interval '90 days'). - Chaves
bigint: todas as PKs sãobigint GENERATED ALWAYS AS IDENTITY(ointestoura em ~2,1 bi; o custo debiginté irrisório e evita migração dolorosa no futuro).
Consequências
- + Banco enxuto: o que pesa (
coleta_bruta) tem retenção; o que é valioso e leve (historico_preco) fica. - + Reprocessamento continua possível dentro da janela de retenção;
payload_hashpermite dedup (não regravar coleta idêntica) e verificação de integridade. - + Compressão zstd reduz muito o storage do HTML bruto vs. texto puro ou base64.
- −
coleta_bruta.payload_brutodeixa de ser legível/consultável direto no SQL (ébyteacomprimido) — precisa descomprimir no app/ferramenta. Aceitável: é dado de auditoria, não de query. - − Retenção de 90 dias significa que reprocessar algo muito antigo exige recoleta (ou o arquivo frio). Trade-off consciente.
Alternativas consideradas
- Base64 no payload: rejeitado — infla o tamanho e não comprime; só faz sentido em transporte textual, não em storage.
jsonbpara o bruto: bom para consulta, mas o HTML não é JSON ejsonbnão comprime bem o texto cru — perde o propósito de "snapshot fiel". Rejeitado para o bruto.- TOAST/compressão nativa apenas (
text+ LZ4 do Postgres): simples, mas ratio pior que zstd na origem e ainda ocupa mais I/O. Mantido como camada complementar, não como única estratégia. - Guardar tudo para sempre: custo de storage cresce sem retorno proporcional — rejeitado.
- Versionar todos os campos (temporal table): complexidade alta e ruído; só rastreamos o que gera valor (preço/desconto/status) — rejeitado.