13 — logs_transacoes: a tabela que cresce mais rápido que tudo
Pergunta: o sistema de logging em si é auto-escalável?
logs_transacoesé a tabela com maior taxa de inserção da plataforma — quando ela vira o gargalo?
Por que isso é diferente das outras
logs_transacoes recebe um INSERT por CUD em qualquer parte da plataforma (cf. mem://architecture/observability-and-logging-standard). Crescimento real:
- 1 escola média: ~500 CUDs/dia → ~15k/mês.
- 100 escolas: 1.5M/mês → 18M/ano.
- Sem retenção/particionamento, a tabela ultrapassa 50M em < 3 anos.
Quem lê
10 edge functions diferentes consultam logs_transacoes:
admin-dashboard admin-cron-monitor maintenance-cron
admin-comunicacao verify-password user-profile
admin-logs healthcheck-cron admin-financeiroA tela admin-logs é o consumer mais intenso (filtros por módulo + intervalo de data + escola + usuário).
Riscos por camada
Escrita (fire-and-forget)
Padrão atual (cf. mem) é EdgeRuntime.waitUntil(insert). Bom — não bloqueia Response. Mas:
- Sob pico de CUD (importação de 5k alunos), gera 5k INSERTs em poucos segundos.
pg_stat_statementsvai mostrarINSERT INTO logs_transacoescomo o top query.- Hipótese: já estamos perto do limite de I/O de write em escolas de pico.
Leitura
admin-logsfiltra por(escola_id, created_at desc)+modulo— precisa índice composto, ver 09.- Filtros JSONB em
payload/diffsão caros — confirmar GIN index se forem usados.
Retenção
Não há job de retenção/arquivamento visível. Toda linha vive para sempre.
- LGPD: logs com PII (já mascarada — cf.
mem://security/pii-log-masking-standard) ainda assim devem ter TTL. - Performance: particionar por mês (
PARTITION BY RANGE (created_at)) reduz custo de scan e permiteDROP PARTITIONantigo barato.
Hipóteses
- H1:
admin-logsem prod já demora >2s para abrir — não por falta de índice em si, mas por size of relation (table bloat sem retenção). - H2: Inserções em pico de importação contribuem para latência fora do Resultados, percebida como "geral lenta" — efeito sistêmico.
- H3: A próxima crise de performance vai ser
admin-logs, não Resultados.
Padrão recomendado (proposta, sem implementar)
- Particionamento mensal de
logs_transacoesporcreated_at(estratégiapg_partmanou nativa). - Retenção de 12 meses online + arquivamento (S3/storage) para meses anteriores.
- Índice composto
(escola_id, modulo, created_at desc). - Quota por escola opcional (não emitir log de cada PATCH trivial — gatilhar só CUD com impacto).
- Sampling em ações de altíssima frequência (
page_view,heartbeat) — não logar 100%.
Próximas etapas (auditoria, não fix)
- Medir tamanho atual da tabela:
select pg_size_pretty(pg_total_relation_size('public.logs_transacoes')). - Top 10 ações por contagem em 30 dias:
select acao, count(*) from logs_transacoes where created_at > now() - interval '30 days' group by 1 order by 2 desc limit 10. - Verificar se há índice em
created_atsimples (não composto):select indexdef from pg_indexes where tablename = 'logs_transacoes'.
Links
mem://architecture/observability-and-logging-standardmem://security/pii-log-masking-standard- 09 — Índice e EXPLAIN baseline