Minhas notas sobre o design de schema do Postgres no GitLab (2022)
As escolhas de schema PostgreSQL do GitLab geram críticas amplas sobre como aplicações modernas modelam dados em escala. Os comentaristas examinam trade-offs entre chaves primárias de 32 e 64 bits, UUIDs versus IDs sequenciais e estratégias de migração de schema online, destacando como localidade de índice, chaves estrangeiras e abstrações de ORM podem definir ou destruir o desempenho em tabelas com bilhões de linhas. O debate também questiona “boas práticas” comuns, como esconder chaves primárias dos usuários, argumentando que isso muitas vezes reflete preocupações de negócio e competição mais do que segurança, e enfatizando que um design cuidadoso, com foco no banco de dados, continua crucial apesar dos avanços em ferramentas.
Tamanho da chave primária, migrações e ferramentas
- Muitos comentários discutem PKs int vs bigint. Alguns argumentam que atingir limites de 32 bits é um risco real para serviços grandes e “perto demais do ideal”, enquanto outros observam que dados reais (por exemplo, repositórios/issues do GitHub) ainda estão abaixo de 2^31.
- Migrar int→bigint é descrito como viável, mas não trivial em escala: reescritas de tabelas, reconstrução de índices, chaves estrangeiras e criação de índices em single-thread podem levar horas em tabelas multi-TB.
- Abordagens com zero/baixo downtime mencionadas: replicação lógica com switchover, ferramentas de mudança de schema online (pg-osc, gh-ost), desacoplar migrações de schema dos deploys da aplicação e sistemas de migração operados por DBAs.
- Alguns apontam dores secundárias: desserialização de bigint no JavaScript, consumidores downstream assumindo ints de 32 bits.
UUIDs vs inteiros sequenciais
- UUIDv4 como PK é criticado principalmente por desempenho, não por tamanho. 8 bytes extras por entrada de FK/índice se acumulam em muitas tabelas e tornam mais difícil que os índices caibam na RAM.
- UUIDs aleatórios destroem a localidade do índice: inserções em btree ficam espalhadas, causam page bloat e levam a quedas severas de desempenho quando os índices ultrapassam a memória, não apenas a uma penalidade estável de ~25%.
- IDs ordenados por tempo (UUIDv6/v7, estilo Snowflake, sequências criptografadas ou permutadas) são discutidos como compromissos melhores, mas têm trade-offs (vazamento de tempo, rotação de chaves, complexidade).
Design de schema, ORMs e migrações
- Vários argumentam que o design de schema é “idade da pedra” e que ferramentas de migração (EF, Rails, Django, Prisma etc.) ou geram migrações perigosas (locks, rewrites) ou obscurecem o que realmente é executado.
- Há uma forte corrente a favor de pensar schema-first e usar SQL puro (muitas vezes com stored procedures) em vez de ORMs pesados, vistos como com vazamentos, complexos e difíceis de operar em escala.
- Outros defendem ORMs como úteis para consultas dinâmicas e grafos de objetos complexos, se usados com entendimento.
Arquitetura e desempenho do GitLab vs GitHub
- Alguns percebem as páginas do GitLab como visivelmente mais lentas que as do GitHub. As explicações oferecidas incluem cultura e priorização de desempenho, mas os detalhes são anedóticos e incompletos.
- Há discordância/incerteza sobre se o GitLab.com é um único banco multi-tenant ou um banco por cliente; um comentário afirma que é essencialmente uma instância multi-tenant do produto self-hosted deles.
Expor chaves primárias e “external IDs”
- Uma corrente vê esconder PKs sequenciais como majoritariamente “segurança teatral”; se a autorização estiver quebrada, IDs adivinhados não deveriam importar.
- Outros enfatizam defesa em profundidade e inteligência competitiva: IDs sequenciais revelam contagens/crescimento (pedidos, usuários, issues) e tornam mais fácil a enumeração em massa e a exploração.
- Exemplos incluem volumes de pedidos em e-commerce, enumeração de usuários e scraping; contra-argumentos dizem que atacantes motivados muitas vezes conseguem inferir dados semelhantes de qualquer forma.
- O padrão do GitLab de
idinterno maisiidpor projeto é visto como amigável ao usuário e desacopla URLs de mudanças no PK interno, ao custo de joins e índices extras.
Especificidades do Postgres: text vs varchar, FKs
- A discussão esclarece que, no Postgres,
textvsvarchar(n)não tem diferença de desempenho em runtime; o problema real é o custo de migração ao alterar limites emvarchar(n)versus ajustar umCHECKemtext. - Um comentarista rebate a ideia de que chaves estrangeiras são “caras”, argumentando que a integridade precisa ser imposta em algum lugar e que FKs no nível do banco geralmente vencem se usadas corretamente.