ULID Generator
Generate lexicographically sortable unique IDs
Klicka på Generera för att skapa ULIDs
Vad är en ULID?
ULID (Universally Unique Lexicographically Sortable Identifier) är ett 128-bitars identifierarformat utformat för att vara både unikt och naturligt sorterbart. Till skillnad från UUID v4, som är helt slumpmässigt, bäddar en ULID in en millisekundprecisions Unix-tidsstämpel i sina höga bitar — vilket säkerställer att ID:n som genereras senare sorteras efter ID:n som genererats tidigare.
ULID:ar kodas med Crockfords Base32-alfabet, vilket ger en kompakt 26-teckens sträng som är URL-säker, skiftlägeskänslig och fri från visuellt tvetydiga tecken.
ULID-specifikationen skapades av Alizain Feerasta och används allmänt i distribuerade system, händelsekällor och databasprimärnycklar där både unicitet och tidsordning spelar roll. ULID:ar är inte en IETF-standard — de är en gemenskapsspecifikation tillgänglig på ulid.github.io.
ULID-struktur
En ULID är 128 bitar bred, uppdelad i två komponenter:
| Tidsstämpel | Slumpmässig |
|---|---|
| 01ARZ3NDEK | TSVE4RRFFQ69G5FAV |
| 48 bitar — Unix-tidsstämpel i millisekunder. Kodar genereringstiden med 1ms precision. Täcker datum till år 10889. | 80 bitar — kryptografiskt säkra slumpmässiga data. Regenereras fräscht för varje ULID (om inte monotonicitetsläge används). |
Kodad som 26 Crockford Base32-tecken: de första 10 tecknen representerar tidsstämpeln, de sista 16 tecknen representerar den slumpmässiga komponenten.
Crockford Base32-alfabetet
ULID:ar använder Crockfords Base32-kodning, som använder 32 av de 36 alfanumeriska tecknen. Alfabetet är: 0123456789ABCDEFGHJKMNPQRSTVWXYZ
Fyra tecken utesluts avsiktligt:
IochLutesluts — lätt förväxlade med siffran1Outesluts — lätt förväxlad med siffran0Uutesluts — undviker oavsiktliga obscena ord i genererade ID:n- Kodningen är
skiftlägeskänslig—01ARZ3NDEKTSV4RRFFQ69G5FAVoch01arz3ndektsv4rrffq69g5favär samma ULID
Crockford Base32 är effektivare än hexadecimalt (32 symboler vs 16) och mer mänskligt läsbar än Base64 (inga + / = tecken, skiftlägeskänslig).
ULID vs UUID
ULID:ar och UUID:n representerar båda 128-bitarsidentifierare, men skiljer sig avsevärt i kodning och designmål:
| Egenskap | ULID | UUID |
|---|---|---|
| Format | Crockford Base32 | Bindestreck-hex |
| Längd | 26 tecken | 36 tecken |
| Tidsstämpel | 48-bitars Unix ms | Ingen (v4) eller 48-bitars ms (v7) |
| Sorterbar | Ja — lexikografisk | Nej (v4) / Ja (v7) |
| URL-säker | Ja (enbart alfanumerisk) | Ja (med bindestreck) |
| Beroenden | Kräver bibliotek | Inbyggd (crypto.randomUUID) |
| DB-stöd | Lagra som CHAR(26) eller BINARY(16) | Inbyggd UUID-kolumntyp |
| Spec | Gemenskapsspecifikation (ulid.github.io) | RFC 4122 / RFC 9562 |
Om du redan befinner dig i ett UUID-ekosystem (PostgreSQL uuid-kolumner, REST-API:er, ORM:ar med UUID-stöd) är UUID v7 vanligtvis ett bättre val än ULID. Om du föredrar en mer mänskligt vänlig kodning och kontrollerar hela stacken, är ULID ett utmärkt val.
ULID vs nanoid
Både ULID och nanoid producerar korta, URL-säkra identifierare, men de har olika designmål:
| Egenskap | ULID | NanoID |
|---|---|---|
| Tidsstämpel | Ja — 48-bitars Unix ms | Nej |
| Sorterbar | Ja | Nej |
| Standardlängd | 26 tecken | 21 tecken |
| Entropi | 80 bitar (slumpmässig komponent) | ~126 bitar |
| Alfabet | Crockford Base32 (32 tecken) | URL-säker Base64 (64 tecken) |
| Anpassningsbar längd | Nej | Ja (valfri längd) |
| Användningsfall | Tidsordnade ID:n, DB-primärnycklar | Slumpmässiga tokens, korta URL:er, API-nycklar |
Välj ULID när du behöver tidsordning. Välj nanoid när du behöver maximal entropi i en kort, slumpmässig sträng.
Använda ULID:ar i databaser
ULID:ar kan lagras i databaser på flera sätt beroende på dina krav:
Kodexempel
ULID-generering kräver ulid-biblioteket (tillgängligt för JavaScript, Python, Go, Rust med mera):
// 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)
}