uuidulidnanoididsidentifiersdevtools

nanoid vs UUID vs ULID: Choosing an ID Format

·8 min read·Developer Tools

The ID you pick shows up everywhere

Identifiers leak into your URLs, your JSON payloads, your database indexes, and your logs — so the format you choose has real ergonomic and performance consequences. "Just use a UUID" is a fine default, but UUID v4 is random, ugly in URLs, and can hurt database write performance at scale. ULID and nanoid exist to fix specific pain points UUID v4 has. Here's how the three compare and when each is the right call. For the two UUID versions specifically, see UUID v4 vs v7.

UUID: the universal standard

A UUID is a 128-bit identifier, written as 36 characters: f47ac10b-58cc-4372-a567-0e02b2c3d479. Its strength is ubiquity — every language, database, and framework understands UUIDs natively, and crypto.randomUUID() generates v4 in one call.

  • UUID v4 is fully random. That's great for unguessability but bad for databases: random values scatter inserts across a B-tree index, causing page splits and fragmentation that slow high-volume writes.
  • UUID v7 fixes exactly that by making IDs time-ordered — a millisecond timestamp prefix plus randomness — so new rows insert at the "end" of the index and stay roughly sortable by creation time. In 2026, v7 is the recommended default for database primary keys.

The downsides that remain: 36 characters is long, the hyphens and format aren't URL-pretty, and it's not the most compact option.

ULID: sortable and more compact

A ULID (Universally Unique Lexicographically Sortable Identifier) is also 128 bits but encoded as 26 Crockford Base32 characters: 01ARZ3NDEKTSV4RRFFQ69G5FAV. It's built around two properties UUID v4 lacks:

  • Lexicographically sortable. The first 48 bits are a timestamp, so sorting ULIDs *as strings* sorts them by creation time — no separate created_at needed for ordering.
  • More compact and URL-safe. 26 characters vs 36, no hyphens, case-insensitive Base32, and it's safe to drop into a URL.

ULID overlaps heavily with UUID v7 (both are time-ordered 128-bit IDs). The practical difference: UUID v7 keeps the standard UUID format (so your database's native uuid type and tooling just work), while ULID gives you a shorter, prettier string at the cost of not being a "real" UUID. If your stack has first-class UUID support, v7 is usually the smoother choice; if you want compact, human-manageable IDs in URLs, ULID is attractive.

nanoid: tiny, random, configurable

nanoid takes a different goal: the *smallest* URL-friendly random ID. It's not 128 bits by default — you choose the length. The default is 21 characters from a 64-symbol URL-safe alphabet (V1StGXR8_Z5jdHi6B-myT), which gives a collision resistance comparable to UUID v4 in far fewer bytes.

  • Compact and URL-safe by design — ideal for public-facing short IDs, share links, and slugs.
  • Configurable — pick your own alphabet (e.g. only lowercase, or no look-alike characters) and length to trade size against collision odds.
  • Purely random, so like UUID v4 it is not sortable and not time-ordered.

nanoid is the pick when you want short, opaque, random IDs and don't need time ordering.

Side-by-side

UUID v4UUID v7ULIDnanoid
Length36 chars36 chars26 chars21 (configurable)
Bits128128128configurable
Time-ordered / sortableNoYesYesNo
URL-friendlySo-soSo-soYesYes
DB primary keyPoor at scaleExcellentGoodOK
Native DB supportUniversalGrowingVia stringVia string
Best forLegacy defaultDB keysSortable, compact IDsShort public IDs

How to choose

  1. Database primary key at scale?UUID v7 (time-ordered, native UUID type, no index fragmentation). ULID if you specifically want the shorter string form.
  2. Short, opaque, public-facing ID (share links, slugs)? → nanoid.
  3. Need creation-time ordering baked into the ID?UUID v7 or ULID.
  4. Maximum compatibility, don't care about the downsides?UUID v4 — still a perfectly reasonable default for low write volume.

The one habit worth breaking is reaching for UUID v4 as a database key by reflex — at high insert rates, v7 or ULID will save you real index pain. To generate identifiers now, use the UUID generator; for the timestamp mechanics behind v7 and ULID, see Unix timestamps.

Frequently asked questions

Prefer v7. UUID v4 is fully random, which scatters inserts across the index and causes fragmentation and page splits at high write volume. UUID v7 is time-ordered, so new rows append near the end of the index and stay roughly sortable by creation time.

Both are 128-bit, time-ordered identifiers. UUID v7 keeps the standard 36-character UUID format so native database UUID types and tooling work directly. ULID uses a shorter 26-character Base32 string that's more URL-friendly but isn't a standard UUID.

Use nanoid when you want a short, URL-safe, opaque random ID — for share links, public slugs, or anywhere the 36-character UUID is too long. nanoid is configurable in length and alphabet but, like UUID v4, is not time-ordered or sortable.

ULID is sortable — its timestamp prefix means sorting the strings sorts by creation time. nanoid is purely random and therefore not sortable. If you need ordering, choose ULID or UUID v7.

Yes. UUID v4 has universal support and strong unguessability, and it's fine for many applications, especially at modest write volumes. The main reason to switch is database write performance at scale, where a time-ordered format like UUID v7 or ULID performs better.

Try JSONKit — JSON Developer Tools

Format, validate, convert and diff JSON. Instant, accurate and 100% private.