A practical guide to choosing the right identifier format for your project, with a decision matrix covering all 20+ formats on ksuid.net.
Need RFC compliance?
UUID v4 or UUID v7
Need time-sorting for database performance?
UUID v7, ULID, KSUID, TSID, Snowflake
Need the shortest possible ID?
Sqids, TSID, XID, Nano ID
Need to fit in a 64-bit integer column?
Snowflake, TSID
Need maximum collision resistance?
UUID v4, KSUID, CUID2
Need anti-fingerprinting protection?
CUID2
Need minimal client-side bundle?
Nano ID
| Format | Best For | Avoid When | Tier |
|---|---|---|---|
| cuid | Legacy apps already using CUID v1 | Starting new projects — use CUID2 or UUID v7 | Legacy |
| cuid2 | Security-sensitive apps needing anti-fingerprinting | You need time-sorted ordering or smallest bundle size | Recommended |
| ksuid | High-throughput event pipelines with second-level ordering | You need UUID-column compatibility or millisecond precision | Situational |
| nanoid | Client-side apps where bundle size matters | You need time-sorted ordering for database primary keys | Recommended |
| objectid | MongoDB-native applications | Building outside the MongoDB ecosystem | Legacy |
| pushid | Firebase/real-time database applications | You need standards compliance or very high collision resistance | Situational |
| scru128 | High-volume systems needing monotonic sortable IDs | You need broad library ecosystem or RFC backing | Recommended |
| shortid | None — deprecated, migrate to Nano ID | Always — it is deprecated and has known issues | Legacy |
| slugid | URL-safe identifiers in task queues | You need time-sorting or a widely adopted format | Legacy |
| snowflake | 64-bit integer keys with extreme throughput | Dynamic environments (serverless, K8s) without worker-ID coordination | Situational |
| sqids | Obfuscating sequential numeric IDs in URLs | You need true uniqueness — Sqids encode existing numbers | Situational |
| short-uuid | Compact display of existing UUIDs | You need generated IDs, not re-encoded UUIDs | Legacy |
| timeflake | UUID-compatible time-sorted IDs | You need monotonic guarantees within the same millisecond | Recommended |
| tsid | Compact 64-bit time-sorted primary keys | You need more than 64 bits of address space | Recommended |
| ulid | Time-sorted IDs with UUID-compatible storage | Standards compliance (RFC) is a hard requirement | Recommended |
| ulidx | Modern ULID with strict spec compliance | Standards compliance (RFC) is a hard requirement | Recommended |
| uniqid | None — use UUID v7 or TSID instead | Always — no cryptographic randomness, easy to predict | Legacy |
| uuid | RFC compliance and maximum ecosystem support | Database insert performance matters at scale | Situational |
| uuidv7 | New projects needing standards-compliant sortable IDs | Timestamp leakage is a privacy concern | Recommended |
| xid | Compact sortable IDs across Go/JS/Python ecosystems | You need cryptographic randomness or RFC standards | Situational |
Strong defaults for new projects. These formats use cryptographic randomness, are actively maintained, and offer modern features like time-sorting or anti-fingerprinting.
Examples: UUID v7, ULID, CUID2, Nano ID, SCRU128, TSID, Timeflake
Solid choices for specific use cases but with trade-offs. They may lack cryptographic randomness, require coordination, or have a narrower ecosystem.
Examples: UUID v4, KSUID, Snowflake, XID, Sqids, Push ID
Outdated or have known weaknesses. Avoid in new projects. If your existing system uses one, consider migrating when practical.
Examples: CUID v1, ShortId, ObjectId, Short-UUID, Slugid, Uniqid
For most new projects, UUID v7 is the best default choice. It combines the universal compatibility of the UUID format (128-bit, RFC 9562, native database support) with time-sorted ordering that dramatically improves database insert performance. If you need a more compact representation, ULID or TSID are excellent alternatives.
UUID v7 is the better choice for nearly all new systems. It offers the same format compatibility as UUID v4 but with time-sorted ordering that reduces B-tree index fragmentation and improves write throughput by 2-10x. UUID v4 remains appropriate only when you specifically need to avoid embedding any timestamp information in your identifiers.
Recommended (green) formats are strong defaults for new projects — they use cryptographic randomness, have active maintenance, and offer modern features. Situational (orange) formats are solid choices for specific use cases but have trade-offs that make them less universal. Legacy (red) formats are outdated or have known weaknesses and should generally be avoided in new projects.
UUID v7, ULID, and CUID2 are all excellent for distributed microservices because they require no coordination between nodes. UUID v7 and ULID add time-sorting for better database performance, while CUID2 provides anti-fingerprinting properties. Avoid Snowflake IDs in dynamic environments because they require worker-ID coordination.
Yes, and this is a common pattern. For example, you might use UUID v7 for database primary keys (time-sorted, standard format), Nano ID for user-facing short codes (compact, URL-safe), and Snowflake IDs for event streams (64-bit integer, high throughput). The key is to standardize within each bounded context to keep parsing and storage simple.
© 2024 Carova Labs. All rights reserved