How to use it
- Pick a version, a .NET format and how many you need.
- Optionally uppercase them or wrap each in quotes with a trailing comma for pasting into code.
- Press Regenerate for a fresh batch.
v4 versus v7 — the decision that matters
For years v4 was the only version anyone used: 122 random bits, six fixed bits for version and variant. It is simple and it is a poor database key.
The reason is index locality. A B-tree index stores rows in key order, and inserts land wherever the key sorts. Random keys land everywhere — every insert dirties a different page, the working set stops fitting in memory, pages split, and fragmentation grows. On a large table with a clustered UUID key the effect is measurable and unpleasant.
v7 fixes this by making the first 48 bits a Unix millisecond timestamp. Identifiers generated later sort after ones generated earlier, so inserts append to the end of the index like an auto-increment key, while the remaining 74 random bits keep them unique across machines. It became an RFC-standardised version in 2024 (RFC 9562) after years of ad-hoc equivalents — ULID, KSUID, MongoDB ObjectId, NEWSEQUENTIALID — all solving the same problem.
The trade is that v7 reveals when it was created. That is normally fine for internal keys and worth thinking about for identifiers in public URLs, since it exposes creation timing and, in aggregate, volume.
If you are choosing today: v7 for database keys, v4 when the identifier is exposed and timing should stay private.
Reading the layout
0189d6f8-2c17-7a3e-8f42-1b9c5d7e0a44
└──────────────┘ │└──┘ │
time (v7) │ └─ variant (10xx)
└─ version nibble (4 or 7)
Four bits carry the version and two the variant, which is why a v4 UUID has 122 random bits rather than 128. Those bits are what let any parser identify the version without external context.
The nil UUID (all zeros) and the max UUID (all ones) are both reserved and useful as explicit sentinels — a "no value" marker that is unmistakably not a real identifier.
.NET formats, and one specific trap
Guid.ToString() accepts five specifiers. D is the default hyphenated form and the one to use. N (no hyphens) shows up in URLs and cache keys. B and P wrap in braces or parentheses and mostly appear in Windows registry and COM contexts. X produces a C-style hex struct almost nobody needs.
The trap worth knowing is unrelated to formatting: Guid.NewGuid() produces a v4, so using it as a clustered primary key in SQL Server has exactly the fragmentation problem described above. NEWSEQUENTIALID() exists for that reason, but it is server-side only and its values are guessable — it increments predictably. A v7 generated in application code gives you the ordering without the guessability, which is why it is now the better default.