Générateur ULID
Génère des identifiants uniques triables lexicographiquement
Cliquez sur Générer pour créer des ULIDs
Qu'est-ce qu'un ULID ?
ULID (Universally Unique Lexicographically Sortable Identifier) est un format d'identifiant de 128 bits conçu pour être à la fois unique et naturellement triable. Contrairement à UUID v4, qui est entièrement aléatoire, un ULID intègre un horodatage Unix de précision milliseconde dans ses bits de poids fort — garantissant que les identifiants générés plus tard se trient après les identifiants générés plus tôt.
Les ULID sont encodés en utilisant l'alphabet Crockford Base32, produisant une chaîne compacte de 26 caractères qui est URL-safe, insensible à la casse et exempte de caractères visuellement ambigus.
La spécification ULID a été créée par Alizain Feerasta et est largement utilisée dans les systèmes distribués, l'event sourcing et les clés primaires de base de données où l'unicité et l'ordre chronologique comptent tous deux. Les ULID ne sont pas une norme IETF — ce sont une spécification communautaire disponible sur ulid.github.io.
Structure ULID
Un ULID fait 128 bits de large, divisé en deux composants :
| Horodatage | Aléatoire |
|---|---|
| 01ARZ3NDEK | TSVE4RRFFQ69G5FAV |
| 48 bits — horodatage Unix en millisecondes. Encode le temps de génération avec une précision de 1 ms. Couvre les dates jusqu'à l'an 10889. | 80 bits — données aléatoires cryptographiquement sécurisées. Régénérées pour chaque ULID (sauf si le mode monotone est utilisé). |
Encodé comme 26 caractères Crockford Base32 : les 10 premiers caractères représentent l'horodatage, les 16 derniers représentent le composant aléatoire.
Alphabet Crockford Base32
Les ULID utilisent l'encodage Crockford Base32, qui utilise 32 des 36 caractères alphanumériques. L'alphabet est : 0123456789ABCDEFGHJKMNPQRSTVWXYZ
Quatre caractères sont intentionnellement exclus :
IetLsont exclus — facilement confondus avec le chiffre1Oest exclu — facilement confondu avec le chiffre0Uest exclu — évite les mots obscènes accidentels dans les identifiants générés- L'encodage est
insensible à la casse—01ARZ3NDEKTSV4RRFFQ69G5FAVet01arz3ndektsv4rrffq69g5favsont le même ULID
Crockford Base32 est plus efficace que l'hexadécimal (32 symboles vs 16) et plus lisible par l'humain que Base64 (pas de caractères + / =, insensible à la casse).
ULID vs UUID
Les ULID et les UUID représentent tous deux des identifiants de 128 bits, mais diffèrent significativement dans l'encodage et les objectifs de conception :
| Propriété | ULID | UUID |
|---|---|---|
| Format | Crockford Base32 | Hexadécimal avec tirets |
| Longueur | 26 caractères | 36 caractères |
| Horodatage | Unix ms de 48 bits | Aucun (v4) ou ms de 48 bits (v7) |
| Triable | Oui — lexicographique | Non (v4) / Oui (v7) |
| URL-safe | Oui (alphanumérique uniquement) | Oui (avec tirets) |
| Dépendances | Nécessite une bibliothèque | Natif (crypto.randomUUID) |
| Support BD | Stocker comme CHAR(26) ou BINARY(16) | Type de colonne UUID natif |
| Spec | Spec communautaire (ulid.github.io) | RFC 4122 / RFC 9562 |
Si vous êtes déjà dans un écosystème UUID (colonnes uuid PostgreSQL, API REST, ORM avec support UUID), UUID v7 est généralement plus adapté que ULID. Si vous préférez un encodage plus convivial et contrôlez toute la pile, ULID est un excellent choix.
ULID vs nanoid
ULID et nanoid produisent tous deux des identifiants courts et URL-safe, mais ont des objectifs de conception différents :
| Propriété | ULID | NanoID |
|---|---|---|
| Horodatage | Oui — Unix ms de 48 bits | Non |
| Triable | Oui | Non |
| Longueur par défaut | 26 caractères | 21 caractères |
| Entropie | 80 bits (composant aléatoire) | ~126 bits |
| Alphabet | Crockford Base32 (32 chars) | URL-safe Base64 (64 chars) |
| Longueur personnalisable | Non | Oui (n'importe quelle longueur) |
| Cas d'usage | Identifiants ordonnés dans le temps, clés primaires BD | Jetons aléatoires, URL courtes, clés API |
Choisissez ULID quand vous avez besoin d'un ordre chronologique. Choisissez nanoid quand vous avez besoin d'une entropie maximale dans une chaîne courte et aléatoire.
Utiliser les ULID dans les bases de données
Les ULID peuvent être stockés dans les bases de données de plusieurs façons selon vos exigences :
Exemples de code
La génération ULID nécessite la bibliothèque ulid (disponible pour JavaScript, Python, Go, Rust et plus) :
// Using the 'ulid' npm package
import { ulid } from 'ulid'
const id = ulid() // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
const id2 = ulid() // "01ARZ3NDEKXXXXXXXXXXXX..." (same ms, incremented random)
// With a custom timestamp
const id3 = ulid(1469918176385) // deterministic time portion
// Extract the timestamp back out
import { decodeTime } from 'ulid'
decodeTime(id) // → 1469918176385 (Unix ms)# Using python-ulid
from ulid import ULID
uid = ULID()
str(uid) # "01ARZ3NDEKTSV4RRFFQ69G5FAV"
uid.timestamp # 1469918176.385
uid.datetime # datetime(2016, 7, 30, 23, 36, 16, 385000, tzinfo=timezone.utc)
# Parse an existing ULID string
parsed = ULID.from_str("01ARZ3NDEKTSV4RRFFQ69G5FAV")
parsed.timestamp # 1469918176.385-- Store ULIDs as TEXT or CHAR(26)
CREATE TABLE events (
id CHAR(26) PRIMARY KEY DEFAULT gen_ulid(), -- if using a PG extension
name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Or pass the ULID from your application layer
INSERT INTO events (id, name, created_at)
VALUES ('01ARZ3NDEKTSV4RRFFQ69G5FAV', 'user.signup', NOW());
-- Range queries are efficient because ULIDs sort chronologically
SELECT * FROM events
WHERE id > '01ARZ3NDEKTSV4RRFFQ69G5FAV'
ORDER BY id
LIMIT 20;// Pure browser / Deno / Node.js implementation (no dependencies)
const CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
function encodeTime(ms) {
let result = '', n = BigInt(ms)
for (let i = 9; i >= 0; i--) {
result = CROCKFORD[Number(n & 31n)] + result
n >>= 5n
}
return result
}
function encodeRandom(bytes) {
let n = 0n
for (const b of bytes) n = (n << 8n) | BigInt(b)
let result = ''
for (let i = 15; i >= 0; i--) {
result = CROCKFORD[Number(n & 31n)] + result
n >>= 5n
}
return result
}
function generateULID() {
const randomBytes = new Uint8Array(10)
crypto.getRandomValues(randomBytes)
return encodeTime(Date.now()) + encodeRandom(randomBytes)
}