ULID Generator
Generate lexicographically sortable unique IDs
Klik op Genereren om ULIDs te maken
Wat is een ULID?
ULID (Universally Unique Lexicographically Sortable Identifier) is een 128-bit identificatorformaat ontworpen om zowel uniek als van nature sorteerbaar te zijn. In tegenstelling tot UUID v4, dat volledig willekeurig is, bevat een ULID een millisecondeprecisie Unix-tijdstempel in zijn hoge bits — wat ervoor zorgt dat later gegenereerde ID's sorteren na eerder gegenereerde ID's.
ULIDs worden gecodeerd met het Crockford Base32-alfabet, waarbij een compact 26-teken string wordt geproduceerd dat URL-veilig, hoofdletterongevoelig en vrij van visueel dubbelzinnige tekens is.
De ULID-specificatie werd gemaakt door Alizain Feerasta en wordt veel gebruikt in gedistribueerde systemen, event sourcing en database primaire sleutels waar zowel uniciteit als tijdvolgorde van belang zijn. ULIDs zijn geen IETF-standaard — ze zijn een community-specificatie beschikbaar op ulid.github.io.
ULID-structuur
Een ULID is 128 bits breed, verdeeld in twee componenten:
| Tijdstempel | Willekeurig |
|---|---|
| 01ARZ3NDEK | TSVE4RRFFQ69G5FAV |
| 48 bits — Unix-tijdstempel in milliseconden. Codeert de generatietijd met 1ms precisie. Dekt datums tot het jaar 10889. | 80 bits — cryptografisch veilige willekeurige gegevens. Vers gegenereerd voor elke ULID (tenzij monotoniemodus wordt gebruikt). |
Gecodeerd als 26 Crockford Base32-tekens: de eerste 10 tekens vertegenwoordigen het tijdstempel, de laatste 16 tekens vertegenwoordigen de willekeurige component.
Crockford Base32-alfabet
ULIDs gebruiken Crockfords Base32-codering, die 32 van de 36 alfanumerieke tekens gebruikt. Het alfabet is: 0123456789ABCDEFGHJKMNPQRSTVWXYZ
Vier tekens worden opzettelijk uitgesloten:
IenLworden uitgesloten — gemakkelijk te verwarren met het cijfer1Owordt uitgesloten — gemakkelijk te verwarren met het cijfer0Uwordt uitgesloten — vermijdt accidenteel aanstootgevende woorden in gegenereerde ID's- De codering is
hoofdletterongevoelig—01ARZ3NDEKTSV4RRFFQ69G5FAVen01arz3ndektsv4rrffq69g5favzijn dezelfde ULID
Crockford Base32 is efficiënter dan hexadecimaal (32 symbolen vs 16) en meer mensleesbaar dan Base64 (geen + / = tekens, hoofdletterongevoelig).
ULID vs UUID
ULIDs en UUIDs vertegenwoordigen beide 128-bit identificatoren, maar verschillen aanzienlijk in codering en ontwerpdoelen:
| Eigenschap | ULID | UUID |
|---|---|---|
| Formaat | Crockford Base32 | Koppeltekens-hexadecimaal |
| Lengte | 26 tekens | 36 tekens |
| Tijdstempel | 48-bit Unix ms | Geen (v4) of 48-bit ms (v7) |
| Sorteerbaar | Ja — lexicografisch | Nee (v4) / Ja (v7) |
| URL-veilig | Ja (alleen alfanumeriek) | Ja (met koppeltekens) |
| Afhankelijkheden | Bibliotheek vereist | Native (crypto.randomUUID) |
| DB-ondersteuning | Opslaan als CHAR(26) of BINARY(16) | Native UUID-kolomtype |
| Specificatie | Community-specificatie (ulid.github.io) | RFC 4122 / RFC 9562 |
Als u zich al in een UUID-ecosysteem bevindt (PostgreSQL uuid-kolommen, REST-API's, ORMs met UUID-ondersteuning), is UUID v7 gewoonlijk een betere keuze dan ULID. Als u vers begint en de voorkeur geeft aan een meer gebruikersvriendelijke codering en de volledige stack beheert, is ULID een uitstekende keuze.
ULID vs nanoid
Zowel ULID als nanoid produceren korte, URL-veilige identificatoren, maar ze hebben verschillende ontwerpdoelen:
| Eigenschap | ULID | NanoID |
|---|---|---|
| Tijdstempel | Ja — 48-bit Unix ms | Nee |
| Sorteerbaar | Ja | Nee |
| Standaardlengte | 26 tekens | 21 tekens |
| Entropie | 80 bits (willekeurige component) | ~126 bits |
| Alfabet | Crockford Base32 (32 tekens) | URL-veilig Base64 (64 tekens) |
| Aanpasbare lengte | Nee | Ja (elke lengte) |
| Gebruiksscenario | Tijdgeordende ID's, DB primaire sleutels | Willekeurige tokens, korte URL's, API-sleutels |
Kies ULID wanneer u tijdvolgorde nodig heeft. Kies nanoid wanneer u maximale entropie in een korte, willekeurige string nodig heeft.
ULIDs in databases gebruiken
ULIDs kunnen op verschillende manieren worden opgeslagen in databases afhankelijk van uw vereisten:
Codevoorbeelden
ULID-generatie vereist de ulid-bibliotheek (beschikbaar voor JavaScript, Python, Go, Rust en meer):
// 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)
}