UUID Generator (v4, v7, v1)
What is a UUID?
A UUID (Universally Unique Identifier) β also called a GUID (Globally Unique Identifier) on Microsoft platforms β is a 128-bit value used to uniquely identify something without coordination. The odds of two UUIDs clashing are astronomically low: generating a billion v4 UUIDs per second for a hundred years has roughly the same chance of a collision as an asteroid hitting your server.
A UUID is displayed as 32 hexadecimal digits split by hyphens into five groups: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, where M indicates the version and N encodes the variant.
UUID versions in practice
The RFC defines seven versions. Only three matter in everyday code:
v4 β random (the classic default)
- 122 bits of cryptographic randomness + 6 bits of version/variant markers
- No timestamp, no hardware info, fully unpredictable
- Available in Java since 1.5 via
UUID.randomUUID() - Weakness: inserting random UUIDs into a database index causes fragmentation
v7 β time-ordered (recommended for new projects)
- 48-bit Unix millisecond timestamp + 74 bits of randomness
- Sortable by creation time, like auto-incrementing integers
- Standardized in RFC 9562 (May 2024)
- Play nicely with B-tree database indexes β no fragmentation
- No Java built-in yet β use the
uuid-creatorlibrary
v1 β legacy time + MAC address
- 60-bit timestamp + 14-bit clock sequence + 48-bit "node" (historically the MAC address)
- Discouraged today because the node used to leak the machine's MAC address
- Use only for compatibility with older systems
v4 vs v7 β why database engineers prefer v7
Imagine 1 million INSERTs with v4 UUID primary keys. Because each UUID is fully random, every INSERT lands in a different B-tree leaf page. The index becomes fragmented β pages fill to 50%, the engine splits them, disk I/O explodes.
With v7, the time prefix means every INSERT goes at or near the end of the index (just like an auto-increment integer). The B-tree stays compact, the OS page cache stays hot, and INSERT throughput is 3β10Γ higher on common workloads.
If you're starting a new service, default to v7. The only reason to pick v4 is when you explicitly want the creation time to not be observable from the ID.
UUIDs in Java
v4 β built into java.util
import java.util.UUID;
UUID id = UUID.randomUUID();
String s = id.toString(); // "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6"
String noHyphens = id.toString().replace("-", "");
// Parse
UUID parsed = UUID.fromString(s);
v7 β with uuid-creator library
The JDK has no v7 support yet. Use uuid-creator:
<dependency>
<groupId>com.github.f4b6a3</groupId>
<artifactId>uuid-creator</artifactId>
<version>6.0.0</version>
</dependency>
import com.github.f4b6a3.uuid.UuidCreator;
UUID v7 = UuidCreator.getTimeOrderedEpoch(); // v7
UUID v4 = UuidCreator.getRandomBased(); // v4
UUID v5 = UuidCreator.getNameBasedSha1(namespace, "unique-name");
v5 β name-based (SHA-1 hash of a namespace + name)
Generate a deterministic UUID from a string. Useful when you need the same input to always produce the same UUID (e.g. imported external IDs).
When to use UUIDs (and when not to)
Use a UUID when:
- You need IDs that can be generated without consulting a central authority
- Multiple databases/services must mint IDs that won't collide when merged
- You don't want sequential IDs to leak record counts or creation order
- A URL-safe, unguessable token is needed (v4 / v7)
Avoid UUIDs when:
- Your IDs must be short and human-friendly (use nanoid or short-UUID libraries)
- You need pure sequential ordering with no randomness (use auto-increment)
- Storage cost matters a lot β UUID is 16 bytes vs 8 for BIGINT, and 36 chars as text
Storing UUIDs in a database
Three common approaches:
- Native UUID type β PostgreSQL has
UUID(16 bytes). MySQL 8 hasUUID_TO_BIN()/BIN_TO_UUID(). Use this when available. - BINARY(16) β universally supported, compact. Convert to/from UUID in the app layer.
- VARCHAR(36) β simplest, but 2Γ the storage and slower comparisons. Avoid when you'll store millions.
JPA mapping
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.UUID) // JPA 3.1+
@Column(columnDefinition = "uuid")
private UUID id;
// β¦
}
On Hibernate 6+, GenerationType.UUID generates v4 by default. For v7 you'll need a custom ID generator.
Common mistakes
- Using
Math.random()-based UUIDs. Math.random is not cryptographically secure. Always usecrypto.getRandomValues()in JS orSecureRandomin Java. - Storing UUIDs as VARCHAR(36) on millions of rows. That's 4Γ the space vs BINARY(16), and 4Γ the RAM for the index.
- Exposing v1 UUIDs publicly β they leak the server's MAC and approximate time of creation.
- Assuming v4 UUIDs are ordered. They're not. Tools that sort by UUID will get random ordering.
- Parsing v7 with
UUID.fromString. The JDK method accepts any valid UUID, but treats it as opaque β you can't extract the timestamp without extra code.
Related tools and guides
- JWT Decoder β decode
jticlaims that are often UUIDs - Epoch Timestamp β extract the time from a v7 UUID manually
- Java Online Compiler β try the UUID snippets above
- Base64 Encoder / Decoder β pair UUIDs with Base64 for shorter tokens