ID sequencial ou UUID? O que realmente importa na segurança de uma aplicação
← Voltar para o blog
Banco de Dados
163 views10 min de leitura

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):

  1. ID do banco (chave primária) não é "identificador público"

  2. 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: BIGINT auto-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:

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.