uniku
Guides

Choosing an ID

Choose for the system boundary, not the trend.

Different identifiers optimize for different constraints. Start with the boundary the value crosses: database index, URL, public API, MongoDB collection, or a native integer column.

SituationChooseWhy
Database primary keysUUID v7 or ULIDTime-ordered values improve index locality.
Public API resourcesTypeIDUUID v7 with a readable, domain-specific prefix.
Short URLs and invite codesNanoidCompact and URL-safe.
Values that should resist enumerationCUID v2Non-sequential, secure identifier.
MongoDB _id compatibilityObjectIDMatches MongoDB's 12-byte ObjectID format.
Go rs/xid compatibilityXIDMatches rs/xid's compact 12-byte text and binary format.
Native BIGINT storageTSIDA sortable 64-bit integer, not a UUID-shaped string.
Broad standards compatibilityUUID v4The conventional random UUID format.

A good default

If you create records in more than one service or need an ID before inserting a row, start with UUID v7. It is a UUID-native value, sort-friendly, and uses a familiar database column type.

import { uuidv7 } from 'uniku/uuid/v7'

const orderId = uuidv7()

Time ordering is local

UUID v7, ULID, ObjectID, XID, and TSID carry time information. uniku keeps the state required for monotonic sequencing inside one JavaScript isolate; it does not coordinate clocks or sequences between processes or machines.

Time order leaks creation time

UUID v7, ULID, KSUID, ObjectID, XID, and TSID embed a creation timestamp in the identifier itself. Anyone who can read the ID can decode when the record was created, not just its order relative to other records. That is a feature for index locality and a leak if the ID is public and the creation time is sensitive, for example a document, invoice, or account that should not reveal how old it is. If the identifier is exposed outside your system and creation time must stay private, use UUID v4, CUID v2, or Nanoid instead: none of them encode a timestamp.

On this page