Which ID format should I use?
Almost every choice here comes down to one question: does the ID need to sort by creation time, and are you willing to publish that time to anyone who sees it?
| Format | Length | Sorts by time | Timestamp | Entropy | Best for |
|---|---|---|---|---|---|
| UUID v4 | 36 characters | No | None | 122 bits | The default when you have no reason to want anything else |
| UUID v7 | 36 characters | Yes | Milliseconds since 1970-01-01 | 74 bits | A database primary key you want to insert in order |
| UUID v1 | 36 characters | No | 100 nanoseconds since 1582-10-15 | MAC + clock | Reading values other systems already minted; v7 replaces it |
| UUID v6 | 36 characters | Yes | 100 nanoseconds since 1582-10-15 | MAC + clock | Migrating a v1 estate to something that sorts |
| UUID v5 | 36 characters | No | None | Deterministic | The same input always needing to produce the same ID |
| ULID | 26 characters | Yes | Milliseconds since 1970-01-01 | 80 bits | A sortable ID that has to look tidy in a URL |
| KSUID | 27 characters | Yes | Seconds since 2014-05-13 | 128 bits | Sortable with more randomness than a ULID, at second precision |
| TypeID | 26 characters plus the prefix | Yes | Milliseconds since 1970-01-01 | 74 bits | Telling at a glance which table an ID came from |
| ObjectID | 24 characters | Roughly | Seconds since 1970-01-01 | 40 bits + counter | MongoDB, where it is already the default |
| Snowflake | up to 19 digits | Yes | Milliseconds since a custom epoch | Coordinated, not random | One system that can assign every worker a unique number |
| Nano ID | 21 characters by default, tunable | No | None | 126 bits | Short, opaque, URL-safe public identifiers |
| Cuid2 | 24 characters by default, tunable | No | None | Hashed, unstated | When leaking creation time or ordering would be a problem |
Start here
If you are storing the ID in a database and you control the schema, use UUID v7. It is a real UUID, so every database and language already has a type for it, and because the timestamp leads, new rows land at the end of the index instead of scattering across it.
If the ID will be shown to people who should not be able to work out when it was made, or count how many you have issued, use UUID v4 or Nano ID.
What sortable really costs
Every format in the sortable column publishes its creation time. Anyone holding the ID can read it, and two IDs made moments apart differ only in their random half.
That is fine for a primary key and bad for a password reset link. No ID on this site is a secret, but the sortable ones leak more than the rest.
Length is not the same as entropy
A ULID is 26 characters against a UUID's 36, and holds the same 128 bits. The difference is base32 against hexadecimal, not information. A Nano ID is shorter still and carries more randomness than a UUID v7, because it spends none of its bits on a timestamp, a version or a variant.
Once you are past roughly 64 bits of randomness, collisions stop being the thing worth worrying about. Pick on what the ID has to do, not on how many bits it has.
A note on databases
Store a UUID in a real 16-byte UUID column where one exists. Storing it as a 36-character string more than doubles the size of the column and every index that touches it.
SQLite and MySQL have no UUID type. In SQLite a BLOB works, and in MySQL BINARY(16) does. Both are worth the small conversion cost at the edges.