A UUID is a 128-bit identifier written as 32 hexadecimal digits, like 0192f4c1-7a3e-7b21-9c4d-5e6f7a8b9c0d. Both version 4 and
version 7 are safe to generate without coordination between machines. The difference is what the bits contain, and that difference matters
most once UUIDs become database primary keys.
How the two versions are built
UUID v4: random
A v4 UUID is 122 random bits plus 6 fixed bits that mark the version (4) and variant. The third group always starts with
4: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx. With a good random source, the chance of two v4 UUIDs colliding is negligible
for any real system.
UUID v7: time-ordered
UUID v7, standardised in RFC 9562 (2024), starts with a 48-bit Unix
timestamp in milliseconds, then the version (7), then random bits. Because the timestamp comes first, v7 UUIDs generated
later sort after ones generated earlier — as plain strings or bytes.
0192f4c1-7a3e-7… ← created at 2024-11-04 01:19:33.438 UTC
0192f4c1-7a41-7… ← 3 ms later: sorts after the first
Why ordering matters for databases
Most relational databases store a table's primary key in a B-tree index. When keys arrive in increasing order, each insert lands at the right-hand edge of the index. When keys are random (v4), each insert lands somewhere random, which:
- splits index pages more often, leaving them partly empty (a larger index);
- touches pages all over the index instead of the few "hot" ones that stay in memory, which hurts once the index outgrows RAM;
- in MySQL/InnoDB, where rows are stored in primary-key order, scatters the table data itself.
v7 keeps most of the benefit of a sequential integer — inserts are roughly append-only — while still being generated anywhere without a central
counter. A side benefit: ORDER BY id approximates creation order.
What each version reveals
- v7 leaks its creation time to the millisecond. Anyone holding the ID can read when the record was created. For most records that is harmless; for some (account sign-up time, document creation in a sensitive context) it may not be.
- v4 reveals nothing — it is random. But neither version is a secret: do not use a UUID as an access token or password-reset code. Use a dedicated random token for that.
- v1, the older time-based version, embeds a timestamp and traditionally a MAC address. It is rarely the right choice for new systems.
How to choose
| Situation | Use |
|---|---|
| Primary key in a large or fast-growing table | v7 |
| Public identifier where creation time must not be inferable | v4 |
| Event or log IDs you want roughly time-sorted | v7 |
| Idempotency keys, correlation IDs, test fixtures | v4 (either works) |
| Secret tokens (password reset, API keys) | Neither — use a random token of 128+ bits |
A common pattern combines both: an internal time-ordered key for the database, and a separate random public ID exposed in URLs. Smart Edu,
for example, exposes only a public_id UUID in its API and never the internal numeric ID.
Generating UUIDs
- PHP / Laravel:
Str::uuid()(v4) andStr::uuid7()(v7, in recent Laravel 11 and 12 releases). - JavaScript:
crypto.randomUUID()gives v4 in browsers and Node; v7 needs a library or a few lines of code. - PostgreSQL:
gen_random_uuid()gives v4; PostgreSQL 18 adds a nativeuuidv7().
The UUID Generator on Zerethon Tools generates v1, v4, v7 and the
all-zero Nil UUID — up to 10,000 at once — in the browser, using crypto.getRandomValues() for the random bits rather than
Math.random(). To check when a v7 UUID was created, take its first 12 hex digits, convert them to a number, and paste it into the
Unix Timestamp Converter as milliseconds.