Define a KStream for the event stream topic and a KTable for the dimension/lookup topic using StreamsBuilder.
Ensure both the stream and the table use the same key type and serdes; repartition the stream (via selectKey and the implicit repartition) if keys do not match.
Call stream.join(table, valueJoiner, Joined.with(keySerde, streamValueSerde, tableValueSerde)) to produce the joined stream.
Handle the case where the table has no entry for a key using leftJoin if you want to emit stream records even when the table lacks a matching row.
Start the KafkaStreams application and verify join correctness by inspecting output topic messages.
Monitor state store restoration time on restart, as the KTable's state store must be fully restored before joins produce correct results.
Known gotchas
KStream-KTable joins are non-windowed: the table provides a point-in-time lookup, and the join result depends on what the table holds at the moment the stream record arrives — late table updates do not trigger re-evaluation of already-joined stream records.
Both topics must have the same number of partitions, or you must co-partition them explicitly; Kafka Streams will throw a TopologyException if co-partitioning requirements are violated.
The KTable is populated from the beginning of the topic on first startup; large compacted topics can cause long restoration delays.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp