Skip to content
Generate now

ULID vs UUID: Sortable IDs for Database Keys

Random UUIDs solved the problem of generating unique IDs without a central counter, but they brought a hidden cost: databases hate inserting keys in random order. ULIDs keep the uniqueness and add a timestamp at the front, so new IDs sort after old ones. This guide explains why that matters for performance, how a ULID is built, and how it compares with the newer, time-ordered UUID version 7.

Options

Tip: press Enter or Space to generate again.

Ready

Why random keys can slow databases down

Most relational databases store primary keys in a B-tree index. When keys arrive in increasing order, new entries go to the end of the index, which keeps pages full and caches warm. Random keys such as UUID v4 land anywhere in the tree, so the database touches many different pages, splits them more often and leaves them partly empty. On small tables you will never notice; on large, write-heavy tables the difference can be significant.

Time-ordered IDs keep the advantages of client-side generation while behaving much more like an auto-increment counter inside the index.

How a ULID is built

A ULID is 128 bits, the same size as a UUID, split into two parts:

  • 48-bit timestamp โ€” milliseconds since the Unix epoch, placed first.
  • 80 random bits โ€” making IDs created in the same millisecond unique.

It is written as 26 characters of Crockfordโ€™s Base32: digits and uppercase letters without I, L, O and U, so it is case-insensitive and hard to misread. The first 10 characters encode the time, and the last 16 are random. Because the time comes first, sorting ULIDs as plain strings also sorts them by creation time.

ULID, UUID v4 and UUID v7 compared

  • UUID v4 โ€” 122 random bits, 36 characters, no ordering. Universally supported.
  • ULID โ€” 48-bit time plus 80 random bits, 26 characters, sortable as text. Defined by a community specification.
  • UUID v7 โ€” standardized in 2024, it also puts a millisecond timestamp first, but keeps the familiar UUID layout so it fits native uuid columns.

A ULID can be converted to the 16-byte binary form and stored in a UUID column, but the text representations differ. If your stack already speaks UUID everywhere, v7 is the smoothest path to ordered keys; if you want shorter, readable strings, ULID is a great fit.

How to generate ULIDs with the tool

The generator above creates valid ULIDs in your browser, using the Web Crypto API for the random part:

  1. Set how many you need โ€” up to 200 in one batch.
  2. Generate and look at the output: IDs created in the same moment share their first ten characters, because they share a timestamp.
  3. Copy them into seed scripts, migrations, log fixtures or API test requests.
  4. Export as CSV, JSON or TXT to keep a reusable set of test keys.

Nothing is uploaded or stored, so you can use the IDs immediately.

Things to keep in mind

A ULID reveals roughly when a record was created, because anyone can decode the timestamp. That is useful for debugging but may be unwanted in public URLs. Clock differences between servers mean ordering across machines is approximate, not exact. And within a single millisecond the random part decides the order, unless your library implements the optional monotonic mode, which increments the random part instead.

Practical uses beyond primary keys

The sortable layout makes ULIDs useful in several other places:

  • Log and event streams โ€” IDs double as rough timestamps, so events can be ordered and paged without an extra index.
  • Object storage keys โ€” files named with ULIDs list in creation order in most storage browsers.
  • Message queues โ€” consumers can spot out-of-order or duplicate messages by comparing IDs.
  • Cursor pagination โ€” โ€œgive me everything after this IDโ€ works naturally because later IDs sort higher.

In each case, the ID carries ordering information for free, which simplifies schemas and queries.

Pro tips

  • Store ULIDs as 16-byte binary values when space and index size matter.
  • Do not rely on ULIDs for exact ordering across different servers.
  • Avoid exposing ULIDs publicly if creation times are sensitive.
  • Keep ULIDs uppercase in text form for consistency, even though decoding is case-insensitive.
  • Benchmark inserts with your real table and data volume before switching key formats, rather than relying on general advice.

Frequently asked questions

Can I extract the creation time from a ULID?

Yes. Decoding the first 10 characters from Base32 gives the millisecond timestamp at which the ID was generated.

Are ULIDs safe for distributed systems?

Yes. With 80 random bits per millisecond, separate machines can generate IDs independently with a negligible chance of collision.

Should I migrate existing UUID v4 keys to ULIDs?

Usually not. Migrating keys is costly and risky; consider time-ordered IDs for new tables where insert performance matters.

Try a generator

Random Address Generator

Realistic street addresses with valid-format postal codes and phone numbers for 40 countries.

Fake Identity Generator

Complete fictional person profiles: name, birthday, address, phone, email, job and more.

Need random data? Get it now.

Pick any of 144 generators, hit Generate and copy or export the results as CSV, JSON or TXT. No account, no limits, nothing stored.

Start generating โ€” free