ULID Generator
Generate lexicographically sortable unique IDs
Натисніть «Згенерувати» для створення ULID
Що таке ULID?
ULID (Universally Unique Lexicographically Sortable Identifier) — 128-бітний формат ідентифікатора для унікальності та природного сортування. На відміну від UUID v4, ULID вбудовує Unix-часову мітку в мілісекундах у старші біти.
ULID кодується за Crockford's Base32 — компактний 26-символьний рядок, безпечний для URL і нечутливий до регістру.
Специфікацію створив Алізейн Фероста. ULID не є стандартом IETF — специфікація спільноти (ulid.github.io).
Структура ULID
ULID — 128 бітів, два компоненти:
| Часова мітка | Випадкове |
|---|---|
| 01ARZ3NDEK | TSVE4RRFFQ69G5FAV |
| 48 бітів — Unix-часова мітка в мс. Точність 1 мс. Охоплює до 10889 року. | 80 бітів — криптографічно захищені випадкові дані. Оновлюються для кожного ULID. |
26 символів Crockford Base32: перші 10 — часова мітка, останні 16 — випадковий компонент.
Алфавіт Crockford Base32
Алфавіт ULID: 0123456789ABCDEFGHJKMNPQRSTVWXYZ
Чотири символи навмисно виключені:
I— легко сплутати з1L— легко сплутати з1абоIO— легко сплутати з0U— виключена для зменшення ймовірності образливих слів
Crockford Base32 нечутливий до регістру — рядкові <code>i</code>, <code>l</code>, <code>o</code> декодуються як їх візуальні аналоги.
ULID проти UUID
Порівняння ULID з UUID v4:
| Властивість | ULID | UUID |
|---|---|---|
| Довжина | 26 символів | 36 символів (або 32 без дефісів) |
| Біти | 128 бітів | 128 бітів |
| Лексикографічно сортований | Так | Ні |
| Часова мітка | 48-бітний Unix мс | Ні |
| URL-безпечний | Так (Base32) | Так (лише hex) |
| Нечутливий до регістру | Так | Так |
| Стандарт | Специфікація спільноти | RFC 4122 (IETF) |
| Нативна підтримка в браузері | Ні | Так (<code>crypto.randomUUID()</code>) |
Використовуйте ULID, коли потрібне часове сортування, UUID v4 — для максимальної сумісності.
ULID проти NanoID
ULID і NanoID — популярні альтернативи UUID з різними цілями:
| Властивість | ULID | NanoID |
|---|---|---|
| Довжина | 26 символів | 21 символ (за замовчуванням) |
| Біти ентропії | 80 бітів | 126 бітів |
| Часова мітка | Так (48-бітний мс) | Ні |
| Лексикографічно сортований | Так | Ні |
| Користувацький алфавіт | Ні (Crockford Base32) | Так (налаштовуваний) |
| Нативна підтримка | Ні (потрібна бібліотека) | Ні (потрібна бібліотека) |
| Нативна підтримка в браузері | Ні | Так (Web Crypto API) |
Обирайте ULID для часового порядку, NanoID — для коротших ID без часової мітки.
Підтримка баз даних
ULID зберігаються як текст або бінарні дані:
Приклади коду
ULID не стандартизований нативно. Використовуйте офіційний пакет:
// 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)
}