ULID জেনারেটর
লেক্সিকোগ্রাফিকভাবে সর্টযোগ্য ইউনিক ID তৈরি করুন
ULID তৈরি করতে জেনারেট বাটনে ক্লিক করুন
What is a ULID?
ULID (Universally Unique Lexicographically Sortable Identifier) is a 128-bit identifier format designed to be both unique and naturally sortable. Unlike UUID v4, which is entirely random, a ULID embeds a millisecond-precision Unix timestamp in its high bits — ensuring that IDs generated later sort after IDs generated earlier.
ULIDs are encoded using Crockford's Base32 alphabet, producing a compact 26-character string that is URL-safe, case-insensitive, and free of visually ambiguous characters.
The ULID specification was created by Alizain Feerasta and is widely used in distributed systems, event sourcing, and database primary keys where both uniqueness and time-ordering matter. ULIDs are not an IETF standard — they are a community specification available at ulid.github.io.
ULID Structure
A ULID is 128 bits wide, divided into two components:
| Timestamp | Random |
|---|---|
| 01ARZ3NDEK | TSVE4RRFFQ69G5FAV |
| 48 bits — Unix timestamp in milliseconds. Encodes the generation time with 1ms precision. Covers dates until the year 10889. | 80 bits — cryptographically secure random data. Regenerated fresh for each ULID (unless monotonicity mode is used). |
Encoded as 26 Crockford Base32 characters: the first 10 characters represent the timestamp, the last 16 characters represent the random component.
Crockford Base32 Alphabet
ULIDs use Crockford's Base32 encoding, which uses 32 of the 36 alphanumeric characters. The alphabet is: 0123456789ABCDEFGHJKMNPQRSTVWXYZ
Four characters are intentionally excluded:
IandLare excluded — easily confused with the digit1Ois excluded — easily confused with the digit0Uis excluded — avoids accidental obscene words in generated IDs- The encoding is
case-insensitive—01ARZ3NDEKTSV4RRFFQ69G5FAVand01arz3ndektsv4rrffq69g5favare the same ULID
Crockford Base32 is more efficient than hexadecimal (32 symbols vs 16) and more human-readable than Base64 (no + / = characters, case-insensitive).
ULID vs UUID
ULIDs and UUIDs both represent 128-bit identifiers, but differ significantly in encoding and design goals:
| Property | ULID | UUID |
|---|---|---|
| Format | Crockford Base32 | Hyphenated hex |
| Length | 26 characters | 36 characters |
| Timestamp | 48-bit Unix ms | None (v4) or 48-bit ms (v7) |
| Sortable | Yes — lexicographic | No (v4) / Yes (v7) |
| URL-safe | Yes (alphanumeric only) | Yes (with hyphens) |
| Dependencies | Requires library | Native (crypto.randomUUID) |
| DB support | Store as CHAR(26) or BINARY(16) | Native UUID column type |
| Spec | Community spec (ulid.github.io) | RFC 4122 / RFC 9562 |
If you are already in a UUID ecosystem (PostgreSQL uuid columns, REST APIs, ORMs with UUID support), UUID v7 is usually a better fit than ULID. If you prefer a more human-friendly encoding and control the full stack, ULID is an excellent choice.
ULID vs nanoid
Both ULID and nanoid produce short, URL-safe identifiers, but they have different design goals:
| Property | ULID | NanoID |
|---|---|---|
| Timestamp | Yes — 48-bit Unix ms | No |
| Sortable | Yes | No |
| Default length | 26 characters | 21 characters |
| Entropy | 80 bits (random component) | ~126 bits |
| Alphabet | Crockford Base32 (32 chars) | URL-safe Base64 (64 chars) |
| Customizable length | No | Yes (any length) |
| Use case | Time-ordered IDs, DB primary keys | Random tokens, short URLs, API keys |
Choose ULID when you need time-ordering. Choose nanoid when you need maximum entropy in a short, random string.
Using ULIDs in Databases
ULIDs can be stored in databases in several ways depending on your requirements:
Code Examples
ULID generation requires the ulid library (available for JavaScript, Python, Go, Rust, and more):
// 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)
}