Understanding Message Timestamps
1. Understanding Timestamp Types
| Type |
Source |
Detail |
| CreateTime |
Set by producer |
Event time |
| LogAppendTime |
Set by broker on write |
Ingestion time |
| message.timestamp.type |
Topic config selects |
CreateTime default |
Example: Read record timestamp
long ts = record.timestamp();
TimestampType type = record.timestampType(); // CREATE_TIME or LOG_APPEND_TIME
2. Using Create Time
| Aspect |
Description |
Detail |
| CreateTime |
When event occurred |
Producer-supplied |
| Default |
Current time if unset |
System.currentTimeMillis |
| Streams |
Drives event-time windows |
Preferred |
Example: Explicit create time
// topic, partition, timestamp, key, value
producer.send(new ProducerRecord<>("events", null, eventTimeMs, key, value));
3. Using Log Append Time
| Aspect |
Description |
Detail |
| LogAppendTime |
Broker write moment |
Overwrites producer ts |
| Monotonic |
Roughly increasing per partition |
Server clock |
| Use Case |
Retention by arrival |
Deterministic |
Example: Set log append time
kafka-configs.sh --alter --entity-type topics --entity-name events \
--add-config message.timestamp.type=LogAppendTime \
--bootstrap-server localhost:9092
4. Configuring Timestamp Type
| Config |
Values |
Default |
| message.timestamp.type |
CreateTime / LogAppendTime |
CreateTime |
| Scope |
Broker default + topic override |
Per topic |
log.message. timestamp.type |
Broker-level default |
CreateTime |
Example: Broker default
log.message.timestamp.type=CreateTime
5. Setting Producer Timestamp
| Aspect |
Description |
Detail |
| Timestamp arg |
Explicit in ProducerRecord |
ms epoch |
| null |
Defaults to send time |
Auto |
| Ignored if |
Topic uses LogAppendTime |
Broker overwrites |
Example: Backdated event
long original = parseEventTime(json);
producer.send(new ProducerRecord<>("events", null, original, key, json));
6. Understanding Timestamp Ordering
| Aspect |
Description |
Detail |
| Not Guaranteed |
CreateTime may be unordered |
Out-of-order events |
| Offset Order |
Offsets always increase |
Storage order |
| Streams |
Handles via grace period |
Late events |
Example: Detect out-of-order
if (record.timestamp() < lastSeenTs) outOfOrderCount++;
lastSeenTs = Math.max(lastSeenTs, record.timestamp());
7. Using Timestamps for Retention
| Aspect |
Description |
Detail |
| Retention Basis |
Segment max timestamp vs retention.ms |
Per segment |
| CreateTime risk |
Backdated data deleted early |
Watch clocks |
| LogAppendTime |
Predictable expiry |
Arrival-based |
Warning: With CreateTime, future-dated timestamps can keep segments alive far beyond retention.ms.
Example: Retention with append time
message.timestamp.type=LogAppendTime
retention.ms=259200000
8. Filtering by Timestamp
| Method |
Purpose |
Detail |
| offsetsForTimes |
Find offset at/after time |
Per partition |
| seek |
Jump to that offset |
Then poll |
| In-loop |
Skip records below time |
Post-filter |
Example: Seek by timestamp
Map<TopicPartition, Long> query = Map.of(tp, sinceMs);
var offsets = consumer.offsetsForTimes(query);
consumer.seek(tp, offsets.get(tp).offset());
9. Configuring Timestamp Difference
| Config |
Description |
Default |
message.timestamp. difference.max.ms |
Max allowed skew vs broker time |
Long.MAX |
| Reject |
Records beyond skew refused |
CreateTime only |
| Use Case |
Block bad clocks |
Data hygiene |
Example: Limit timestamp skew
message.timestamp.difference.max.ms=3600000 # 1 hour
10. Resetting Offsets by Timestamp
| Method |
Description |
Detail |
| --to-datetime |
CLI reset to time |
Group offline |
| offsetsForTimes |
API equivalent |
In-app |
| Use Case |
Replay from incident |
Recovery |
Example: Reset group to datetime
kafka-consumer-groups.sh --reset-offsets --group analytics \
--topic events --to-datetime 2026-06-10T08:00:00.000 \
--execute --bootstrap-server localhost:9092