Kafka Streams Custom TimestampExtractor for aggregation
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Kafka Streams uses timestamps to decide how records participate in windowed aggregations. If the event time you care about lives inside the message payload instead of in Kafka record metadata, you need a custom TimestampExtractor so your aggregation windows follow business event time rather than broker time.
Why Timestamp Extraction Matters
Windowed operations such as tumbling, hopping, and session windows all depend on a timestamp. By default, Kafka Streams can use the record timestamp that Kafka stores with the message, but that may not represent when the business event actually happened.
Typical cases where event time is better:
- IoT devices send delayed measurements
- mobile clients buffer events offline
- upstream services publish historical backfills
If you aggregate by ingestion time instead of event time, your windows can become misleading.
A Custom TimestampExtractor
The extractor must return milliseconds since the Unix epoch:
Using partitionTime as a fallback is often safer than throwing when a bad record arrives, though the right policy depends on your data quality requirements.
Wiring It into Kafka Streams
You can configure the extractor globally:
With that configuration, timestamp-based operations across the topology will use the extracted event time by default.
You can also attach an extractor at the Consumed level for a specific source when you do not want one global extractor to apply to every input topic.
Example Aggregation
Here is a simple five-minute windowed count:
The important point is that the five-minute windows are now based on event.getEventTimeMillis().
Late Records and Grace Periods
Custom extraction changes what "late" means. A record can arrive now but belong to an older window if its event-time field is old.
That is why grace periods matter:
With a grace period, slightly late events can still update the intended window instead of being dropped as too late.
Validating the Extracted Timestamp
Do not assume every record contains a valid timestamp. Good extractors usually protect against:
- null payloads
- negative timestamps
- missing fields
- timestamps in seconds instead of milliseconds
A defensive version:
The last thing you want is one malformed record breaking a stateful topology unnecessarily.
Common Pitfalls
The biggest mistake is returning seconds instead of milliseconds. Kafka Streams expects epoch milliseconds, so a seconds-based timestamp silently shifts windows by a factor of one thousand.
Another issue is using event time without thinking about late data. Once you switch from broker time to payload time, out-of-order records become normal, not exceptional, and your window grace settings need to reflect that.
Finally, avoid throwing away bad records inside the extractor without observability. If the extractor falls back or drops records, log or monitor that behavior so window results do not become mysterious later.
Summary
- A custom
TimestampExtractorlets Kafka Streams aggregate by event time instead of broker timestamp. - The extractor must return epoch milliseconds.
- Use it when the true business timestamp is stored inside the record payload.
- Combine event-time extraction with appropriate grace periods for late data.
- Validate malformed or missing timestamps so one bad record does not destabilize the topology.
Related reading
- Kafka Streams Deserialization Handler
- Kafka Streams does not increment offset by 1 when producing to topic
- Kafka Streams dynamic routing (ProducerInterceptor might be a solution?)
- Kafka Streams error - Offset commit failed on partition, request timed out
- Kafka streams error SerializationException Size of data received by LongDeserializer is not 8
- Kafka Streams Failed to flush state store caused by java.lang.ClassCastException cannot case key to value
- Kafka Streams How to ensure offset is committed after processing is completed
- Kafka Streams how to get the kafka headers

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.