
ID sequencial ou UUID? O que realmente importa na segurança de uma aplicação
A ideia da postagem é responder a pergunta que me fizeram no YouTube: "Olá professor Matheus poderia me tirar uma duvida a respeito de banco de dados? Então, sabe quando vc cria um id pro seu banco de dados? Normalmente eu vejo o pessoal fazendo por exemplo Long id ai faz um GeneretionType.IDENTITY que gera um id sequencial: 1,2,3,4,5... Assim por diante. A minha questão é, enquanto eu estudava sobre cyber segurança descobrir que em aplicações reais não se usa id sequencial, pq pode vim o famoso joãozinho que se acha o hacker e pode encontrar vulnerabilidades no seu sistema só puxando os id. Então enquanto procurava soluções cheguei no UUID que esse sim é um id mais complexo, só que justamente por ser complexo é muito complicado se qualquer pessoa se lembrar dele caso precise. Então digamos que no meu sistema eu tenha uma tabela de usuários e eu possa puxar os usuários pelo id, e nessa minha tabela eu tenho varios gustavos por exemplo mas preciso de um gustavo em especifico, eu não vou saber qual o id dele por ser um id muito complexo. Então quem já trabalha na área e ta acostumado, como vcs normalmente costumam fazer para resolver esse problema? Usam UUID mesmo, id sequencial, ou outra forma."
Publicado em 9 de janeiro de 2026 às 14:31
Se você leu o resumo, sabe que ele está com o raciocínio certo, só precisa separar duas coisas (que geralmente a galera mistura):
ID do banco (chave primária) não é "identificador público"
Segurança não é "não usar ID sequencial" e sim controlar acesso"(autorização)
O ponto de segurança (o "joãozinho puxando IDs")
O problema não é o ID ser 1,2,3.... O problema é o sistema permitir que alguém acesse dados de outro usuário só mudando o número na URL (/users/1, /users/2).
Isso é um bug de autorização (IDOR / Broken Access Control). A correção é:
toda rota que busca algo por ID precisa validar: "esse cara tem permissão pra ver esse recurso?"
se o recurso é do próprio usuário, validar: id da URL == id do usuário autenticado (ou checar ownership/roles)
UUID não "resolve" isso. Ele só torna mais difícil "adivinhar". Se a autorização estiver errada, com UUID também vaza.
"Mas UUID é impossível de memorizar"
E é aí que entra a prática do mundo real:
Usuário nunca procura usuário por ID.
Usuário procura por nome, e-mail, CPF, username, matrícula, etc.O ID serve pro sistema, não pra pessoa.
Então o cenário "tenho vários Gustavos e preciso do Gustavo específico" normalmente é resolvido com:
busca por email (quase sempre único)
busca por username
filtros (nome + data de cadastro + status + empresa/unidade)
e por trás disso, o sistema usa o ID pra referenciar certo.
O que o mercado costuma fazer de verdade
Depende do caso, mas o padrão mais comum é:
Opção A) ID sequencial no banco + identificador público separado
Banco:
BIGINTauto-increment (IDENTITY)Público/API: um "publicId" não sequencial (UUID/ULID/KSUID, ou até um código curto)
Exemplo:
tabela
users:id(interno),public_id(exposto)URL:
/users/{publicId}(não dá pra enumerar fácil)joins/índices continuam rápidos e baratos com
BIGINT
Opção B) UUID como chave primária
Funciona (eu não gosto), e muita gente usa, principalmente em sistemas distribuídos/microservices.
Mas tem trade-offs:
índice maior, mais peso em join, pode fragmentar mais
e na prática você ainda vai ter campos “humanos” (email/username) pra busca
Sugiro a leitura desse artigo do Rafael Ponte: https://www.linkedin.com/posts/rponte_n%C3%A3o-use-uuid-como-pk-nas-tabelas-do-seu-banco-activity-7242521378787082240-YhMB/?originalSubdomain=pt
Opção C) ULID/KSUID em vez de UUID
São IDs "tipo UUID", mas geralmente ordenáveis por tempo, o que melhora índice/insert em alguns bancos e ainda não é sequencial simples.
No fim das contas, a escolha entre ID sequencial, UUID, ULID ou qualquer outro formato não é uma decisão de “segurança”, e sim de arquitetura, performance e contexto. Sistemas quebram não porque alguém “adivinhou um ID”, mas porque faltou controle de acesso. O ID é um detalhe interno do sistema; quem garante segurança é a validação correta de permissões, ownership e papéis em cada requisição. Separar identificadores internos de identificadores públicos, entender quem consome cada um e aplicar autorização corretamente é o que diferencia código de tutorial de sistema de produção de verdade.