Loading...

About the UUID/ULID Generator

UUIDs and ULIDs both give you a 128-bit identifier you can generate anywhere without asking a central authority for permission. The difference that matters in practice is ordering: a UUIDv4 is pure randomness, while a ULID and a UUIDv7 both put a millisecond timestamp in the high bits so that identifiers generated later sort after identifiers generated earlier.

That ordering property is not cosmetic. Random identifiers used as a primary key scatter inserts across the whole of a B-tree index, which dirties many pages per write and steadily fragments the index. Time-ordered identifiers append near the right-hand edge instead, so inserts stay in a small hot region. On a large table the difference shows up as write throughput and index bloat, not as anything you would notice in development.

Everything here is generated in your browser using the platform crypto API, so the values are cryptographically random and never leave your machine. That matters if you are minting identifiers you intend to actually use rather than throwaway test data.

Frequently asked questions

Should I use UUIDv4 or UUIDv7 for a database primary key?

UUIDv7, in almost every case. Both are 128 bits and both are generated without coordination, but v7 is time-ordered, so inserts land at the end of the index instead of scattering randomly through it. That keeps write amplification and index fragmentation down. Use v4 when you specifically do not want the creation time to be recoverable from the identifier.

What is the difference between a ULID and a UUIDv7?

They solve the same problem and are both 128 bits with a millisecond timestamp in the high bits. The practical differences are encoding and compatibility: ULIDs are usually written in 26-character Crockford Base32, which is shorter and case-insensitive, while UUIDv7 uses the standard 36-character hyphenated hex form and drops straight into any column, library, or tool that already expects a UUID. If your stack has a native UUID type, v7 is the lower-friction choice.

Can two randomly generated UUIDs collide?

In theory yes, in practice no. A v4 UUID has 122 random bits. You would need to generate on the order of a billion per second for roughly 85 years before reaching a one-in-a-billion chance of a single collision. Collisions you actually see in the wild are essentially always a broken random source — for example a library seeded from the clock, or a fork that copied its parent's PRNG state — rather than bad luck.

Does a time-ordered identifier leak information?

Yes, and you should decide whether you care. A ULID or UUIDv7 encodes the millisecond it was created, so anyone holding the identifier learns when the record was created, and can order two records by comparing them. For a public-facing resource identifier that is usually harmless. For something like a password-reset token or an invitation code it is a real leak, and you should use v4 there.

Should I store UUIDs as text or as a native type?

Native, whenever the database offers it. PostgreSQL has a uuid type that stores 16 bytes; storing the same value as a 36-character string costs more than double that in the row and again in every index that touches it. MySQL has no native type, so the usual approach is BINARY(16). Storing UUIDs as VARCHAR is the single most common cause of surprisingly large indexes.

Need this managed for you, not just automated?

We're also a hands-on DevOps consultancy — Kubernetes, CI/CD, and cloud infrastructure.

Explore Our Services