Você realmente precisa de chaves estrangeiras?
A decisão de impor restrições de chave estrangeira em bancos relacionais opõe integridade de dados e manutenibilidade de longo prazo a desempenho de escrita, flexibilidade de sharding e complexidade de migração. Muitos engenheiros argumentam que as restrições devem ser o padrão porque evitam bugs sutis, documentam o modelo de dados e protegem dados que sobreviverão a qualquer aplicação individual, enquanto outros apontam grandes implantações em MySQL e arquiteturas especializadas onde as restrições são removidas e a integridade é imposta no código da aplicação. A discussão destaca que chaves estrangeiras raramente são um gargalo em escalas típicas, e que optar por omiti-las com segurança exige alta disciplina, ferramentas robustas e uma compreensão clara das compensações.
Posição geral sobre restrições de chave estrangeira
- Visão majoritária forte: use restrições de chave estrangeira (FK) por padrão em qualquer sistema não trivial e de longa duração.
- Elas evitam dados corrompidos/orfãos, expõem bugs da aplicação cedo e tornam refatorações mais seguras.
- Vários relatos de grandes sistemas legados em MySQL / com centenas de tabelas sem FKs se transformando em pesadelos de “data rot”, exigindo scripts frágeis de limpeza e conhecimento institucional.
Integridade de dados, segurança e documentação
- FKs são comparadas a tipos, cintos de segurança ou memória protegida: você pode programar sem elas, mas elas detectam muitos erros de forma barata.
- Com restrições fortes, equipes podem assumir “se está no banco, é válido”, tratando o banco como uma fortaleza.
- FKs fornecem documentação viva do modelo de dados; FKs ausentes dificultam entender relacionamentos ou até saber se uma coluna é uma referência.
Desempenho, escala e quando considerar remover FKs
- Críticos argumentam que FKs desaceleram cargas pesadas de escrita/exclusão, complicam sharding e mudanças de esquema online (especialmente no MySQL) e adicionam contenção de locks.
- Outros respondem que:
- A maioria dos aplicativos nunca atinge uma escala em que isso importe.
- Você paga o custo de integridade em algum lugar; mover as verificações para o código da aplicação não as torna gratuitas e introduz risco de races.
- Processamento em lote, restrições adiadas e ajustes de configuração muitas vezes mitigam problemas de desempenho.
- Algumas plataformas de altíssima escala ou complexas implementam camadas personalizadas de integridade em vez de FKs nativas, mas isso é apresentado como uma escolha avançada e especializada.
Enforcement no nível da aplicação vs no nível do banco
- Um grupo: a integridade pode ser imposta na camada da aplicação ou do serviço, especialmente se houver apenas um writer e controle de acesso rígido; FKs são opcionais.
- Grupo oposto: múltiplos aplicativos, acesso ad hoc e semântica de concorrência tornam frágil e propenso a erros reproduzir garantias do banco em código.
Soft deletes e comportamento de exclusão
- Combinar soft deletes com
deleted_ate FKs é complicado, especialmente para garantir que pais com filhos ativos não possam ser soft-deletados. - Abordagens propostas: soft-delete universal, FKs compostas incluindo uma flag “is_deleted”, mover linhas excluídas para tabelas separadas ou tabelas de auditoria via triggers.
Estratégias de ambiente
- Alguns sugerem habilitar FKs apenas em dev/test para pegar problemas, desabilitando em produção para velocidade de ingestão.
- Isso é fortemente criticado como invertido e arriscado: produção, e não teste, contém os dados que realmente importam.