uuidv7 is a small, dependency-free Java library for generating RFC 9562 UUID version 7 identifiers.
It is designed for production workloads that care about time ordering, throughput, low allocation pressure, and multicore scalability.
The library exposes two generation modes:
UUIDv7.randomUUID()is the default high-throughput API. It uses per-thread state, avoids shared hot-path contention, and preserves monotonic ordering for values produced by the same thread within the same millisecond.UUIDv7.secureRandomUUID()is the stronger-entropy API. It usesSecureRandomto seed and advance the UUID state, which improves unpredictability at a much higher per-call cost.
- RFC 9562 UUIDv7 layout
- 48-bit Unix epoch timestamp in milliseconds
- Correct version and variant bits
- Clock rollback handling
- Same-millisecond monotonic sequencing
- No runtime dependencies beyond the JDK
- Java 17+
- Fast path allocates only the returned
UUIDobject
<dependency>
<groupId>io.github.robsonkades</groupId>
<artifactId>uuidv7</artifactId>
<version>1.0.1</version>
</dependency>import io.github.robsonkades.uuidv7.UUIDv7;
import java.util.UUID;
UUID fast = UUIDv7.randomUUID();
UUID secure = UUIDv7.secureRandomUUID();- Use
UUIDv7.randomUUID()for database keys, event IDs, trace IDs, queue message IDs, and other high-volume identifiers. - Use
UUIDv7.secureRandomUUID()only if stronger entropy in the UUID payload matters more than raw throughput. - Do not use UUIDv7 as a secret token format. UUIDv7 embeds creation time by design.
The implementation is intentionally optimized around the real bottlenecks of UUID generation on the JVM:
- The fast generator keeps mutable state in
ThreadLocalstorage, which avoids global locks, atomics, and cache-line ping-pong under contention. - UUID bit packing is done directly into two
longvalues. Nobyte[16],ByteBuffer, boxing, or formatting work happens on the hot path. - If the wall clock moves backwards, the generator reuses the last logical timestamp and advances monotonic state instead of emitting a smaller UUID.
- If the same-millisecond counter space is exhausted, the generator advances to the next logical millisecond rather than knowingly wrapping and returning duplicates.
- The secure generator keeps the same state machine, but uses
SecureRandomto seed new timestamps and to advance same-millisecond state with positive random increments.
Benchmarks were run with JMH 1.37 on this repository's current implementation and benchmark suite.
- JVM: GraalVM CE 25.0.2
- Hardware: 24 logical CPUs
- JVM args:
-Xms1g -Xmx1g - Warmup: 5 iterations x 1 second
- Measurement: 5 iterations x 1 second
- Forks: 2
- Benchmark source:
src/test/java/io/github/robsonkades/uuidv7/UUIDv7Benchmark.java
Comparison targets:
optimizedFast:UUIDv7.randomUUID()optimizedSecure:UUIDv7.secureRandomUUID()legacyThreadLocalRandom: previous no-state baselinenaiveSecureRandomByteBuffer:SecureRandom+byte[16]+ByteBufferuuidCreator:com.github.f4b6a3:uuid-creatoruuidCreatorFast:com.github.f4b6a3:uuid-creatorfast modejugEpoch:com.fasterxml.uuid:java-uuid-generator
These results are point-in-time measurements, not universal constants. Different JVMs, CPU topologies, entropy providers, and OS timer behavior will change the exact numbers.
| Implementation | Throughput | Allocation |
|---|---|---|
optimizedFast |
250.3 M ops/s | 32.0 B/op |
legacyThreadLocalRandom |
279.1 M ops/s | 32.0 B/op |
jugEpoch |
69.4 M ops/s | 32.0 B/op |
uuidCreatorFast |
35.7 M ops/s | 64.0 B/op |
naiveSecureRandomByteBuffer |
3.75 M ops/s | 208.0 B/op |
uuidCreator |
3.59 M ops/s | 231.3 B/op |
optimizedSecure |
1.86 M ops/s | 368.2 B/op |
| Implementation | Throughput | Allocation |
|---|---|---|
optimizedFast |
1.069 B ops/s | 32.0 B/op |
legacyThreadLocalRandom |
1.081 B ops/s | 32.0 B/op |
uuidCreatorFast |
27.8 M ops/s | 64.3 B/op |
optimizedSecure |
21.8 M ops/s | 368.4 B/op |
jugEpoch |
10.6 M ops/s | 32.6 B/op |
uuidCreator |
2.44 M ops/s | 225.0 B/op |
naiveSecureRandomByteBuffer |
2.23 M ops/s | 208.0 B/op |
| Implementation | Mean | p95 | p99 | p99.9 |
|---|---|---|---|---|
optimizedFast |
32.1 ns | 100 ns | 100 ns | 221.3 ns |
jugEpoch |
38.6 ns | 100 ns | 100 ns | 300.0 ns |
uuidCreatorFast |
54.4 ns | 100 ns | 100 ns | 400.0 ns |
naiveSecureRandomByteBuffer |
328.7 ns | 300 ns | 400 ns | 9486.7 ns |
optimizedFaststays close to the bareThreadLocalRandombaseline in single-thread mode while adding rollback handling and same-thread monotonic sequencing.- Under 24-thread load,
optimizedFastscales essentially linearly and remains near the legacy baseline, which is the main design goal of the implementation. optimizedFastis about 67x faster than the naiveSecureRandom + ByteBufferbaseline in single-thread throughput and about 480x faster at 24 threads.optimizedFastis about 7x faster thanuuidCreatorFastin single-thread throughput and about 38x faster at 24 threads.jugEpochanduuidCreatorshow a large collapse under contention, which strongly suggests shared internal coordination costs.optimizedSecureis intentionally much slower thanoptimizedFast. That is the expected trade-off for stronger entropy and random monotonic increments.
This project is licensed under the MIT License. See LICENSE for details.
Contributions, bug reports, and feature requests are welcome. See CONTRIBUTING.md.