Por que esses formatos existem
O UUIDv4, que é aleatório, é ótimo para ser único e péssimo para ser ordenado, e essa desordem prejudica o desempenho do banco de dados sem que ninguém perceba (a história está no artigo sobre chaves de banco de dados). Antes de o UUIDv7 padronizar um UUID ordenado pelo tempo, vários projetos criaram os seus próprios formatos de identificador para ter o mesmo benefício: um ID que se ordena pela hora de criação, é compacto, funciona bem em URLs e, ainda assim, não precisa de coordenação central. Vale conhecê-los porque você vai encontrá-los em sistemas reais e porque eles mostram o mesmo punhado de trade-offs (o que se ganha de um lado e se perde do outro).
A receita comum
Quase todo ID ordenável segue a mesma ideia: colocar um timestamp (carimbo de tempo) na frente e bits aleatórios ou sequenciais depois. Assim, ordenar os IDs como texto também os ordena, mais ou menos, pelo tempo, porque a parte mais significativa é o relógio. Codificar o conjunto todo numa base que preserva a ordem (para que o texto se ordene do mesmo jeito que os bytes) torna os IDs ordenáveis lexicograficamente, como simples strings. Os formatos diferem em quantos bits gastam com o tempo e quantos com a aleatoriedade, em como codificam o resultado e em se precisam ou não de alguma coordenação entre os geradores.
ULID
O é um identificador de 128 bits, o mesmo tamanho de um UUID, escrito como 26 caracteres em base32 de Crockford. Os primeiros 48 bits são um timestamp em milissegundos, e os 80 restantes são aleatórios. A codificação não diferencia maiúsculas de minúsculas, foi escolhida para ser fácil de ler e é ordenável lexicograficamente, com um modo monotônico opcional que garante a ordem mesmo para IDs criados no mesmo milissegundo. O ULID (Universally Unique Lexicographically Sortable Identifier, um identificador universalmente único e ordenável lexicograficamente) foi uma das respostas mais populares ao problema de ordenação do v4 e, como tem 128 bits, pode ser guardado no mesmo espaço de um UUID.
KSUID
O KSUID (criado pela Segment) é um identificador de 160 bits, codificado como 27 caracteres em base62. Ele usa um timestamp de 32 bits, com resolução de segundos e uma epoch própria, o marco zero da contagem, escolhida para que os timestamps continuem compactos por muitos anos; depois dele vêm 128 bits de aleatoriedade. A parte aleatória maior torna as colisões extremamente improváveis, mesmo com taxas altas de geração, ao custo de ser maior que um UUID. Como o ULID, ele fica ordenado pelo tempo quando é ordenado como texto.
Snowflake
O Snowflake (que nasceu no Twitter) tem outro formato: é um inteiro de 64 bits, e não um valor de 128 bits. Ele empacota em 64 bits um timestamp em milissegundos, um identificador de máquina ou de datacenter e um número de sequência por milissegundo, e por isso cabe numa coluna bigint comum, com sinal. Essa compactação é o que o torna atraente para conjuntos de dados muito grandes. O problema é a coordenação: cada gerador precisa de um ID de máquina único, que alguém tem de atribuir e gerenciar; ou seja, o Snowflake abre mão da vantagem dos UUIDs de dispensar coordenação em troca de um identificador bem menor. Muitos sistemas têm o seu próprio esquema no estilo do Snowflake, construído sobre a mesma ideia de empacotamento.
NanoID
O NanoID é o ponto fora da curva: ele não se baseia em tempo de jeito nenhum. É só uma string aleatória compacta e segura para usar em URL, com alfabeto e tamanho configuráveis, pensada como uma alternativa menor e mais amigável a um UUID aleatório, para quando você quer um identificador opaco numa string curta. Compare-o com o UUIDv4, e não com os formatos ordenáveis: ele é otimizado para tamanho e para uso em URL, não para ordenação.
Como eles se comparam
Os trade-offs se organizam em alguns eixos. Tamanho: o Snowflake tem 64 bits, o ULID e o UUID têm 128 bits, o KSUID tem 160 bits. Codificação: base32 (ULID), base62 (KSUID), um inteiro (Snowflake) ou hexadecimal (UUID). Coordenação: só o Snowflake precisa de IDs de máquina atribuídos; os outros dispensam coordenação. Ordenação: todos, menos o NanoID, são ordenados pelo tempo. E uma ressalva que vale para todos: qualquer ID que começa com um timestamp deixa a hora de criação visível para quem conseguir lê-lo, o que não é problema na maioria dos usos, mas merece atenção quando o identificador fica exposto publicamente.
Por que o UUIDv7 mudou a conta
Esta lista importa menos do que importava porque o UUIDv7 (veja o artigo sobre as versões) padronizou a mesma receita de timestamp seguido de parte aleatória dentro do formato UUID normal, de 128 bits. Ele entrega ordenação pelo tempo e boa localidade no índice e continua sendo um UUID padrão, que todo banco de dados e toda biblioteca já entendem, sem codificação própria e sem coordenação. Por isso, em sistemas novos, o ponto de partida honesto é o v7, e uma dessas alternativas só entra quando você precisa da propriedade específica dela: um tamanho de 64 bits que cabe num bigint (Snowflake), uma codificação de texto específica ou um espaço aleatório maior. Elas resolveram um problema real; hoje, o v7 resolve a maior parte dele de forma padronizada.