Skip to content

Generators

ULID & NanoID Generator

Sortable ULIDs and tiny NanoIDs — generated client-side.

Runs in your browser

Sortable, timestamp-prefixed identifiers.

GenerateULIDs

    ULIDs sort lexicographically by creation time — handy for time-ordered keys.

    Understanding ULID and NanoID

    UUIDs, but for the database we actually use.

    Why UUIDv4 is bad for B-tree indexes, what ULID and NanoID change, and the tradeoff between sortability and uniformity.

    The UUIDv4 problem.

    UUIDv4 is purely random — every byte unrelated to every other. Great for collision resistance, terrible for B-tree indexes: each new row gets a key that lands in a random page of the index, forcing the database to load and rewrite pages all over the disk. On large tables this destroys insert performance. The alternatives are sortable IDs that pack a timestamp into the high-order bits so new rows always append to the end of the index.

    ULID — sortable + random.

    A ULID is 128 bits: 48 bits of timestamp (milliseconds since 1970), 80 bits of random. Encoded as 26 Crockford-base32 characters — no I/L/O/U, case-insensitive, human-keyboardable. Sorting ULIDs lexically is the same as sorting by creation time within a millisecond; same-millisecond IDs sort by their random tail. The insert pattern is "append at the end of the index", which is what databases like.

    ULID = 48-bit timestamp · 80-bit random

    NanoID — small + uniform.

    NanoID is purely random but optimised for compactness and URL safety. Default 21 characters from a 64-character alphabet — same collision space as UUIDv4 but shorter and URL-safe without quoting. It doesn't carry a timestamp, so it doesn't help with index locality, but it's perfect for slugs, share tokens, public IDs where you want something compact that isn't guessable.

    A worked comparison.

    UUIDv4 (36 char): f47ac10b-58cc-4372-a567-0e02b2c3d479 ULID (26 char): 01HXY7QRWZGKMP3D5KFNQTV8E2 NanoID (21 char): V1StGXR8_Z5jdHi6B-myT Same uniqueness guarantee, three different storage shapes. ULID's first 10 characters are a sortable timestamp prefix; NanoID is shorter and URL-safe; UUIDv4 is the universal-but-suboptimal default.

    When to pick which

    time-ordered insert vs short share token

    ULID for primary keys; NanoID for URL slugs.

    postgres PK → ULID ; share URL → NanoID

    = Pick by use case

    UUIDv7, the standardised middle.

    UUIDv7 (RFC 9562, 2024) is the standardised successor: same time-prefix idea as ULID, but packaged as a UUID (36 characters, hyphenated, drop-in for existing UUID columns). Most modern databases and libraries now have UUIDv7 support. If you can adopt it, UUIDv7 is the cleanest answer for new primary keys; ULID is the equivalent in a different encoding.

    Information leakage.

    A time-ordered ID encodes "when was this record created" — sometimes desirable, sometimes not. An attacker who sees two of your IDs can derive their order; sees one of yours and one from earlier and they can estimate your creation rate. For internal IDs, fine. For public-facing IDs, NanoID (or a separately-issued public token) hides that information.

    Collision math.

    A 21-character NanoID with a 64-character alphabet has 64²¹ ≈ 2¹²⁶ possible values. A ULID has 80 bits of randomness per millisecond. Both make collision-by-chance a non-issue at any realistic scale — you'd need to generate 10¹⁹ NanoIDs before the probability of a collision rose above one in a billion. The longer alphabet variant of NanoID is rarely worth using; the default size is plenty.

    Frequently asked questions

    Quick answers.

    What is the difference between ULID and NanoID?

    ULIDs include a timestamp for chronological sorting, whereas NanoIDs are purely random. ULID has a fixed format, while NanoID allows for custom lengths and character sets.

    Are these identifiers safe to use for database keys?

    Yes. ULIDs are particularly useful as primary keys because their chronological ordering helps maintain database index performance. NanoIDs are safe for public URLs where brevity is preferred.

    Is any data sent to your servers?

    No. Generation occurs entirely within your browser using the `crypto.getRandomValues` API. No identifier generated here is ever transmitted or logged.

    Can I customise the NanoID output?

    Yes. You can adjust the length and the alphabet to remove ambiguous characters like `1`, `l`, `0`, or `O` depending on your requirements.

    People also search for

    Related tools

    More in this room.

    See all in Generators