A UUID is a 128-bit identifier that any system can produce independently without asking a central authority for permission. That property is the entire point: two services, two laptops, and two database shards can all mint identifiers at the same moment and rely on them not colliding.
Generating one is a single function call in every mainstream platform. The decisions worth attention are which version to generate and where the randomness comes from, because those choices determine whether the guarantee actually holds.
What a generated UUID looks like
The canonical text form is thirty-six characters: thirty-two hexadecimal digits in five hyphen-separated groups of 8-4-4-4-12. Only 122 of the 128 bits are free, because four bits encode the version and two encode the variant.
You can read the version directly from the string. The first character of the third group is the version digit, so a value with 4 in that position is a random UUID and one with 7 is time-ordered. The first character of the fourth group is 8, 9, a, or b for the standard variant defined in RFC 9562.
Generating in JavaScript and Node
Modern browsers and Node expose crypto.randomUUID(), a built-in UUID v4 generator backed by the platform's cryptographic random source. It needs no dependency and is available in every current runtime, so a package is rarely justified for version 4 alone.
The uuid package from npm remains useful when you need other versions, name-based generation, parsing, or validation helpers. What you should not do is assemble an identifier from Math.random(), which is not a cryptographic source and produces predictable, collision-prone output.
Generating in Python, Java, and C#
Python's standard library provides uuid.uuid4() for random identifiers and uuid.uuid5() for deterministic name-based ones. The returned object exposes hex, bytes, and int representations, which is convenient when storing the value compactly rather than as text.
Java uses UUID.randomUUID(), backed by a secure random source. In .NET, Guid.NewGuid() serves the same role, and the term GUID is simply Microsoft's name for the same 128-bit structure. A GUID generated in C# and a UUID generated in Java are interchangeable, though .NET's default ToString() formatting options differ.
Generating in databases
PostgreSQL provides gen_random_uuid() as a built-in function in recent versions, so a column can default to a fresh identifier without any application involvement. That is the cleanest option when rows may be created by migrations, imports, or several services at once.
Letting the database generate the value has a trade-off: the application does not know the identifier until after the insert returns. When code needs the identifier beforehand, to write a related record or publish an event, generate it in the application and pass it in. Both approaches are valid; mixing them inconsistently is what causes confusion.
Generating from the shell
Linux systems expose uuidgen, and reading /proc/sys/kernel/random/uuid produces a version 4 value directly from the kernel. On Windows, PowerShell offers [guid]::NewGuid(). These are handy for seeding configuration, creating test fixtures, or generating a correlation identifier in a script.
For a one-off value during development, it is often quicker to generate UUID online in a browser tab. Since a version 4 identifier carries no information about the machine that produced it, generating one in a page and pasting it into code is perfectly safe, provided the tool uses the browser's cryptographic random source rather than a weak substitute.
Choosing what to generate
Version 4 is the sensible default for identifiers that are simply meant to be unique. Version 7 is a better choice for database primary keys because it embeds a timestamp and sorts chronologically, which keeps index insertions local instead of scattering them. Version 5 suits deterministic identifiers derived from a namespace and a name.
Avoid version 1 for anything exposed publicly. It encodes a timestamp and, historically, a MAC address, so it leaks information about the generating host and the moment of creation. If you want time ordering, version 7 provides it without that disclosure.
Randomness is the real dependency
A version 4 UUID has 122 random bits, and its collision resistance depends entirely on those bits being unpredictable. Any generator built on a fast, non-cryptographic random number source undermines the guarantee, and the failure is silent: the output looks identical, and the problem only appears as duplicate keys or as a security issue when identifiers turn out to be guessable.
Use the platform's cryptographic source and treat a UUID as an identifier rather than a secret. Even a perfectly generated version 4 value should not act as a bearer token or a password reset key, because identifiers appear in logs, referrer headers, and support tickets far more often than secrets do.
UUID and GUID generator calls by platform
The table gathers the call for each environment, including the database and package forms.
| Environment | Call | Version |
|---|---|---|
| GUID generator JavaScript | crypto.randomUUID() | v4 |
| UUID v4 npm / uuid generator npm | import { v4, v7 } from "uuid" | v4, v7 |
| UUID generator Angular | crypto.randomUUID() in a service | v4 |
| UUID v7 Python / Python v4 | uuid.uuid4(), uuid.uuid7() | v4, v7 |
| UUID v7 Java | UUID.randomUUID(); library for v7 | v4, v7 |
| UUID v7 C# / uuid v7 dotnet | Guid.NewGuid(), Guid.CreateVersion7() | v4, v7 |
| GUID generator C# online equivalent | Guid.NewGuid().ToString() | v4 |
| UUID generator C++ | boost::uuids::random_generator() | v4 |
| Generate UUID Android | UUID.randomUUID().toString() | v4 |
| UUID auto generate Postgres | DEFAULT gen_random_uuid() | v4 |
| UUID v7 Postgres | DEFAULT uuidv7() | v7 |
| UUID generator from string | uuid.uuid5(NAMESPACE_URL, name) | v5 |
A UUID auto generate column default is the cleanest option when several writers insert rows, because no application needs to agree on anything. Reach for a UUID generator API or a hosted service only when a client genuinely cannot run the code locally; the operation is a few lines and needs no network. A UUID v4 CDN script is similarly unnecessary now that crypto.randomUUID() ships in every current browser.
The UUID generator algorithm for each version
The UUID v4 algorithm is the simplest: fill all 128 bits from a cryptographic random source, then overwrite the four version bits and two variant bits. That leaves the 122 free bits described earlier. The GUID generation algorithm in .NET does exactly this for its default version.
The v5 algorithm hashes a namespace identifier together with a name using SHA-1 and truncates the result, which is why it is deterministic: the same namespace and name always yield the same identifier. The v7 layout replaces the leading random bits with a millisecond timestamp, as described in the article on time-ordered identifiers.
Generating many identifiers at once
Bulk generation for seed data or load testing works the same way, but two details change. Draw from the cryptographic source in batches rather than one call per identifier, since the per-call overhead dominates when producing millions. And confirm that every worker process has its own entropy state, because forked processes that inherit a seeded generator can produce identical sequences.
This failure has a recognisable signature: duplicates that cluster by process rather than appearing randomly. If a bulk import produces collisions, suspect a shared or copied random state long before suspecting the birthday bound, which at any realistic volume remains far outside the range of plausible causes.