Home/Learn/Apache Kafka/Kafka Streams Basics

Kafka Streams Basics

Intermediate
Kafka Streams

Kafka Streams is a Java client library for building stateful, fault-tolerant stream processing applications that read from and write to Kafka topics.

Overview

Kafka Streams is a lightweight, embeddable Java library for building real-time stream processing applications directly on top of Kafka — no separate cluster (Flink, Spark) required. An application processes data by defining a **topology**: a directed acyclic graph of source nodes (reading from topics), processor nodes (transform, filter, aggregate), and sink nodes (writing to topics). Kafka Streams handles fault tolerance through **changelog topics**: state stores are backed by compacted Kafka topics, so state is rebuilt automatically after restart. It integrates with Spring Boot via `spring-kafka` and the `KafkaStreamsConfiguration` API. The high-level **Streams DSL** (`map`, `filter`, `join`, `aggregate`) covers most use cases; the low-level **Processor API** gives full control for custom logic.

Defining a Topology with the Streams DSL

The DSL is built on `StreamsBuilder`. `stream()` creates a `KStream` for record-by-record processing. `table()` creates a `KTable` for keyed state. DSL operations are lazy — no processing happens until the topology is compiled and a `KafkaStreams` instance is started.

Spring Boot — Kafka Streams topology with StreamsBuilder
@Configuration
@EnableKafkaStreams
class StreamConfig {
    @Bean(name = KafkaStreamsDefaultConfiguration.DEFAULT_STREAMS_CONFIG_BEAN_NAME)
    KafkaStreamsConfiguration streamsConfig() {
        return new KafkaStreamsConfiguration(Map.of(
            StreamsConfig.APPLICATION_ID_CONFIG,    "order-processor",
            StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "broker:9092",
            StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG,   Serdes.String().getClass(),
            StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass()
        ));
    }
}

@Component
class OrderTopology {
    @Autowired
    void buildPipeline(StreamsBuilder builder) {
        KStream<String, String> orders = builder.stream("orders-raw");

        orders
            .filter((key, value) -> value.contains(""status":"PAID""))
            .mapValues(value -> enrichOrder(value))
            .to("orders-enriched");   // sink topic
    }
}

Stateful Operations: Aggregations and Joins

Stateful operations (count, aggregate, join) store intermediate state in a local **RocksDB state store** backed by a compacted changelog Kafka topic. On restart, Kafka Streams restores the state store from the changelog before resuming processing — providing fault tolerance without external storage.

Kafka Streams — stateful count and KStream-KTable join
@Autowired
void buildPipeline(StreamsBuilder builder) {
    KStream<String, Order> orders = builder.stream(
        "orders",
        Consumed.with(Serdes.String(), orderSerde)
    );

    // Count orders per customer — stateful aggregation
    KTable<String, Long> orderCounts = orders
        .groupByKey()
        .count(Materialized.as("order-counts-store"));  // named state store

    orderCounts.toStream().to("order-counts-topic",
        Produced.with(Serdes.String(), Serdes.Long()));

    // KStream-KTable join: enrich order with customer data
    KTable<String, Customer> customers = builder.table("customers");
    orders.join(customers,
        (order, customer) -> enrich(order, customer))
        .to("orders-enriched");
}

Fault Tolerance, Scaling, and State Restoration

Kafka Streams achieves fault tolerance via changelog topics — every state store write is also sent to an internal compacted topic. On restart, the state is replayed from the changelog. Scaling is done by adding more application instances: Kafka Streams redistributes partitions (and their associated state) across instances automatically via the Streams rebalance protocol.

Kafka Streams — changelog, standby replicas, scaling
# Kafka Streams fault tolerance and scaling:

# 1. State store backed by changelog topic (created automatically)
#    Internal topic: <app-id>-<state-store-name>-changelog
#    e.g.: order-processor-order-counts-store-changelog

# 2. Restart recovery:
#    App starts → consumer group rebalance → partitions assigned
#    → state store restored from changelog (or standby replica if configured)
#    → processing resumes from last committed offset

# 3. Standby replicas — warm spare state (reduces restore time)
num.standby.replicas=1  # keep 1 standby copy in another instance

# 4. Scaling: run 2 instances of the same application-id
#    → Kafka Streams splits partitions between them
#    → each instance handles its own slice of state

# 5. Interactive Queries — read state store directly (no external DB)
ReadOnlyKeyValueStore<String, Long> store =
    streams.store(StoreQueryParameters.fromNameAndType(
        "order-counts-store", QueryableStoreTypes.keyValueStore()));
Long count = store.get("customer-42");

Key Points to Remember

  • 1Kafka Streams is an embedded Java library — no separate processing cluster required
  • 2A topology is a DAG of source, processor, and sink nodes compiled from the Streams DSL
  • 3Stateful operations use RocksDB state stores backed by compacted changelog topics
  • 4On restart, state is restored from the changelog before processing resumes
  • 5Scaling: run multiple instances of the same application.id; Kafka redistributes partitions
  • 6Interactive Queries expose state store contents directly without an external database

Interview Questions

Sign in to ask Aria
1

How does Kafka Streams achieve fault tolerance without an external database?

MediumConfluent
2

What is the difference between KStream and KTable in Kafka Streams?

EasyAmazon
3

How do you scale a Kafka Streams application horizontally?

MediumLinkedIn
4

What is a changelog topic and what is it used for?

MediumThoughtWorks
5

What are standby replicas in Kafka Streams and why are they useful?

HardUber

Ask Aria about Kafka Streams Basics

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…