CUID Generator logoCUID Generator

Architecture tool

Choose an ID from your requirements, not habit

There is no universally best identifier. Describe what the ID must do and get a recommendation with the constraints that could change the answer.

Recommendation

CUID2 (default 24 characters)

Best fit for compact, distributed public IDs

CUID2 is compact, lowercase, URL-friendly, and can be generated by disconnected clients or multiple application nodes without coordination. Keep the default length unless you have quantified a different collision budget.

Why this fits

  • Your writers do not need a round trip to reserve an ID.
  • The lowercase Base36 representation stays readable in routes and logs.
  • The default length provides a very large collision space without UUID punctuation.

Trade-offs to accept

  • CUID2 is not an IETF identifier standard and may lack a native database type.
  • It is intentionally not time-sortable; query an explicit created_at column.

Suggested database shape

id VARCHAR(24) PRIMARY KEY
created_at TIMESTAMPTZ NOT NULL DEFAULT now()

Generation starting point

import { createId } from "@paralleldrive/cuid2";
createId();

Before shipping

  1. 1Generate with the maintained @paralleldrive/cuid2 package.
  2. 2Keep 24 characters unless a documented collision analysis supports another length.
  3. 3Validate format at trust boundaries and enforce a unique or primary-key constraint.
  4. 4Treat IDs as public and enforce authorization separately.

How the recommendation is made

The advisor starts with the system boundary. A single primary database can coordinate a compact numeric key; offline clients and independent nodes cannot. It then separates public record identifiers from bearer secrets and checks whether ordering or standards compatibility is a hard requirement.

The result is deliberately conservative: it keeps timestamps in an explicit created_at column, keeps authorization separate from identifier opacity, and does not shorten random IDs without a collision analysis.

Important: An unguessable ID is defense in depth, not access control. Every request still needs an authorization decision.