Apache Kafka stores messages as key-value pairs. The key determines partition assignment and enables log compaction — Kafka retains only the last message per key when compaction is enabled. UUID v4 keys are stateless and collision-safe but carry no ordering information. UUID v7 adds a 48-bit millisecond timestamp to every key, enabling time-range replay, deduplication by recency, and approximate ordering within a partition — all without any schema changes. The Apache Kafka documentation and the uuid npm package (for Node.js producers) both support the patterns described here.
Why message key choice matters
Kafka routes messages to partitions by hashing the key. The key also drives:
- Log compaction — Kafka keeps the latest message per key. A stable UUID v7 key per entity (user, order, device) enables compacted topics to act as a changelog.
- Consumer ordering — messages with the same key always land in the same partition, so a single consumer processes them in order.
- Deduplication — idempotent producers use the message key to detect duplicates on retry.
UUID v7 for event ordering
UUID v4 keys provide no ordering within a partition. UUID v7 keys are lexicographically ordered by creation time:
Event 1: 019236a7-b4f2-7000-8d3e-9c1a2b3d4e5f (t = 1727308800000 ms)
Event 2: 019236a7-b4f4-7000-8e2f-7b4c5d6e7f80 (t = 1727308800002 ms)
Event 3: 019236a7-b4f6-7000-9a1b-6c5d4e3f2a91 (t = 1727308800004 ms)
Sorting these keys as strings gives the correct production sequence. A Kafka Streams application can use this to reconstruct event timelines without a separate timestamp field.
Time-range replay
Standard Kafka replay requires knowing the partition offset for a target time. With UUID v7 keys, you can binary-search the key space by timestamp prefix:
// Java: find the offset for events after a target time
long targetMs = Instant.parse("2026-09-01T00:00:00Z").toEpochMilli();
String targetPrefix = String.format("%012x", targetMs); // 48-bit hex prefix
// Compare UUIDs: event.key().startsWith(targetPrefix or greater)
This works because UUID v7 keys sort the same way timestamps sort — a property guaranteed by RFC 9562 §5.7.
Producer configuration (Java)
ProducerRecord<String, byte[]> record = new ProducerRecord<>(
"orders",
UuidCreator.getTimeOrderedEpoch().toString(), // UUID v7 key
orderPayload
);
producer.send(record);
The uuid-creator Java library provides getTimeOrderedEpoch() which generates RFC 9562-compliant UUID v7.
Producer configuration (Python)
from uuid6 import uuid7
from confluent_kafka import Producer
producer = Producer({'bootstrap.servers': 'localhost:9092'})
producer.produce(
'orders',
key=str(uuid7()), # UUID v7 string key
value=payload_bytes
)
The uuid6 package on PyPI implements UUID v7 for Python producers.
Partition skew consideration
UUID v7 keys generated in rapid bursts share the same millisecond prefix. Kafka’s default murmur2 hash distributes them differently from purely random UUIDs — high-burst producers may see temporary partition skew. Mitigations:
- Append a random suffix:
${uuidv7()}-${Math.random().toString(36).slice(2, 6)} - Use a custom partitioner that uses only the random bits (bits 76–127) for partition selection
- For ordered processing, accept the skew — it is proportional to burst duration, typically milliseconds
Log compaction with UUID v7 entity keys
For entity changelog topics (one key per entity, latest value wins):
Topic: user-profile-changes
Key: <user UUID v7, assigned at account creation>
Value: serialised user state
Using UUID v7 as the entity key means the key itself encodes when the entity was created — useful for auditing and for filtering compacted topics by cohort (all users created in January 2026 share a key prefix).
Further reading
- UUID v7 in Distributed Systems — ordering and tracing patterns
- UUID Security — what the embedded timestamp discloses
- UUID Generation Strategies — where to generate IDs
External references
- Apache Kafka documentation
- uuid-creator Java library
- uuid6 on PyPI
- RFC 9562 — UUID standard
- uuid npm package
Frequently asked questions
Why use UUID v7 instead of UUID v4 as a Kafka message key?
UUID v4 keys distribute messages uniformly across partitions, which is good for load balancing but loses time ordering. UUID v7 keys preserve millisecond-precision ordering within a partition — consumers can process events in creation sequence without a separate event_time field. The embedded timestamp also enables time-range replay: seek to the partition offset corresponding to a target time by binary-searching the UUID key prefix. See RFC 9562 §5.7 for the UUID v7 bit layout.
How do I extract the timestamp from a UUID v7 Kafka key?
In Java (Kafka Streams or consumer): long ms = Long.parseUnsignedLong(key.replace("-","").substring(0,12), 16);. In Python with uuid6 on PyPI: uuid6.UUID(key).time returns Unix milliseconds. The first 12 hex characters encode the 48-bit timestamp defined in RFC 9562.
Does UUID v7 affect Kafka partition assignment?
Yes. Kafka's default partitioner hashes the message key to select a partition. UUID v7 keys have a shared time-prefix for bursts of events in the same millisecond, which could skew partitioning if events cluster in time. Use a custom partitioner that hashes the full 128-bit value, or include a producer ID suffix — the Apache Kafka documentation covers custom partitioner configuration via partitioner.class.