Expiração por design: construa TTLs globais para os dados do seu SaaS antes que os reguladores o façam

Por Diogo Hudson Dias
Platform engineer in a São Paulo office reviewing S3 lifecycle settings with a dashboard of data deletion metrics visible on the wall

OneDrive acabou de colocar uma data de expiração em arquivos. Isso não é um recurso — é uma admissão: os dados que você mantém são os dados que você vai perder. Depois de 1.000+ violações e atrasos de divulgação cada vez maiores, acumular dados de clientes deixou de ser uma decisão neutra; virou passivo. Se o seu SaaS ainda depende de “soft delete” e backups sem limite, você está a uma intimação, a uma quadrilha de ransomware ou a um bucket mal configurado de um incidente evitável.

Este post é um playbook para CTOs implementarem expiração por design: políticas globais de time-to-live (TTL) com SLOs de deleção, legal holds e recibos auditáveis em todos os repositórios que você toca — OLTP, blob, busca, analytics, logs, backups e fornecedores. Você vai receber um plano de 30-60-90 dias e orientações de implementação concretas para Postgres, S3, Elasticsearch, Kafka, BigQuery/Snowflake e sistemas de backup — além dos trade-offs que você precisa encarar como líder de engenharia.

Por que expiração por design agora

  • As violações continuam, os atrasos de divulgação pioram. Contagens públicas mostram divulgações mais lentas, não mais rápidas. Isso significa mais dados obsoletos expostos por mais tempo. A única forma de reduzir o raio de impacto é armazenar menos e por menos tempo.
  • Os fornecedores estão se movendo primeiro. O OneDrive da Microsoft adicionando expiração de arquivos é um sinal: os clientes agora esperam controles de retenção. Se seu app não acompanha, você vai perder negócios para concorrentes mais maduros em segurança.
  • Os reguladores já escreveram as regras. GDPR Art. 5(1)(e) (limitação de armazenamento) e Art. 17 (eliminação), LGPD do Brazil Arts. 15–16 e leis estaduais de privacidade convergem: mantenha apenas o necessário, apenas pelo tempo necessário — e prove isso.
  • IA aumenta a penalidade de acumular. Janelas de contexto e stores vetoriais espalham texto/imagens sensíveis por todo lado. Mesmo com “Lockdown Modes”, a defesa mais segura é não ter os dados em primeiro lugar.

O framework de decisão: cinco escolhas difíceis

Antes de escrever uma linha de código, você precisa de respostas claras para:

1) Classes de objetos e retenção padrão

Todo byte mapeia para uma classe de objeto com um TTL padrão. Comece com uma taxonomia simples e ajuste depois:

  • Eventos/métricas operacionais: 7–30 dias
  • Logs/traces do produto: 14–60 dias
  • Mensagens/comentários de usuários finais: 90–365 dias
  • Anexos/envios de arquivos: 90–365 dias
  • Registros transacionais (pedidos, faturas): por contrato/lei fiscal (geralmente 3–7 anos)
  • Logs de auditoria/segurança: 365–730 dias (ou conforme SOC2/ISO)

Transforme isso em padrões por tenant, com limites por plano. SMBs normalmente aceitam 90–180 dias; enterprise vai pedir 7 anos e legal hold. Precifique de acordo.

2) SLOs de deleção e seu “budget de expiração”

Faça um compromisso de SLO interno para a velocidade com que os dados somem após se tornarem elegíveis:

  • p95 time-to-hard-delete: menos de 6 horas
  • p99 time-to-hard-delete: menos de 24 horas
  • Backups com cryptoshredding: em até 7 dias (ou seu SLA de backup)

Publique isso no seu DPA. Se ainda não consegue cumprir, defina uma meta inicial e instrumente os gaps. Isso vira seu “budget de expiração”.

3) Fonte de verdade: o Tombstone Ledger

Política sem system-of-record vira deriva. Crie um Tombstone Ledger apenas de append que contenha object_id, object_type, tenant_id, created_at, expiry_at, legal_hold_flag, reason_code. Workers de deleção em todos os stores assinam esse ledger e atuam de forma idempotente. O ledger é sua trilha de auditoria e seu gerador de recibos.

4) Legal holds e exceções

Engenheiros odeiam exceções; reguladores amam. Você precisa de um legal_hold_flag que pare a expiração em todo lugar. Atrelado ao seu fluxo de ticketing/GC. Holds devem ter tempo definido e ser visíveis na UI do produto. Toda exceção tem custo; acompanhe-as.

5) Garantias ao cliente

Exponha no app as configurações de retenção por classe de objeto. Mostre contagens de expirações futuras, permita opt-down (TTL mais curto) e opt-up com limite por plano (TTL mais longo). Envie recibos de deleção com contagem de objetos, tempos p95/p99 e cobertura por store. Isso já é um diferencial competitivo em RFPs.

A arquitetura: transforme política em código

Implemente um padrão simples e durável:

  • Retention Policy Service: Avalia políticas e escreve (object_id, expiry_at) no Tombstone Ledger quando dados são criados ou atualizados. Reavalia no acesso se você usa TTL por last_accessed.
  • Tombstone Ledger: Tabela apenas de append (por exemplo, Postgres particionado por mês) ou stream de eventos (Kafka). Registros imutáveis e assinados.
  • Deletion Orchestrator: Consome tombstones, faz fan-out para workers específicos de cada store, rastreia SLOs por store e emite recibos.
  • Store Workers: Workers para Postgres, S3, Elasticsearch, Kafka, BigQuery/Snowflake, CDN e Backups. Idempotentes, com retries e dead-letter queues.
  • Métricas + Auditorias: Tamanho do backlog de deleção, tempos p95/p99 por store, % de cobertura por classe de objeto, contagem de legal holds e auditorias por amostragem (provar ausência).

Implementação, store por store

Postgres (OLTP)

  • Schema: Adicione expiry_at e tombstoned_at às tabelas expiráveis. Evite cascades causando deletes surpresa; delete explicitamente os filhos primeiro.
  • Partitioning: Particione por expiry_at ou created_at. Expirar por drop de partição é O(1) e evita tempestades de vacuum. Se particionar por expiração for difícil, mantenha uma “tabela sombra” separada e particionada de IDs a serem deletados.
  • Worker: Faça deletes em lotes pequenos (por exemplo, 1–5k linhas) para manter locks curtos. Use DELETE ... USING com join em uma tabela temporária de IDs elegíveis. Monitore bloat; rode autovacuum agressivamente em tabelas quentes.
  • Foreign keys: Se você precisa manter pais por mais tempo que filhos, inverta o relacionamento: o filho referencia o pai, mas o filho pode ser removido sem deadlocks de ON DELETE RESTRICT.

Armazenamento de objetos (S3/GCS)

  • Lifecycle: Use regras de Lifecycle do S3 para expirar objetos em expiry_at. Se usar versionamento, defina NoncurrentVersionExpiration também e remova delete markers periodicamente.
  • Multipart uploads: Expire uploads multipart incompletos (vazamento comum). Habilite AbortIncompleteMultipartUpload em 7 dias.
  • Encryption: Chaves KMS por tenant permitem cryptoshred de backups ao descartar as chaves. Faça rotação anual, no mínimo.
  • CDN: Faça purge no delete. Defina Cache-Control max-age abaixo do seu TTL mais curto, a menos que o conteúdo seja imutável.

Busca (Elasticsearch/OpenSearch)

  • ILM (Index Lifecycle Management): Faça roll over por tamanho/tempo e depois delete no TTL. Para índices multi-tenant, particione por tempo para baratear deletes.
  • Deletes: Faça hard-delete de documentos por ID a partir do feed de Tombstones para evitar “ghost hits” durante a fase warm.
  • Armadilha: Snapshots retêm segmentos deletados; alinhe a retenção de snapshots ao seu SLO de backup.

Eventos/logs (Kafka/Pulsar)

  • Retenção: Configure retention.ms por tópico. Para tópicos com payload gerado por usuário, prefira log compaction + retenção curta ou criptografe no producer com chaves por tenant.
  • DLQs: Dead-letter queues devem herdar o TTL mais curto aplicável; são um sumidouro comum de dark data.

Analytics (BigQuery/Snowflake)

  • Partitioning: Particione tabelas por event_date e cluster by tenant_id. Use TTLs de tabela (BigQuery) ou DROP PARTITION agendado (Snowflake) para impor expiração.
  • Materialized views: Recalcule apenas sobre partições atuais. Jobs de backfill não devem ressuscitar dados expirados.
  • Conjuntos de treinamento de modelos: Rastreie procedência. Se o seu TTL invalidar um coorte de treinamento, registre e retreine. Melhor do que explicar ao jurídico por que você usou dados que prometeu deletar.

Backups

  • Retenção em camadas: Backups quentes (7–14 dias), mornos (30 dias), sem frios a menos que exigido em contrato. Encurte por padrão.
  • Cryptoshredding: Criptografe por tenant ou por bucket. Quando um objeto expirar, marque sua chave para revogação no limite do SLO de backup.
  • Disciplina de restauração: Restaurações não devem reintroduzir dados expirados. Ao restaurar, rode um job pós-restauração de expiração antes do sistema entrar no ar.

Verificação: não apenas delete — prove a ausência

  • Recibos: Para cada tenant, emita recibos mensais: objetos expirados, tempos de deleção p95/p99, stores cobertos, exceções (holds). Isso ganha RFPs.
  • Auditorias aleatórias: Amostre 100 IDs expirados por mês e tente buscar em cada store e sistema de analytics. Zero deve retornar. Gere alerta em qualquer acerto.
  • Atestações de fornecedores: Para fornecedores críticos (por exemplo, observabilidade, SaaS de suporte, provedores de LLM com armazenamento de arquivos), obtenha relatórios SOC/ISO que cubram controles de deleção; adicione linguagem no DPA exigindo TTLs e prova em até 10 dias úteis.

O que isso economiza: custo e raio de impacto

Não trate expiração apenas como compliance. É também dinheiro e uptime.

  • Exemplo de custo no S3: Um SaaS em estágio intermediário com 400 TB em S3 Standard paga aproximadamente 400.000 GB × $0,023 = $9.200/mês. Se 60% dos anexos com mais de 180 dias nunca forem reaces­sados (típico), um TTL de 180 dias mais deletes remove ~240 TB, economizando ~ $5.520/mês antes das economias de requests e replicação.
  • Busca e analytics: Índices e partições menores significam menos nós, consultas mais rápidas e clusterização mais barata. Não é incomum ver redução de 20–40% de infra após TTLs agressivos.
  • Raio de impacto do incidente: Se um atacante chega em T0, tudo que é mais antigo que seu TTL não existe para ser exfiltrado. Essa é a única “mitigação” garantida.

Trade-offs que você precisa assumir

  • Expectativas de produto: Clientes que amam “reabrir um chamado de 2018” vão reclamar. Ofereça exports e extensão de retenção por plano, mas não volte à imortalidade.
  • Utilidade de ML vs. privacidade: TTLs curtos reduzem dados históricos de treinamento. Compense com amostragem, aumento sintético ou janelas móveis.
  • Complexidade: Orquestração de deleção entre stores é trabalho de engenharia real. Mas é limitado e testável — ao contrário do passivo de guardar tudo para sempre.

30-60-90 dias: entregue sem ferver o oceano

Dias 0–30: inventário e primitivos

  • Inventário: Enumere classes de objetos e stores (OLTP, blob, busca, analytics, logs, backups, CDN, LLM/vector stores, ferramentas de suporte). Espere 12–20 sumidouros materiais de dados em um SaaS típico.
  • Padrões: Defina TTLs padrão para o tenant (por exemplo, 90 dias para mensagens/arquivos, 365 dias para auditoria, 30 dias para logs). Escreva isso no seu DPA.
  • Tombstone Ledger: Construa em Postgres, particionado mensalmente. Adicione ganchos de escrita nos caminhos de código que criam/modificam dados.
  • Legal hold: Crie API e UI para definir/limpar holds por tenant/classe de objeto, com expiração e motivos.
  • Implemente S3 + Postgres: Entregue regras de lifecycle, worker de deleção em lote no Postgres e recibos iniciais. Defina SLOs internos (p95: 6h; p99: 24h).

Dias 31–60: estenda e instrumente

  • Busca + Analytics: Aplique ILM aos índices. Particione tabelas de analytics por data, adicione scripts de TTL. Bloqueie consultas que atravessem partições expiradas, a menos que explicitamente permitido.
  • Logs/Event buses: Alinhe a retenção do Kafka/Pulsar. Garanta que DLQs herdem TTLs. Pare de enviar PII para logs sem um TTL definido.
  • Métricas + Alertas: Dashboards para backlog de deleção, tempo de deleção por store, contagem de legal holds e falhas de auditoria. Gere alerta em violações de p99.
  • UI para clientes: Exponha controles de retenção por classe de objeto e recibos mensais. Treine o Suporte para responder “onde foi parar meu arquivo de 2 anos?”.

Dias 61–90: feche o loop

  • Backups: Encurte a retenção. Implemente cryptoshred por chaves por tenant. Valide que pipelines de restauração não ressuscitam dados expirados.
  • Fornecedores: Atualize DPAs para exigir TTLs e atestações. Troque fornecedores que não jogam o jogo.
  • Chaos deletion: Exercício trimestral: escolha um tenant, simule um evento de expiração em massa e verifique deleção end-to-end dentro dos SLOs.
  • Roadmap: Adicione rastreamento de last_accessed por classe de objeto para evoluir de TTLs fixos para TTLs baseados em atividade onde fizer sentido.

Armadilhas comuns (e como evitá-las)

  • Soft delete não é delete. Se a linha existe e índices a referenciam, usuários ainda podem inferi-la (contagens, resultados de busca). Use soft delete apenas como estado de transição; agende hard delete logo depois.
  • Cópias fantasmas em caches. CDN e caches de aplicação frequentemente sobrevivem aos dados. Vincule TTLs de cache ao seu TTL de dados mais curto e faça purge com tombstones.
  • Reindex de busca ressuscita dados. Jobs de reindex que leem snapshots antigos vão trazer documentos expirados de volta. Restrinja reindex às partições vivas apenas.
  • Exports sem limite. CSVs em buckets S3 “exports/” viram um novo lago de dark data. Faça exports objetos expiráveis com TTL curto (7–30 dias).
  • Proliferação de observabilidade. Seus fornecedores de APM e logs frequentemente armazenam PII por acidente. Faça scrubbing na origem, mascare agressivamente e imponha TTLs em contrato.
  • LLM/vector stores. Se você incorpora conteúdo de usuário para RAG, o banco vetorial é uma nova cópia. Trate vetores como objetos de primeira classe com TTLs e deleção atrelada ao tombstone do original.

Conexão com a postura de risco de IA atual

Mesmo os maiores fornecedores de modelos estão lançando “Lockdown Modes” para cercar dados e reduzir o raio de impacto de prompt injection. Isso é necessário, mas insuficiente. Um prompt não pode vazar dados que você já deletou. Expiração por design é o guardrail mais barato e confiável para features de IA porque encolhe o contexto que poderia ser exposto.

Como é o “bom” em produção

  • Cobertura: 100% das classes de objeto mapeadas para TTLs, com suporte a legal hold.
  • Latência: p95 time-to-hard-delete abaixo de 6 horas em todos os stores, auditável.
  • Recibos: Tenants podem puxar recibos de deleção e exportar um relatório de política para auditores com um clique.
  • Backups: Cryptoshred em até 7 dias; restaurações não reintroduzem dados expirados.
  • Fornecedores: DPAs com cláusulas de TTL e atestações anuais; bandeiras vermelhas escaladas para compras.

Como montar o time

Você não precisa de uma nova plataforma. Precisa de um pod pequeno e sênior — 1 backend staff, 1 infra/SRE, 1 data engineer, 0,5 product/GC — para cuidar do ledger, dos workers e do alinhamento com fornecedores. Para times nos EUA, um pod nearshore no Brazil dá 6–8 horas de sobreposição e, na nossa experiência, 20–30% menor TCO para esse tipo de trabalho pesado de plumbing, multiplataforma. O segredo é dar a eles autoridade para dizer “não” a features imortais.

Em resumo

O toggle de expiração do OneDrive e o placar interminável de violações estão dizendo a mesma coisa: deleção agora é requisito de produto. Você pode codificá-la com um ledger, SLOs e recibos — ou continuar pagando juros compostos sobre dados de que não precisa. Entregue expiração por design em um trimestre e torne o próximo incidente significativamente menor antes de começar.

Pontos-chave

  • Defina TTLs padrão por classe de objeto, com extensões por plano e legal holds.
  • Implemente um Tombstone Ledger e um orquestrador de deleção; meça o tempo p95/p99 para deletar.
  • Faça cumprir a expiração em Postgres, S3, busca, analytics, logs, backups, CDN e fornecedores.
  • Prove a ausência: envie recibos de deleção, rode auditorias aleatórias e exija atestações de fornecedores.
  • Espere trade-offs: alguns recursos e a utilidade de ML vão encolher; seu risco e seus custos também.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation