Generate UUID v4 or v7 locally with the UUID Generator — no upload, no account.
Why sortable IDs matter
Random primary keys scatter inserts in B-tree and LSM indexes, causing page splits and write amplification. A time-ordered identifier keeps new values dense and inserts fast.
Both UUID v7 and ULID solve this the same way: they embed a 48-bit Unix timestamp in milliseconds at the start of the value.
UUID v7
UUID v7 is defined by RFC 9562. It uses the canonical hyphenated 8-4-4-4-12 format, a version nibble, a variant field, and about 74 random bits.
Its strength is ecosystem fit: any system that parses UUIDs today understands v7, and databases increasingly add native UUIDv7 support.
RFC 9562 pins the layout down precisely: the first 48 bits hold the Unix timestamp in milliseconds, followed by the version nibble (7), the variant field, and the remaining random bits. Because the timestamp sits at the front, byte-wise comparison of the 16-byte form matches creation order.
The spec also allows a monotonic counter to replace part of the random bits when several values share one millisecond, keeping bulk inserts in a stable order.
ULID
ULID (Universally Unique Lexicographically Sortable Identifier) encodes the same 48-bit timestamp plus 80 random bits into a 26-character Crockford Base32 string, typically uppercase.
It is not an RFC or UUID standard, but it is popular in JavaScript and Go ecosystems and sorts lexicographically in the same order as creation time.
Crockford Base32 deliberately drops the letters I, L, O and U so they cannot be confused with the digits 0 and 1, which is why 128 bits fit into 26 characters instead of the 36 a hyphenated UUID needs.
The spec includes a monotonicity rule: each new ULID within the same millisecond increments a counter, so sort order stays stable under bulk generation — useful in distributed systems where several processes share one clock.
Side by side
Where they part ways is the packaging. A hyphenated UUID is 36 characters and case-insensitive; a ULID is 26 characters, conventionally uppercase, and sorts as a plain string. The embedded timestamp is the same 48-bit millisecond value in both, so a value from either format can be decoded to a creation time — for example with the timestamp converter.
| Property | UUID v7 | ULID |
|---|---|---|
| Standard | RFC 9562 | Community spec |
| Format | 8-4-4-4-12, hyphenated | 26-char Crockford Base32 |
| Random bits | ~74 | 80 |
| Case sensitivity | Case-insensitive | Uppercase by convention |
| Ecosystem | UUID parsers everywhere | Growing, stack-specific |
What decides it
- Use UUID v7 when your database or tooling already understands UUIDs
- Use ULID when your stack already uses it or you want compact string keys
- For public-facing unguessable identifiers, keep using UUID v4
- Do not store UUIDs as strings in MySQL if you can use BINARY(16)
- For compact keys in URLs or cache prefixes, the 26-character ULID string is shorter than a hyphenated UUID
- Treat both as opaque: a sortable ID is not a secret, so keep v4 for tokens and unguessable values
FAQ
Q.Are ULIDs and UUID v7 compatible?
A.No, they use different encodings, so a ULID string is not a valid UUID and vice versa. A UUID is 16 bytes written as 36 hex characters with hyphens; a ULID is a 26-character Crockford Base32 string. They solve the same problem — time-ordered, collision-resistant IDs — but the formats are not interchangeable, and a parser for one will reject the other.
Q.Is ULID more sortable than UUID v7?
A.Both sort by the same 48-bit timestamp prefix, so the ordering behavior is equivalent. Lexicographic string ordering works directly on ULIDs; UUID v7 sorts when stored as bytes or compared as the canonical string. Because the timestamp comes first even in the canonical form, sorting the hyphenated string works too, but byte comparison is cheaper.
Q.Should I migrate from ULID to UUID v7?
A.Only if the migration cost is low and your ecosystem actually benefits from RFC 9562 parsing. The switch touches stored values, indexes, and any code that parses or displays IDs, so weigh that against what you gain. Both formats are valid choices; consistency within your system matters more than the format itself.
- A pragmatic middle ground is to keep ULID where it already exists and use UUID v7 for new tables.
References
- RFC 9562 – Universally Unique IDentifiers (UUIDs): https://www.rfc-editor.org/rfc/rfc9562
- ULID Specification: https://github.com/ulid/spec
- ULID JavaScript reference implementation: https://github.com/ulid/javascript
- uuid package (v7 support): https://github.com/uuidjs/uuid
Choose by ecosystem
If your database or ORM already handles UUIDs, v7 drops in with the least friction. If your stack is built around ULID, switching formats buys little.
Neither is a secret: keep UUID v4 for tokens and unguessable IDs, and generate either locally with the UUID Generator.
My own rule of thumb: pick the format your database and ORM already speak, then stick with it. Swapping formats later means migrating data and indexes, and that cost usually outweighs the differences.