Compared with other IDs
TNIDs carry a name like a prefixed ID and fit a UUID column like a UUID. Use them unless one of the exceptions applies.
| Format | Name in the bits? | Fits a UUID column? | Time-sortable? | String length | Case-sensitive string? |
|---|---|---|---|---|---|
| UUIDv4 | No | Yes | No | 36 | No |
| UUIDv7 | No | Yes | To the millisecond | 36 | No |
| ULID | No | As raw bits, without UUID version bits | To the millisecond | 26 | No |
| KSUID | No | No (160 bits) | To the second | 27 | Yes |
| TypeID | No, only in the string | Without the prefix | Usually, when it wraps a UUIDv7 | Prefix + 27 (31 for user) | Lowercase only |
Prefixed UUID, such as user_ + UUID | No, only in the string | Without the prefix | If the UUID is time-ordered | Prefix + 37 (41 for user) | Typically no |
| TNID | Yes, up to 4 characters | Yes (it is a UUIDv8) | TNIDv0, to the millisecond, per name | 19 to 22 | Yes |
- Name in the bits: a TypeID or prefixed UUID string stored in a
uuidcolumn reads back as a plain UUID, with no record of what it identifies. A TNID keeps its name in every form. - Fits a UUID column: native UUID type, 16-byte storage and indexes; passes through tools that expect UUIDs.
- Case-sensitive string: needs a binary collation when stored as text: Text columns.
When to use another ID format
These are uncommon. Pick something else if you need:
- Names over 4 characters, or characters other than
a–zand0–4. TypeID prefixes can have up to 63 characters. - Over about 100 trillion random TNIDv1s under one name. The chance of any collision is then about 1 in 250 for TNIDv1, and about 1 in a billion for UUIDv4.
- Very high volume per millisecond under one name, or creation order within a millisecond. Same-millisecond TNIDv0s are unordered; a million same-name TNIDs in one millisecond have about a 1 in 290,000 chance of a collision. Some UUIDv7 and ULID generators keep order with a counter.
- To pass validators you can't change that reject version 8, such as Yup's
string().uuid()or Hibernate's@UUIDdefault. Databases and standard parsers accept any version.