Skip to content
Filevane
🔑

ObjectId vs UUID vs NanoID: Which ID Should You Use?

August 23, 2026 4 min read

Use UUID v7 if you are choosing today and nothing forces your hand. It is globally unique, time-ordered so it does not fragment a database index, and readable by every language and datastore without a custom type. The other formats each win in a specific situation, and this guide is about which situation you are actually in.

Four formats come up constantly, and the differences that matter are not the ones the names suggest.

The comparison

Length Sortable by time Leaks Best for
MongoDB ObjectId 24 hex chars Yes, to the second Creation time MongoDB _id fields
UUID v4 36 chars No Nothing Anything public-facing
UUID v7 36 chars Yes, to the millisecond Creation time New primary keys
NanoID 21 chars (adjustable) No Nothing URLs and share links
ULID 26 chars Yes, to the millisecond Creation time Sortable, compact keys

When to use each one

Use an ObjectId when you are working with MongoDB. It is the native _id type, the drivers generate it client-side, and every tool in the ecosystem expects it. Generating one yourself is normal practice rather than a workaround — it is how optimistic inserts and offline writes work at all.

Use a UUID v4 when something external expects the RFC format — a Postgres uuid column, a public API contract, a correlation id crossing service boundaries. It leaks nothing, which makes it the safe default for identifiers that appear where strangers can see them.

Use UUID v7 for new primary keys. It keeps the RFC layout and format but puts a millisecond timestamp in the leading bits, so inserts land near each other in the index instead of scattering. It is defined in RFC 9562, which superseded RFC 4122 in 2024.

Use a NanoID when a human will see or type the id. Twenty-one URL-safe characters against a UUID's thirty-six, with no hyphens to escape and comparable collision resistance. This is the right choice for short links and share URLs.

Use a random string when the value is a secret. None of the formats above are secrets, and that is the single most common mistake in this area.

The mistake worth avoiding

An identifier is not a token. ObjectIds embed a predictable timestamp and an incrementing counter, UUID v4 is unguessable in practice but is not specified as a security primitive, and NanoID's length is tuned for collision resistance rather than for resisting an attacker.

If a value grants access to something — a password reset link, an unlisted document URL, an API key — generate it from a cryptographic random source at a length chosen for that job. Every generator on this site draws from the browser's crypto.getRandomValues(), but length and purpose are still yours to choose.

Why random IDs fragment a database index

This is the argument behind UUID v7 and ULID, and it is worth understanding rather than taking on faith.

A B-tree index keeps keys in sorted order. When consecutive inserts carry keys that are close together, they land on the same page, the page fills, and the database moves on to the next one. When the keys are random, every insert lands somewhere unrelated: pages split constantly, the working set stops fitting in cache, and write throughput falls as the table grows.

Time-ordered identifiers restore that locality without giving up global uniqueness — which is the whole point of the newer formats.

Reading the timestamp out of an ObjectId

Because the first four bytes of an ObjectId are a Unix timestamp in seconds, an id carries its own creation date:

new Date(parseInt(id.slice(0, 8), 16) * 1000)

That is useful when you need a created-at value and nobody stored one. It is also the reason an ObjectId in a public URL discloses when the record was created — fine for most applications, a real leak for a few.

Generating them privately

All four generators on this site run entirely in your browser. Nothing is transmitted, so no server has ever seen the values you generate — which is not true of an API-based generator, and matters more than it sounds for identifiers you are about to put into production seed data.

Tools used in this guide

Frequently asked questions

Which ID format should I use by default?

If your database mints ids for you, use what it gives you — an ObjectId in MongoDB, a bigint sequence in Postgres. If you generate ids yourself, UUID v7 is the best general-purpose default: globally unique, time-ordered so it does not fragment an index, and understood by every language and database without a custom type.

Is NanoID safer than UUID?

Neither is a security mechanism. A default NanoID carries about 126 bits of randomness against a UUID v4's 122, so they are effectively equivalent for uniqueness. Both are designed to be unique, not unguessable — anything that grants access needs a purpose-built random token instead.

Do ObjectIds leak information?

Yes, one specific thing: creation time. The first four bytes are a Unix timestamp in seconds, so anyone who sees an ObjectId in a URL learns when the record was created. That is harmless for most applications and a genuine disclosure for a few. UUID v4 leaks nothing.

Why do random UUIDs slow down database inserts?

A v4 UUID is random, so consecutive inserts land in unrelated places in a B-tree index. The index splits pages constantly and stops fitting neatly in cache. Time-ordered identifiers — UUID v7, ULID, or an ObjectId — insert near each other and avoid the problem.

How likely is a NanoID collision?

At the 21-character default, generating a million IDs per second would take roughly a thousand years to reach a 1% chance of one collision. That margin disappears fast if you shorten it: at 8 characters you should expect a collision within a few million IDs.

objectid vs uuiduuid vs nanoidwhich id should i usedatabase primary key iduuid v7 vs v4nanoid collisionobjectid timestampulid vs uuid