Muitos sistemas começam com uma sequência do banco: o primeiro registro recebe 1, o próximo 2, e uma autoridade central impede duplicatas. Esse modelo é simples enquanto toda criação passa pelo mesmo lugar. Quando serviços, regiões ou clientes offline precisam criar dados de forma independente, o contador vira um ponto de coordenação. UUID oferece outra estratégia: gerar um valor em um espaço tão grande que uma colisão prática se torna extremamente improvável.
UUID é um valor de 128 bits
A forma conhecida, como 550e8400-e29b-41d4-a716-446655440000, é uma representação textual. Hífens separam grupos e alguns bits indicam versão e variante. A unicidade não depende de consultar um registro global; depende do método de geração e da quantidade de valores possíveis.
Em UUID v4, a maior parte dos bits é aleatória. Com um gerador seguro, mesmo bilhões de IDs permanecem longe de uma probabilidade relevante de colisão. Ainda assim, uma unique constraint protege a integridade se alguma assumption falhar.
A independência muda fluxos de criação
Um aplicativo pode atribuir ID antes de sincronizar. Duas bases podem criar linhas e fazer merge depois. Um evento pode referenciar uma entidade antes do commit central. Isso simplifica offline-first, importação, filas e sistemas distribuídos.
O ID também não revela uma contagem simples como uma sequência pública. Essa propriedade reduz enumeração casual, mas não substitui autorização em cada request.
Versões diferentes oferecem propriedades diferentes
Version 4 é aleatória. Version 1 combina tempo e informação de nó, com possíveis impactos de privacidade. Version 7 organiza timestamp e randomness para melhorar ordenação aproximada e localidade de índices. Versões baseadas em nome produzem resultado determinístico.
Escolher versão significa decidir sobre privacidade, sorting, determinismo, suporte de bibliotecas e performance. Uma string válida pode ser inadequada para o caso de uso.
O banco precisa de uma representação adequada
Texto é legível, mas ocupa mais espaço. Tipos UUID nativos ou armazenamento binário reduzem índices e oferecem validação. UUIDs aleatórios inseridos em árvores ordenadas podem fragmentar páginas e diminuir cache locality.
O efeito depende de workload, engine e escala. Meça insert rate, tamanho de índice, joins, replicação e backup com dados próximos de produção.
IDs públicos e internos podem coexistir
Alguns sistemas usam integer interno para joins e UUID público nas APIs. Essa escolha adiciona mapping, mas separa eficiência de identidade externa. Outros usam UUID como primary key diretamente.
Nomes e tipos devem impedir confusão. internal_id e public_id não deveriam ser trocados acidentalmente em serializers ou rotas.
A forma canônica evita duplicatas lógicas
APIs normalmente emitem lowercase com hífens. Aceitar várias formas pode ser útil, mas o armazenamento e a saída devem ser canônicos. Use parser UUID, não regex improvisada.
Sintaxe e policy são verificações distintas. Um UUID padrão pode ter uma versão que o serviço não aceita para aquela operação.
Identificador não é segredo
UUIDs aparecem em URLs, logs, analytics, screenshots e mensagens. Mesmo difíceis de adivinhar, podem vazar. Conhecer o ID não deve conceder acesso. O servidor precisa verificar tenant e permissão.
Quando possuir um link deve conceder acesso, use capability token separado, com entropia, expiração e revogação.
Retries precisam reutilizar a identidade
Um cliente que cria novo UUID em toda tentativa pode gerar registros duplicados para a mesma ação. Cada linha é tecnicamente única, mas o negócio vê duplicidade. O ID lógico ou idempotency key deve permanecer entre retries.
Essa regra precisa estar no contrato de criação e nos eventos. Um consumidor não deveria adivinhar se o ID é provisório ou permanente.
Ferramentas humanas precisam de contexto
UUID é difícil de ditar e memorizar. Painéis devem permitir copiar exatamente, buscar e mostrar contexto como nome, status e data. Prefixos curtos podem colidir visualmente e levar suporte ao recurso errado.
Usuários podem receber uma referência amigável enquanto a API usa UUID. As duas identidades precisam de lifecycle claro.
O lifecycle do ID deve ser documentado
Defina quem gera o UUID, em qual momento ele se torna permanente e se o cliente pode enviar um valor próprio. Um serviço pode assumir que o ID muda após sincronização enquanto outro já publicou o valor em eventos e URLs. Essa divergência quebra referências sem produzir uma falha óbvia.
Depois que o identificador aparece externamente, tratá-lo como immutable costuma ser a regra mais segura. Correções de dados devem alterar atributos, não a identidade publicada.
Ambientes de teste não podem contaminar produção
Fixtures usam UUIDs fixos para tornar testes legíveis. O gerador production não deve herdar esse comportamento por configuração. Integration tests precisam provar que chamadas concorrentes produzem valores diferentes e que retries reutilizam o mesmo ID lógico.
Também teste o round trip por API, queue, database e export. A forma deve sobreviver sem truncamento ou transformação.
Migrações devem preservar mapping
Ao importar dados antigos, gere UUID uma vez e salve a relação com a chave legacy. Reexecutar a migração deve produzir a mesma identidade. UUID baseado em nome pode ajudar quando a origem é estável e não sensível.
Rollback, replay e export para parceiros precisam manter referências. Trocar IDs publicados costuma custar mais que qualquer ganho interno.
Observabilidade encontra geradores quebrados
Duplicate-key e UUID malformado deveriam ser raros. Um aumento pode indicar random source ruim, biblioteca incorreta, cliente desatualizado ou corrupção de import. Métricas por produtor ajudam a encontrar a origem.
UUID resolve allocation distribuído. Storage, autorização, idempotência e governança continuam sendo responsabilidades do sistema. Quando essas fronteiras são claras, ele elimina coordenação sem eliminar integridade.