crypto.randomUUID()

Generates a cryptographically random RFC 4122 version 4 UUID as a 36-character string.

Signature
crypto.randomUUID([options])
  • Added in Node.js v15.6.0, v14.17.0

Parameters

ParameterTypeDescription
$optionsoptionalObjectOptional settings object.
$options.disableEntropyCacheoptionalboolean= falseBy default Node.js generates and caches enough random data to produce up to 128 UUIDs at a time. Set to true to bypass the cache and draw fresh entropy for every call.

Return value

stringA 36-character RFC 4122 version 4 UUID string in the canonical 8-4-4-4-12 hyphenated form.

Errors

Throws ERR_INVALID_ARG_TYPE if options is not an object, or ERR_INVALID_ARG_VALUE if disableEntropyCache is not a boolean.

crypto.randomUUID() is the built-in replacement for the uuid package when all you need is a version 4 identifier. It returns a string like 109156be-c4fb-41ea-b1b4-efe1671c5836: 32 hex digits in five hyphen-separated groups, with 122 bits of randomness drawn from the same CSPRNG that backs crypto.randomBytes().

When to reach for it

Use it for anything that needs an identifier no one can guess or enumerate: database primary keys, idempotency keys on a payment endpoint, request correlation IDs, filenames for uploaded objects. Because the value carries no timestamp and no machine identity, it leaks nothing about when or where it was created.

What trips people up

Version 4 UUIDs are deliberately unordered. Using one as a clustered primary key in MySQL or SQL Server scatters inserts across the whole B-tree and wrecks write throughput on large tables. If you need identifiers that sort by creation time, use a time-ordered scheme instead — Node 24.16.0 and 26.1.0 added crypto.randomUUIDv7() for exactly this.

The other surprise is the entropy cache. Node pre-generates enough randomness for 128 UUIDs to keep the call fast. That is a pure performance optimisation and does not weaken the output, but in a process that only ever needs one or two UUIDs the buffer is wasted memory, which is what disableEntropyCache: true exists to avoid.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Generating an idempotency key so a retried payment request is not charged twice
  • Creating a correlation ID attached to every log line for one HTTP request
  • Naming an uploaded file in object storage so it cannot collide or be guessed
  • Producing primary keys client-side before a row is ever sent to the database

Frequently asked questions

Do I still need the uuid npm package in Node.js?

Not for version 4 UUIDs — crypto.randomUUID() has been built in since Node 14.17.0 and 15.6.0 and produces the same RFC 4122 v4 format. You still need the package if you want v1, v3 or v5 UUIDs, or if you must parse and validate UUIDs, none of which the built-in covers.

Is crypto.randomUUID() safe to use as a security token?

Yes, it is generated by a cryptographic pseudorandom number generator and carries 122 bits of randomness, which is far beyond guessable. It is a reasonable session or capability token, though for a bearer token most people prefer crypto.randomBytes(32).toString('base64url') because it packs more entropy into fewer characters.

Why are my UUID primary keys making the database slow?

Version 4 UUIDs are random, so consecutive inserts land at random points in a clustered index and force constant page splits. Either use a non-clustered UUID column with a separate sequential clustering key, or switch to a time-ordered identifier such as crypto.randomUUIDv7().

More examples

Idempotency keys for a retried request

The key is created outside the retry loop. If it were generated inside, every retry would look like a brand new charge to the server and the customer could be billed three times. The output is just the function type — the request itself needs network access.

Example · javascript
import crypto from 'node:crypto';

// Generate the key ONCE, before the first attempt. Reuse it on every retry
// so the server can recognise the duplicate and return the original result.
async function chargeCard(amountCents) {
  const idempotencyKey = crypto.randomUUID();

  for (let attempt = 1; attempt <= 3; attempt++) {
    try {
      const res = await fetch('https://api.example.com/charges', {
        method: 'POST',
        headers: {
          'content-type': 'application/json',
          'idempotency-key': idempotencyKey,
        },
        body: JSON.stringify({ amountCents }),
      });
      if (res.ok) return res.json();
    } catch (err) {
      if (attempt === 3) throw err;
    }
  }
}

console.log(typeof chargeCard);

Correlation IDs in an Express request logger

Every log line for a single request carries the same id, so a slow or failing request can be traced across services by grepping one value. Echoing it back in the x-request-id response header lets a client quote the id in a bug report. This needs a listening server, so it is shown rather than run.

Example · javascript
const crypto = require('node:crypto');
const express = require('express');

const app = express();

app.use((req, res, next) => {
  // Honour an ID from an upstream proxy if there is one, otherwise mint one.
  req.id = req.get('x-request-id') || crypto.randomUUID();
  res.setHeader('x-request-id', req.id);

  const start = process.hrtime.bigint();
  res.on('finish', () => {
    const ms = Number(process.hrtime.bigint() - start) / 1e6;
    console.log(JSON.stringify({
      id: req.id,
      method: req.method,
      path: req.path,
      status: res.statusCode,
      ms: Math.round(ms),
    }));
  });
  next();
});

app.get('/orders/:id', (req, res) => res.json({ ok: true }));

console.log('routes registered:', app._router === undefined ? 'lazy' : 'eager');

Skipping the entropy cache

Both UUIDs are equally unpredictable. disableEntropyCache only changes where the bytes come from, trading a little speed for a smaller resident buffer — worth setting in a short-lived process or a memory-constrained worker that mints one or two IDs and exits.

Example · javascript
const crypto = require('node:crypto');

// Default: Node pre-generates randomness for up to 128 UUIDs at a time.
const cached = crypto.randomUUID();

// Bypass that buffer and read fresh entropy for this one call.
const uncached = crypto.randomUUID({ disableEntropyCache: true });

console.log('both are valid v4 UUIDs:', cached[14] === '4' && uncached[14] === '4');
console.log('both are 36 chars:', cached.length === 36 && uncached.length === 36);
console.log('they differ:', cached !== uncached);

// Neither value is more or less random than the other — the cache is purely
// a throughput optimisation, not a reduction in entropy.
console.log('same format:', /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(uncached));

Discussion

  • Be the first to comment on this lesson.