
UUID vs ULID vs Nanoid: Which Unique ID Should You Use?
Random UUID v4, sortable UUID v7 and ULID, or compact customizable Nanoid: a comparison and online generators for primary keys, public IDs and tokens.
Random, sortable or compact IDs do different jobs
A plain auto-increment leaks how many rows a table has. It coordinates poorly across several servers writing at once, and it is guessable: ID 1042 implies that ID 1041 exists. That is why apps generate IDs on the client or the server, without a central counter. The words “unique and unpredictable” do not mean the same thing in every format. The UUID generator produces a random UUID v4, a UUID v7 that starts with a timestamp, or the nil UUID for tests. The ULID generator has the same goal as UUID v7, an ID that sorts by creation time, in a shorter Base32 string. The Nanoid generator leaves out the timestamp and spends every character on randomness, so the string is shorter for the same entropy. All three run in the browser and sit together on the developer utilities hub, next to the regex tester and the password generator.
Picking the right tool for the context
Prototyping, testing, and visual checks before writing any server-side code.
The online generator prototypes the format; it does not replace production-scale generation.
uuid, ulid, nanoid on Node) avoids any browser round tripMistakes that get expensive once you are in production
A primary key filled with UUID v4 values inserts each new row at a random place in the B-tree index. On a busy table, that splits pages and slows writes. The cause is pure randomness, not UUIDs as such. UUID v7 (RFC 9562) puts a millisecond timestamp in its leading 48 bits and fills the rest with random bits. ULID applies the same idea in Base32. New values then land at the end of the index, like an auto-increment, without exposing a usable counter. RFC 9562 notes that the gap can reach an order of magnitude or more. The UUID generator switches from v4 to v7 without changing the field shape (36 characters with hyphens). The ULID generator offers the shorter 26-character alternative.
Replacing an auto-increment with a UUID, ULID or Nanoid stops plain enumeration (trying ?id=124, then 125…). It does not check anyone's authorization. An ID can leak through a shared link, a log line or a referrer header. It then stays readable if the API does not verify who owns the resource. ULID adds a problem of its own. Its first 10 characters give away the creation time in plain sight. That is harmless for a primary key. For a token meant to stay opaque, it is a weakness. Anyone who roughly knows the creation time narrows the search before attacking the random part.
Nanoid's collision resistance depends on size and alphabet together. The tool's default, 21 characters from the 64-symbol URL-safe alphabet, carries 126 random bits, against 122 for a UUID v4. Every other setting changes that math. At 8 characters from the same alphabet, the odds of at least one collision reach 1% after about 2,400,000 IDs. The Numeric alphabet (10 symbols) shrinks the space too, since 21 digits give about 70 bits. Nothing warns you, apart from the entropy in bits shown by the info button next to the Size field.
The format switch of the UUID tool (plain, braces, URN) and the uppercase switch change the text, not the underlying 128 bits. A column that compares raw strings does not know that {550e8400-…} and urn:uuid:550e8400-… name the same UUID unless you normalize first. ULID has the same trap. Crockford Base32 ignores case on decode, but a UNIQUE constraint on a text column often compares case, as PostgreSQL does by default.
Format, size and sort order of the four variants
Same goal, uniqueness without a central coordinator, in four different shapes.
The real options on each tool, as they exist today.
Three concrete situations where the format choice has a measurable effect.
Generate, adjust, copy
On the UUID generator, the list is generated again as soon as you change an option, and there is no separate Generate button. On the ULID generator, the decoded timestamp of each ID appears right under its row.
1. Pick the version or the Monotonic option
On UUID, v4 gives pure randomness, v7 an order by time and nil the all-zero UUID, with the count fixed at 1. The v7 IDs of one list usually share a millisecond, so they are not ordered among themselves. On ULID, all IDs of a list share the same millisecond and come out in random order. Turn on Monotonic to get them in strictly ascending order.
2. Adjust hyphens, case and format
On UUID, the URN format forces hyphens and lowercase and disables both switches. On ULID, uppercase is on by default, and Crockford Base32 decodes the same in lowercase.
3. Set the count (1 to 50), then copy
Copy the whole list at once, download it as .txt, or copy one row at a time with the per-row button.
The Nanoid generator shows the entropy in bits in the tooltip of the info button next to Size. The value follows each change of size or alphabet, so you do not have to work it out by hand.
The same formats server-side, in Node
Node provides crypto.randomUUID() for a UUID v4, with no dependency. Since Node 24.16 and 26.1, crypto.randomUUIDv7() also produces a v7. On older versions, the small uuid package handles the sortable variant, as in this example.
Basic example
Node has no built-in ULID support. The ulid package generates ULIDs and decodes their embedded timestamp.
Basic example
The nanoid package uses the same URL-safe alphabet and default size as the tool (21 characters). Its customAlphabet function takes your own alphabet and size.
Basic example
No install, nothing uploaded, up to 50 IDs per list and every format option of the three tools. The limits: no high-throughput generation in the browser, no monotonic order across lists, tabs or processes, and a custom Nanoid alphabet capped at 256 characters. Use the pages to prototype a schema or produce fixtures, and keep uuid, ulid and nanoid on the server in production.
Conclusion
No identifier fits every case. UUID v4 remains the right call for a purely opaque ID with no sort requirement and the widest native support. UUID v7 or ULID take over once insertion order matters for index performance, or for sorting without a dedicated created_at column. Nanoid gives the shortest string for a given entropy, which helps in a URL. None of the three replaces a server-side authorization check. None is meant for high-throughput generation in the browser either, which is the job of the uuid, ulid and nanoid server libraries. If these IDs travel in an API's JSON payload, the guide on optimizing a JSON REST API is a natural next read. The JSON Schema validator then checks the expected shape of an id field.
Generate an ID in the browser
uuid, ulid, nanoid), not the browser generatorRelated Articles

Paste a token and a JWKS to check an RS256, ES256 or HS256 signature in your browser. How kid picks the key, measured errors and the claims to check.

HTTP/2 and HTTP/3 change how files travel, not how big they are. Measured sizes, compile times and bundling tests show what minification still saves.

Convert a Unix epoch to a readable date and back, tell seconds from milliseconds, and avoid time zone, JWT and clock change traps, all in your browser.