SCRU128: my new favorite way to do IDs

I’ve recently switched a bunch of my projects over to SCRU128 (Sortable, Clock and Random number-based Unique identifier), replacing UUIDv4 and earlier experiments with ULID and KSUID, and it’s been one of those small changes that quietly improves everything.

Rationale #

Traditional UUIDv4 provides strong uniqueness but lacks temporal ordering, leading to index fragmentation and poor locality for time-based database queries. There are alternatives like ULID which offer millisecond timestamps and basic monotonicity, but their 80-bit randomness can result in non-strict ordering under high-frequency generation. KSUID, originally authored in 2017 by Segment, provides 128 random bits but uses 160 bits altogether, has relatively poor timestamp resolution, and is longer with its 27-character strings.

SCRU128 deals with these limitations while maintaining a 128-bit size:

  • 48-bit Unix millisecond timestamp (range: 1970 to 10889).
  • 80-bit layered randomness (24-bit counter_hi randomized per second, 24-bit counter_lo for per-millisecond increments, 32-bit fresh entropy).
  • Guarantees strict monotonic ordering within the same millisecond, supporting up to about 281 trillion time-ordered IDs per millisecond.
  • 25-digit Base36 textual representation (case-insensitive, lexicographically sortable).
  • Binary form is a 128-bit unsigned integer, also sortable chronologically.

Benefits & Drawbacks #

Benefits:

  • Storage and index size match UUID (16 bytes binary, 25 characters text).
  • Strong monotonicity handles high-throughput bursts better than ULID.
  • Decentralized generation with negligible collision risk.

Drawbacks:

  • Brief pauses during significant clock rollbacks (which is handled gracefully in implementations).
  • Less popular and newer compared to UUID/ULID, which means people might need a quick explanation.

Conclusion & Spec #

Overall, SCRU128 provides a balanced, UUID-compatible upgrade for applications needing time-sortable, monotonically increasing identifiers without coordination.

For more details, read through the spec at https://github.com/scru128/spec.