Back to BlogNode.js

Node.js 24.16.0 Adds crypto.randomUUIDv7(): The Practical Case for Time-Ordered IDs

Node.js 24.16.0 quietly added crypto.randomUUIDv7(), and it is one of those small LTS upgrades that can clean up real backend code fast. Here is when UUIDv7 is better than v4, where it helps, and the footguns to avoid.

nodejsuuidcryptobackendpostgres
Node.js 24.16.0 Adds crypto.randomUUIDv7(): The Practical Case for Time-Ordered IDs

Node.js 24.16.0 quietly shipped a backend-friendly upgrade

Node.js 24.16.0 LTS landed on May 21, 2026, and the headline most JavaScript backends should care about is small enough to miss: crypto.randomUUIDv7().

That addition matters more than it looks.

A lot of Node apps still do one of these three things:

  • use uuid just to generate IDs

  • use randomUUID() everywhere because it is built in

  • use auto-increment integers and then regret it once logs, sharding, imports, or public APIs get involved

UUIDv7 is a nice middle ground. You still get globally unique IDs, but now they are time-ordered enough to behave better in databases, logs, queues, and event streams.

If you run a Node backend on LTS and you generate a lot of identifiers, this is the kind of release that is actually worth using, even if the changelog does not look flashy.

Why UUIDv7 is more useful than UUIDv4 in real apps

crypto.randomUUID() gave Node a good built-in UUIDv4 story. The problem is that UUIDv4 is basically random soup. That is great for uniqueness, but not great for ordering.

With UUIDv4:

  • rows inserted into indexed tables are scattered more randomly

  • sorting IDs tells you nothing useful

  • tracing events by creation order gets messy

  • range queries on IDs are basically nonsense

UUIDv7 fixes that by embedding timestamp information while keeping enough randomness for uniqueness. In practice, that means newly generated IDs tend to sort in creation order.

For backend code, that is immediately useful.

Good fits for UUIDv7

  • public object IDs in REST or GraphQL APIs

  • event IDs in queues or append-only logs

  • order IDs, invoice IDs, job IDs, webhook delivery IDs

  • database primary keys when you want better locality than UUIDv4

Bad fits for UUIDv7

  • places where you specifically want IDs with zero time leakage

  • systems that already depend on a different ID shape like ULID, Snowflake, or KSUID

  • cases where “strictly increasing forever” is a hard requirement

That last point matters. In the Node 24.16.0 release notes, there is also a docs change noting the non-monotonic clock behavior around crypto.randomUUIDv7(). Translation: this is time-ordered, not magic. If the system clock moves weirdly, you should not pretend this is a globally strict sequence generator.

The immediate win: stop pulling a package for basic UUIDv7 generation

Before this release, the usual Node answer was “install a library.”

Now the built-in version is good enough for a lot of teams.

import { randomUUIDv7 } from 'node:crypto'

const id = randomUUIDv7()
console.log(id)

That is boring in the best way.

Less dependency surface for a tiny utility is usually the correct move. JavaScript teams have had enough supply-chain reminders lately. If the platform can do the job, the platform should do the job.

I would not rip out a mature shared ID utility blindly. But if that utility mostly wraps UUID generation and formatting, Node just made that abstraction a lot less valuable.

Where this helps most: database inserts and operational debugging

The strongest practical case for UUIDv7 is not “standards purity.” It is operational convenience.

Better index behavior than UUIDv4

When you use UUIDv4 as a primary key in PostgreSQL or MySQL, new rows land all over the keyspace. That can increase index churn and page splits compared with more sequential identifiers.

UUIDv7 is not perfectly sequential, but it is much friendlier to insertion order. For a busy write-heavy service, that is the difference between “UUIDs are fine” and “UUIDs are annoyingly expensive.”

Logs become easier to read

If your IDs are time-ordered, a raw grep across application logs becomes less annoying. You can often eyeball whether a webhook fired before a job retry or whether a child record was created before its parent workflow completed.

That sounds small until you are debugging a production incident at 2:13 a.m.

Cursor pagination gets less awkward

If your API sorts by creation time, UUIDv7 can sometimes reduce the awkwardness of carrying both created_at and a purely random ID as pagination tie-breakers.

You still need to design pagination carefully, but at least the identifier is no longer actively fighting you.

A migration pattern that does not create a mess

Do not rewrite every ID column in your database because one LTS release added a shiny function. That is how teams turn a good idea into a six-week migration tax.

A saner pattern is:

  • keep existing UUIDv4 records as-is

  • generate UUIDv7 for new records only where ordering helps

  • start with new tables, event stores, or append-heavy workloads

  • standardize on one helper so you can swap behavior later if needed

import crypto from 'node:crypto'

export function createId() {
  if (typeof crypto.randomUUIDv7 === 'function') {
    return crypto.randomUUIDv7()
  }

  return crypto.randomUUID()
}

That fallback is boring, but it buys you painless rollout across mixed Node versions.

If you are publishing a library, I would be even more conservative. Feature-detect it, do not force a hard runtime break unless you really need to.

The other Node 24.16.0 additions are nice, but this one changes everyday code

The same release also added things like test order randomization, fs.stat() signal support, req.signal on IncomingMessage, and edit-free runtime expression probes in node inspect.

Those are good additions. But randomUUIDv7() is the one that will leak into normal app code fastest.

It is the kind of API that ends up in:

  • your createUser() path

  • your background job IDs

  • your webhook event envelope

  • your audit log schema

  • your “temporary until we clean this up” util file that somehow survives four years

That is usually the sign a feature matters.

My take

This is one of those rare Node LTS upgrades that solves a real backend annoyance without asking you to buy into a framework, a new database, or a new architecture religion.

If you are on Node 24 LTS, 24.16.0 is worth a look for crypto.randomUUIDv7() alone. And if you want the implementation trail, the release notes point to the core change in nodejs/node#62553.

My opinionated version is simple:

  • keep randomUUID() for places where ordering does not matter

  • prefer randomUUIDv7() for new write-heavy backend paths

  • stop installing tiny UUID packages unless they are buying you something real

Not every useful release feature needs to be dramatic. Sometimes the win is just fewer dependencies, better inserts, and IDs that stop acting like static noise.