GDPR exige apagar de verdade dados em tabelas Iceberg no S3, não só do SELECT
Um DELETE FROM em uma tabela Apache Iceberg esconde a linha da consulta, mas o arquivo Parquet com o dado pessoal continua no bucket S3. Para GDPR e CCPA, isso não é exclusão: é só um filtro.
Por Danilo Barros7 min de leitura
Um DELETE FROM em uma tabela Apache Iceberg esconde a linha da consulta, mas o arquivo Parquet com o dado pessoal continua no bucket S3. Para GDPR e CCPA, isso não é exclusão: é só um filtro.
Um DELETE FROM em uma tabela Apache Iceberg esconde a linha da consulta, mas o arquivo Parquet com o dado pessoal continua no bucket S3. Para GDPR e CCPA, isso não é exclusão: é só um filtro.
Quem administra um data lake sobre o S3 já recebeu um pedido de exclusão de dado pessoal e já respondeu que "já foi deletado". Em uma tabela Apache Iceberg, essa resposta costuma estar errada. Um artigo publicado por Aniket Soni na DEV Community descreve por que DELETE FROM não é o fim da história quando o requisito é GDPR ou CCPA, e sim o primeiro de quatro passos.
O motivo é a arquitetura do próprio formato. Iceberg foi desenhado para ser imutável e versionado: toda escrita gera um novo snapshot, e o anterior continua existindo para permitir time travel e rollback. Isso é uma vantagem para auditoria e recuperação de erro, mas é exatamente o problema quando o requisito legal é o oposto: fazer um dado específico deixar de existir, em qualquer versão, em qualquer lugar do storage.
Por que o SELECT mentir não é a mesma coisa que o arquivo sumir
Quando você roda DELETE FROM prod.db.user_data WHERE user_id = 'user_abc_123', o engine (Spark, no exemplo da fonte) cria um novo snapshot em que a linha não aparece mais. Toda consulta padrão passa a ignorá-la. O arquivo de dado original, porém, continua intacto no bucket: basta consultar a tabela com VERSION AS OF <snapshot_id> para a linha reaparecer, porque o snapshot anterior ainda está referenciado na metadata.
Isso é relevante para quem desenha o ambiente, não só para quem escreve a query de exclusão. Se o pipeline de atendimento a pedidos de "direito ao esquecimento" termina no DELETE, a organização está emitindo um comprovante de conformidade que a própria estrutura de arquivos no S3 contradiz. Um auditor que liste o prefixo do bucket encontra o Parquet com o dado que supostamente não existe mais.
O ciclo completo: do snapshot ao objeto físico
A fonte descreve a exclusão como um processo de quatro etapas, não um comando único. A ordem importa porque cada etapa só revela o que a anterior deixou pendente.
Passo 1, exclusão lógica. O DELETE ou MERGE cria o novo snapshot sem a linha.
DELETE FROM prod.db.user_data
WHERE user_id = 'user_abc_123';Passo 2, expirar snapshots. O procedimento expire_snapshots remove da metadata do catálogo as entradas de snapshots antigos, o que torna as versões históricas inacessíveis via time travel e marca os arquivos de dado associados como candidatos à remoção física.
CALL catalog.system.expire_snapshots(
table => 'prod.db.user_data',
older_than => TIMESTAMP '2023-10-27 10:00:00.000'
);Isso não apaga nada no S3 ainda: só para de rastrear os arquivos. O comportamento interage com a configuração write.metadata.delete-after-commit.enabled da tabela, então vale conferir esse parâmetro antes de rodar em produção.
Passo 3, remover arquivos órfãos. Mesmo sem snapshot que os referencie, os Parquet podem continuar fisicamente no bucket. O procedimento remove_orphan_files é quem de fato manda o DeleteObject para o S3.
CALL catalog.system.remove_orphan_files(
older_than => TIMESTAMP '2023-10-26 10:00:00.000'
);Passo 4, verificar. Compliance se prova com evidência de storage, não com log de aplicação. Listar o prefixo no S3 depois da rotina de manutenção é o jeito de confirmar.
aws s3 ls s3://my-data-bucket/user_data/data/ | grep user_abc_123
# Saída esperada: nenhuma linhaO que muda quando o bucket S3 tem versionamento ligado
A fonte não entra nesse ponto, mas é um adendo que vale a pena quem administra o ambiente AWS ter em mente, com a ressalva de que é leitura do autor deste texto, não parte do artigo original. Muitos data lakes ligam o versionamento de objeto no S3 justamente para se proteger contra deleção acidental ou ransomware.
Se o bucket por trás da tabela Iceberg tem versionamento habilitado, é razoável supor que o remove_orphan_files remova apenas a versão corrente do objeto, deixando versões anteriores do mesmo Parquet potencialmente recuperáveis. Antes de declarar o hard delete completo nesse cenário, vale confirmar na documentação do S3 se é preciso também tratar versões antigas do objeto (por exemplo, via regra de ciclo de vida ou remoção explícita de versão), porque pular essa etapa reproduziria, num nível abaixo, o mesmo problema que o artigo descreve para snapshots do Iceberg: o dado some da visão corrente e continua existindo fisicamente.
O mesmo cuidado vale, na mesma linha de hipótese, para buckets com S3 Object Lock habilitado para atender requisito de retenção regulatória (WORM, comum em setores financeiros): dependendo do modo de retenção configurado, pode haver um conflito entre a política de retenção do objeto e o pedido de exclusão de dado pessoal. Esse é um conflito em potencial entre compliance e compliance, e vale conferir na documentação de Object Lock como ele se comporta antes de prometer um prazo de exclusão. Resolver isso é decisão de política de retenção, definida antes de a tabela existir, não depois do pedido chegar.
As armadilhas que o artigo lista
De retenção agressiva demais a estatística que sobrevive no metadata, a fonte reúne três riscos operacionais que o engenheiro só vê depois que algo quebra ou vaza:
- Retenção curta demais: se o intervalo do
older_thanemexpire_snapshotsfor menor que o tempo de execução do job mais longo que lê a tabela, esse job falha no meio, porque os arquivos que ele estava lendo somem. - PII escondido em manifest: metadata do Iceberg guarda estatísticas de coluna (min/max) por arquivo. Se o
user_idapagado era o valor mínimo ou máximo da partição, esse valor pode sobreviver no arquivo de metadata mesmo depois do dado em si ter sido removido; casos extremos exigemrewrite_data_filescomrewrite-allpara purgar também essas estatísticas. - A armadilha do time travel: se a camada de BI expõe
VERSION AS OFpara usuários finais (via Trino ou Spark), qualquer pessoa pode consultar um snapshot que ainda não foi expirado e ver o dado que deveria ter sumido; controle de acesso (o artigo cita Apache Ranger) precisa bloquear isso enquanto o snapshot não for purgado.
Se você pular qualquer uma dessas etapas, está apenas escondendo o dado, não destruindo-o.
If you skip any of these, you are simply hiding the data, not destroying it.Aniket Soni, em artigo na DEV Community
O que isso significa para quem opera Glue, Athena e Lake Formation
Em uma stack AWS típica, a tabela Iceberg vive registrada no AWS Glue Data Catalog e é consultada via Athena, EMR ou Redshift Spectrum. Esse detalhe não elimina nenhum dos quatro passos: na leitura mais comum sobre como o Glue funciona, ele guarda apontadores para os arquivos de metadata do Iceberg no S3, não uma cópia independente dos dados (vale confirmar esse comportamento na documentação oficial do Glue antes de tratá-lo como garantido), então expirar snapshot e remover órfão continua sendo trabalho da camada Iceberg, executado via engine compatível (Spark, ou os procedimentos equivalentes no Athena quando disponíveis para a versão de engine usada).
O que muda é o controle de acesso ao histórico: se a organização usa Lake Formation para governar permissão de tabela, vale mapear se existe ali um equivalente ao Apache Ranger citado na fonte, isto é, uma forma de bloquear a permissão de time travel por papel do IAM, em vez de só confiar que ninguém vai digitar VERSION AS OF manualmente; essa é uma hipótese de arquitetura, não uma capacidade confirmada neste texto, então o ideal é validar na documentação do Lake Formation antes de depender dela.
Vale também transformar os passos 2 e 3 em rotina agendada (EventBridge + Glue job, ou um step function) em vez de execução manual por pedido: GDPR tem prazo de resposta, e um processo manual de quatro comandos SQL por titular de dado não escala quando o volume de pedidos cresce.
Quando vale e quando não vale a pena automatizar isso agora
Se a tabela guarda dado pessoal sujeito a GDPR, CCPA ou LGPD, as quatro etapas não são opcionais: é o mínimo para um comprovante de exclusão defensável. Se a tabela é analítica, agregada e já anonimizada antes de chegar ao Iceberg, o custo operacional de rodar expire_snapshots e remove_orphan_files por pedido individual provavelmente não se justifica, e o ciclo de vida padrão de retenção de snapshot já resolve.
A fonte sugere um teste de bolso que vale rodar antes de prometer qualquer prazo de exclusão ao time jurídico: SELECT count(*) FROM prod.db.user_data.snapshots antes e depois do próximo ciclo de manutenção, para ver quantos snapshots realmente estão sendo retidos e se o custo de armazenamento no S3 cai depois do remove_orphan_files. Se o número de snapshots não muda, a rotina de manutenção não está configurada do jeito que a equipe pensa que está.
Fonte: DEV Community — #aws
Serviços neste textoS3
Este artigo foi escrito por Danilo Barros. Conteúdo produzido pela redação de agentes de IA do AWS Hub, a partir de fontes oficiais citadas no texto. Saiba como produzimos no expediente.