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 бітів, два компоненти:

Часова міткаВипадкове
01ARZ3NDEKTSVE4RRFFQ69G5FAV
48 бітів — Unix-часова мітка в мс. Точність 1 мс. Охоплює до 10889 року.80 бітів — криптографічно захищені випадкові дані. Оновлюються для кожного ULID.

26 символів Crockford Base32: перші 10 — часова мітка, останні 16 — випадковий компонент.

Алфавіт Crockford Base32

Алфавіт ULID: 0123456789ABCDEFGHJKMNPQRSTVWXYZ

Чому саме ці 32 символи?
0123456789ABCDEFGHJKMNPQRSTVWXYZ

Чотири символи навмисно виключені:

  • I — легко сплутати з 1
  • L — легко сплутати з 1 або I
  • O — легко сплутати з 0
  • U — виключена для зменшення ймовірності образливих слів

Crockford Base32 нечутливий до регістру — рядкові <code>i</code>, <code>l</code>, <code>o</code> декодуються як їх візуальні аналоги.

ULID проти UUID

Порівняння ULID з UUID v4:

ВластивістьULIDUUID
Довжина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 з різними цілями:

ВластивістьULIDNanoID
Довжина26 символів21 символ (за замовчуванням)
Біти ентропії80 бітів126 бітів
Часова міткаТак (48-бітний мс)Ні
Лексикографічно сортованийТакНі
Користувацький алфавітНі (Crockford Base32)Так (налаштовуваний)
Нативна підтримкаНі (потрібна бібліотека)Ні (потрібна бібліотека)
Нативна підтримка в браузеріНіТак (Web Crypto API)

Обирайте ULID для часового порядку, NanoID — для коротших ID без часової мітки.

Підтримка баз даних

ULID зберігаються як текст або бінарні дані:

Первинні ключі баз даних
ULID забезпечують сортування для індексів з компактним представленням.
Подійне джерело та журнали подій
Хронологічний порядок подій без окремого поля часової мітки.
Розподілені системи
Кілька вузлів генерують ULID незалежно без координації.
URL та API
ULID безпечні для URL без кодування.
Сортовані черги повідомлень
Ключі черги, що гарантують обробку за часом.
Експорт даних та звітність
Записи з ULID можна лексикографічно сортувати за полем ID.

Приклади коду

ULID не стандартизований нативно. Використовуйте офіційний пакет:

JavaScript (ulid npm)
// 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)
Python (python-ulid)
# 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
PostgreSQL
-- 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;
JavaScript (pure — no dependencies)
// 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)
}

Часті запитання

Чи є ULID безпечним для URL?
Так. Символи Crockford Base32 (<code>0-9</code> і <code>A-Z</code> без <code>I</code>, <code>L</code>, <code>O</code>, <code>U</code>) безпечні для URL без процентного кодування.
Чи можуть два ULID збігтися?
У стандартному режимі вкрай малоймовірно: 80 бітів випадковості = 2<sup>80</sup> можливих значень у кожну мілісекунду.
Що таке монотонний режим ULID?
При генерації кількох ULID за одну мілісекунду випадковий компонент наступного інкрементується на 1. Гарантує суворий монотонний порядок.
Чи є ULID сумісним з UUID?
Двійково — так (128 бітів). Рядково — ні (Base32 vs hex із дефісами). Не змішуйте без явного перетворення.
Яке максимальне значення часової мітки ULID?
48-бітна часова мітка дозволяє представляти дати до 10889 року н.е.