Task Assignment and Standby Replicas in Kafka Streams
How a Kafka Streams application divides its work into tasks, spreads those tasks across instances and threads, and keeps warm copies of state ready so that a failure costs seconds instead of minutes.
Imagine a busy restaurant kitchen with many cooks. Each cook owns a station, such as grilling, salads or desserts, and each station keeps its own supplies and half-prepared food within reach. If a cook falls ill in the middle of the dinner rush, the manager must decide who takes over that station. If the replacement has to fetch every ingredient from the warehouse and prepare everything from scratch, guests wait for a long time. If another cook has been quietly shadowing the station and already has the supplies laid out, service barely stops.
Kafka Streams applications live in exactly this situation. The application is divided into small units of work called tasks. Many of those tasks keep local state, and that state is expensive to rebuild. The way tasks are handed out, and the option to keep shadow copies of state called standby replicas, decide how quickly your application recovers from failures and how smoothly it scales. This tutorial explains both ideas from the ground up, all the way to the advanced details that architects need in production.
1Why Assignment and Standby Copies Matter
Before any vocabulary, we must feel the problem these features solve.
Stream processing that remembers
Some stream processing is simple. Read a message, change it a little, write it out, and forget it. If an instance running this kind of logic dies, another instance simply carries on. Nothing needs to be rebuilt.
Many useful applications are not like that. They count events, sum values over time windows, join two streams together or remember the latest value for every key. To do this they must remember things between messages. That memory is called state, and it is kept in a local store on the machine that runs the work. If that machine is lost, the memory is lost with it, and it must be reconstructed before work can continue.
A cashier who tallies the day’s sales in a notebook can be replaced instantly if the notebook is available. If the notebook burns, the replacement must re-add every receipt from the morning onward before the tally is correct again. The bigger the notebook, the longer the recovery.
Two questions every Streams application must answer
Who does which work?
When several instances of the application run, something must decide which instance handles which slice of the input. This is task assignment.
What happens when someone leaves?
When an instance fails, or a new one joins, work must move. Moving stateful work is slow unless the state is already nearby.
How fast can we recover?
The answer depends on how much state must be rebuilt at the new location, and on whether a warm copy already exists there.
How much are we willing to pay?
Warm copies consume disk, network and processing. Every application must decide how much insurance is worth buying.
Task assignment and standby replicas are features of the Kafka Streams library, not of the Kafka brokers. Brokers only store topics and coordinate groups. Everything described here happens inside your Streams application processes.
2Kafka Streams in Five Minutes
A quick tour of the library gives us the vocabulary needed for everything that follows.
A library, not a cluster
Kafka Streams is a Java library that you embed inside your own application. There is no separate processing cluster to install. You start several copies of your application, and they cooperate through Kafka itself. Adding capacity means starting more copies. Removing capacity means stopping some. The copies find each other and share the work automatically.
The building blocks
Topology
The graph of processing steps that your application applies to its input streams, from sources through transformations to sinks.
Application identifier
A name that identifies the whole application. All copies with the same name form one logical application and share one consumer group.
Instance
One running copy of your application, typically one process on one machine or container.
Stream thread
A worker thread inside an instance. An instance can run one or several threads, and each thread runs a share of the tasks.
Task
The smallest unit of work and the smallest unit of assignment. We study it closely in the next chapter.
State store
A local, queryable store of data that a task uses to remember things between records, usually kept on local disk.
Changelog topic
A Kafka topic that records every change to a state store, so the store can always be rebuilt from Kafka.
Standby replica
A shadow copy of a task’s state, kept warm on another instance, ready to take over quickly.
Think of a chain of bakeries that share one recipe book. Each shop is an instance. Each baker in a shop is a thread. Each baker is responsible for a few specific products, which are the tasks. The recipe book is the topology, and every shop follows it.
Built on the consumer group
Under the surface, all instances with the same application identifier form a single consumer group. That means they use the same group membership machinery that ordinary Kafka consumers use. When an instance joins or leaves, the group rebalances, and the partitions of the input topics are redistributed. Kafka Streams adds its own logic on top to decide how tasks, and therefore state, are distributed.
Some beginners believe that Kafka brokers run the Streams processing. They do not. Brokers only store data. All computation, all state and all task logic run inside your application instances.
3From Partitions to Tasks: The Unit of Work
A task is the atom of a Streams application. Understanding it makes assignment obvious.
Why partitions are the natural unit
A Kafka topic is split into partitions, and within a partition the order of messages is fixed. To keep results correct, all messages for one key must be processed by the same worker, in order. Partitions are the units that already guarantee this. So Kafka Streams divides its work by partition.
What a task is
For each partition of the input, and for each independent part of your topology, the library creates one task. A task reads records from its partition or partitions, runs them through its portion of the processing steps, updates its own local state stores and writes results. A task never shares its state with any other task. Two tasks can therefore run on different machines with no coordination between them, which is what makes Streams scale.
A postal sorting office divides the country into postcode areas. Each area has one sorter with a private set of pigeonholes. Nobody else touches those pigeonholes. Adding more sorters means giving each of them a smaller set of areas, but never splitting one area between two sorters.
Input partitions exist
Each input topic has a fixed number of partitions.
Library reads the topology
It determines which parts of the processing graph depend on each other and which are independent.
Tasks are created
One task is created for each partition number in each independent part of the topology.
Tasks are assigned
The tasks are handed out to threads on instances, and each task runs where it is placed.
Task identity
Each task has a two-part identity written like a pair of numbers: the first identifies which independent part of the topology it belongs to, and the second is the partition number. A task named with the pair one and three, for example, handles partition three of the second independent part. This identity is stable across restarts, and it is how the library, its state directories and its changelog topics all refer to the same piece of work.
The number of tasks caps how many threads across all instances can be busy. If your input topic has twelve partitions and your topology has one independent part, you have twelve tasks. Running thirty threads will leave eighteen of them idle.
4Sub-topologies and How Many Tasks You Really Have
Not every processing graph produces the same number of tasks. The shape of the graph matters.
Independent parts of a topology
A topology may look like one connected picture, but the library splits it into smaller pieces called sub-topologies. A boundary between sub-topologies appears wherever data has to be moved through an intermediate Kafka topic, for example when you re-group records by a new key. Each sub-topology can be processed independently, because the topic in between decouples them.
flowchart LR
subgraph S0["Sub-topology 0"]
A["Read orders"] --> B["Filter and re-key"]
end
B -->|"repartition topic"| C
subgraph S1["Sub-topology 1"]
C["Read repartitioned data"] --> D["Aggregate by customer"] --> E["Write totals"]
end
Counting tasks
The number of tasks is the sum, over all sub-topologies, of the number of partitions each one reads. A sub-topology that reads from a topic with eight partitions produces eight tasks. If a second sub-topology reads from a repartition topic with eight partitions, it produces another eight tasks. The total is sixteen.
| Sub-topology | Reads from | Partitions | Tasks |
|---|---|---|---|
| 0 | Orders topic | 8 | 8 |
| 1 | Repartition topic | 8 | 8 |
| 2 | Customer profile topic | 4 | 4 |
| Total tasks | 20 | ||
Co-partitioning
When a sub-topology joins two input topics, both must have the same number of partitions and use the same key-to-partition method. Only then does key seven in one topic land in the same partition number as key seven in the other. A single task then reads the matching partition from both topics and can join them locally. The library keeps such partitions together in one task for exactly this reason.
Two filing cabinets are arranged alphabetically in the same way. To match a customer file with their invoices, one clerk can open drawer G in both cabinets and compare them without walking around the office. If the cabinets were arranged differently, matching would be a nightmare.
Changing the partition count of an input topic after a stateful application has been running changes the meaning of every task and breaks the link between keys and state. Choose partition counts with future growth in mind before the first deployment.
5Instances, Threads and Where Tasks Live
Tasks are placed onto threads, and threads live in instances. Two levels of placement are involved.
Two levels of placement
First the library decides which instance owns a task. Then, inside that instance, the task is given to one of its stream threads. Each thread runs its tasks one after another in a loop, reading a bit from each, so a thread with several tasks shares its time among them. A task always runs on exactly one thread at a time.
flowchart TB
subgraph I1["Instance A"]
T1["Thread 1: tasks 0_0 and 0_1"]
T2["Thread 2: tasks 0_2 and 0_3"]
end
subgraph I2["Instance B"]
T3["Thread 1: tasks 1_0 and 1_1"]
T4["Thread 2: tasks 1_2 and 1_3"]
end
Balancing goals
Even load
Each thread should get a similar number of tasks so that no thread is overloaded while another sits idle.
Even stateful load
Tasks that carry state are heavier than stateless tasks, so they should be spread as evenly as possible.
Keep tasks where they were
A task that already has its state on some instance should stay there to avoid costly rebuilding.
Keep copies apart
A standby copy must never live on the same instance as its active task, or one failure would remove both.
A manager assigning tables to waiters wants each waiter to have a similar number of tables, wants a waiter to keep tables whose guests they already know, and never wants a table and its backup waiter to be the same person.
Adding threads inside one instance is easy but shares one machine’s memory and disk. Adding instances spreads state across machines and survives machine failures. For fault tolerance, instances matter more than threads.
6State Stores and Changelog Topics
State is what makes assignment matter. Here is how it is stored and protected.
The local store
Each stateful task keeps its data in a local store. By default this is an embedded key-value database on local disk, with an in-memory cache in front of it. Reads and writes are extremely fast, because they never leave the machine. Each task has its own private store, stored in a directory named after the task, under the application’s state directory.
The changelog topic
Local disks fail, so the library also records every change to the store in a special Kafka topic, called a changelog topic. Each store gets one changelog topic, with the same number of partitions as the task count of its sub-topology, so each task has its own changelog partition. Changelog topics are replicated by Kafka and use log compaction, which keeps only the latest value for each key, so they do not grow forever.
A shopkeeper keeps a cash register on the counter for quick use, and also writes every sale into a ledger stored at head office. If the register is stolen, the head office ledger can be replayed to rebuild the register’s contents.
flowchart LR
IN["Input partition"] --> TK["Task"]
TK --> ST["Local state store on disk"]
TK -->|"every update"| CL["Changelog topic partition in Kafka"]
TK --> OUT["Output topic"]
CL -. "rebuild after loss" .-> ST
Restoring state
When a task starts on a machine that does not have its store, the library restores it by reading the task’s changelog partition from the beginning and applying every record to a fresh local store. Only when this restoration finishes can the task begin processing new input. The bigger the store, the longer the restoration takes.
| Situation | Where the store comes from | Time before processing resumes |
|---|---|---|
| Task restarts on same machine with disk intact | Local files, then a short catch-up from the changelog | Short |
| Task moves to a machine with a standby copy | The warm standby store, then a short catch-up | Short |
| Task moves to a machine with no copy | Full replay of the changelog | Long, grows with store size |
| Stateless task moves anywhere | Nothing to restore | Immediate |
Restoring a store with hundreds of millions of keys from a changelog can take many minutes or even hours. During that time the task produces nothing, and downstream consumers see a stall. This is the pain that standby replicas exist to remove.
7Rebalances and the Role of the Assignor
Whenever group membership changes, work must be redistributed. A special component makes the decision.
What triggers a rebalance
An instance joins
A new copy of the application starts and asks to share the load.
An instance leaves or fails
A copy shuts down or stops sending heartbeats, and its tasks need new homes.
Topic changes
Input partitions are added or a subscribed topic appears or disappears.
Probing rebalance
A scheduled rebalance the library itself requests to check whether warm-up copies have caught up. We will meet this later.
The group leader computes the plan
During a rebalance, one member of the group is chosen as the leader. Every member sends the leader information about itself. In Kafka Streams, this information includes which tasks the member currently holds, how far behind its stores are, and which tasks it holds as standby copies. The leader runs the task assignor, a piece of logic that produces the new plan, and sends each member its share.
Members join
Every instance sends a join request that includes its current tasks and store information.
Leader collects
The group leader receives the subscriptions of all members.
Leader computes
The task assignor decides which member gets each active task and each standby task.
Plan is distributed
Each member receives its assignment and starts, stops or moves tasks accordingly.
In a team meeting, everyone tells the chairperson what they are currently working on and how much they know about each project. The chairperson makes a new roster and reads it out. The staff then carry out their new duties.
The partition assignment of the consumer group and the task assignment of Kafka Streams are two sides of the same plan. The Streams assignor decides tasks, and that automatically decides which input partitions each member reads.
8The Goals of Task Assignment
A good assignor balances several competing goals at once. Knowing them explains its behavior.
| Goal | Why it matters | Tension with other goals |
|---|---|---|
| Balance | Uses all capacity evenly, avoiding hot instances | Perfect balance may move many stateful tasks |
| Stickiness | Keeps tasks with the state they already have | May leave the group slightly unbalanced |
| Co-location of co-partitioned inputs | Required for joins to work locally | Reduces freedom to spread partitions |
| Standby separation | Keeps backups on different machines from active tasks | Needs enough instances to satisfy |
| Fast availability | Gets processing resumed quickly after change | Favors warm state over ideal balance |
| Stateful spread | Prevents one instance from holding too much state | May conflict with stickiness |
| Rack or zone awareness | Reduces cross-zone traffic and survives zone loss | Adds constraints to placement |
The central tension
The most important tension is between balance and stickiness. Moving a task to fix imbalance means restoring its state at a new location, which takes time. Leaving it where it is avoids restoration but may leave one instance busier than another. A good assignor keeps tasks sticky by default and moves them only when the benefit is worth the cost, and where possible moves them gradually.
A school head rearranging classroom teachers could reassign everyone for perfect balance every term, but pupils lose the teacher who knows them. A wise head only moves a teacher when the imbalance is truly harmful, and prepares the move in advance.
Stateless tasks are free to move
Tasks without local state can be placed anywhere at no cost, so the assignor uses them to even out the load after placing the stateful ones.
Stateful tasks are weighed by history
The assignor prefers to give a stateful task to an instance that already holds its store, or a recent copy of it.
Standbys are placed after actives
Active tasks are placed first, and standby copies are then placed on other instances, again preferring instances that already hold matching state.
9Sticky Assignment and the Pain of Moving State
Stickiness is the simplest defense against slow recovery. It also has limits.
What sticky means
A sticky assignor tries to give each task to the same member that ran it last time. When a new member joins, only enough tasks are moved to it to balance the group, and the rest stay put. When a member leaves, only its tasks move, and they move to the members that already hold the most useful state for them.
Start from the previous assignment
The assignor takes the last known placement of every task as its starting point.
Remove departed members
Tasks that belonged to members that left become unassigned.
Place unassigned tasks
Each unassigned task goes to the member with the best chance of having its state and with spare capacity.
Rebalance minimally
If members are unevenly loaded, move as few tasks as needed to bring them within an acceptable range.
The problem with pure stickiness
A purely sticky approach protects existing state but handles growth poorly. Suppose an application runs on three instances and you add a fourth to relieve load. The new instance has no state at all. If the assignor hands it tasks immediately, it must restore each store from scratch before it can process anything, and during that time the tasks are not making progress anywhere. The system got worse, not better, right after scaling out.
When new capacity is added, tasks handed to it are unavailable until their state is restored. Without help, adding an instance to an application with large state can pause processing for the moved tasks for a long time.
Strengths of sticky assignment
- Very fast recovery after brief interruptions
- Minimal data movement during normal operation
- Predictable placement that operators can reason about
Weaknesses of pure stickiness
- New instances receive no state and no work until forced
- Handing state-heavy tasks to a new instance causes long stalls
- After failures, work may pile up on the members that held the state
A new employee joins a busy team on Monday. If the manager hands over the most complex projects on day one, the projects stall while the newcomer learns. A better manager lets the newcomer shadow and learn first, and hands over the work only when they are ready. That idea leads us to warm-up copies.
10Standby Replicas: A Warm Copy Waiting in the Wings
A standby replica is the direct answer to the cost of cold starts.
The idea
A standby replica is a copy of a task’s state store maintained on a different instance from the active task. The standby does not process input or write any output. It only keeps its local store up to date by reading the same changelog topic that the active task writes. If the active task’s instance fails, the standby’s instance can take over almost immediately, because its store is already nearly complete.
A trainee chef stands behind the head chef at every service, watching and keeping their own copy of the recipe notes up to date, but never cooking any dish. If the head chef leaves suddenly, the trainee already knows the current state of every dish and steps in within moments.
Active tasks and standby tasks
Active task
Reads input, processes records, updates state, writes output and writes to the changelog. There is exactly one active copy of each task.
Standby task
Reads only the changelog and applies updates to a local copy of the store. It never processes input and never produces output.
Warm-up task
A temporary standby created to prepare a new home for an active task before the task moves there. We cover it in a later chapter.
Stateless task
Has no store, so it has no need for a standby copy.
flowchart LR
IN["Input partition"] --> AT["Active task on Instance A"]
AT --> S1["Store on Instance A"]
AT -->|"writes"| CL["Changelog partition"]
CL -->|"reads only"| SB["Standby task on Instance B"]
SB --> S2["Warm copy of store on Instance B"]
AT --> OUT["Output topic"]
How many standbys
The number of standby copies per task is a single setting. The default is zero, meaning no standbys, and any positive number creates that many additional copies of every stateful task, each on a different instance. One standby protects against a single instance failure. Two protect against two overlapping failures, and so on. Each copy costs disk space and network and processing to keep up to date.
Because a standby must live on a different instance from its active task and from the other standbys, the number of instances must be larger than the number of standby copies. Asking for more standbys than the cluster can place simply results in fewer copies than requested.
11How a Standby Task Works Inside
A standby task is simple by design, which is exactly why it is cheap to keep.
What a standby does all day
A standby task runs the same restoration logic used at startup, but it never stops. It continuously reads new records from the changelog partition and applies each update to its local store. It does not run the processing steps of the topology, so it does no business computation and calls no external services. Its whole job is to copy.
Created by the assignment
The plan gives an instance a standby role for a specific task.
Initial restore
If the instance has no store, it reads the changelog from the start until it has caught up.
Continuous tailing
It keeps reading new changelog records and applying them, staying within a small distance of the active task.
Checkpointing
It records how far it has read so that a restart does not begin from scratch.
Promotion when needed
If the assignor makes it the active owner, it finishes any remaining catch-up and starts processing input.
Standbys are read-only followers
A standby never writes to the changelog and never writes output. It is a follower in the same sense that a Kafka replica is a follower: it only consumes and applies. This keeps the design free of write conflicts and means a standby can be added or removed without affecting the correctness of the active task.
A court stenographer’s assistant copies each page of the transcript into a second binder as it is written. The assistant never speaks in court and never edits the main transcript, but if the stenographer leaves, the assistant’s binder is almost complete.
| Activity | Active task | Standby task |
|---|---|---|
| Reads input topic | Yes | No |
| Runs processing logic | Yes | No |
| Reads changelog | Only during restore | Always |
| Writes changelog | Yes | No |
| Writes output | Yes | No |
| Maintains local store | Yes, as it processes | Yes, as it copies |
| CPU cost | Higher | Lower, mostly applying updates |
The work of a standby scales with the rate of state updates, not with the complexity of your processing logic. An application that updates state constantly makes its standbys work hard, and one that updates rarely makes them nearly idle.
12Failover With and Without a Standby
The payoff of standby copies is easiest to see by comparing two failures side by side.
Failure without a standby
Instance fails
The instance stops sending heartbeats and is removed from the group after the session timeout.
Rebalance
The group rebalances and the orphaned tasks are assigned to surviving instances.
Full restore
Each new owner replays the entire changelog of its new task to rebuild the store from nothing.
Processing resumes
Only after the restore ends does the task process input again. The pause lasts as long as the restore.
Failure with a standby
Instance fails
Same detection delay as before.
Rebalance favors the standby
The assignor sees which instance already holds a warm copy and gives the active role to that instance.
Short catch-up
The promoted task only replays the small remainder of the changelog that it had not yet applied.
Processing resumes quickly
The pause is largely the failure detection and rebalance time, with little restoration time on top.
sequenceDiagram
participant A as Instance A active task
participant B as Instance B standby
participant G as Group leader
participant K as Kafka changelog
A->>K: Write state updates
B->>K: Read updates and apply
A->>A: Crash
G->>G: Detect failure, run rebalance
G-->>B: Promote to active for the task
B->>K: Read remaining few updates
B->>B: Resume processing input
| Phase | No standby | With standby |
|---|---|---|
| Failure detection | Session timeout | Same |
| Rebalance | Same | Same |
| State recovery | Full changelog replay | Small catch-up |
| Total pause | Detection plus rebalance plus long restore | Detection plus rebalance plus short catch-up |
| Scales with store size | Yes, badly | Barely |
A standby only shortens the recovery step. The time to notice the failure and to complete the rebalance remains. To shorten those, tune group timeouts and use features such as static membership, which we cover later.
13Where Standbys Are Placed
A standby is only useful if it is not lost in the same accident as the active task.
The basic rules
Never on the same instance as the active
Otherwise one machine failure would remove both copies.
Never two copies of one task on one instance
Multiple standbys of the same task must each live on different instances.
Spread standbys evenly
Standby load should be balanced across instances so one instance is not burdened with all the copying.
Prefer instances that already hold the state
If an instance already has a partial copy, giving it the standby role avoids copying from scratch.
Instances versus threads
The separation applies at the level of instances, not threads. Two threads in the same instance share the same machine and the same state directory. A standby on a different thread of the same instance would offer no protection against machine loss, so the assignor places it on a different instance.
Keeping a spare copy of an important document in the same drawer as the original is pointless if the drawer is stolen. The spare must be kept in a different building. Instances are the buildings, and threads are just desks within a building.
flowchart TB
subgraph IA["Instance A"]
A1["Active task 0_0"]
S2["Standby task 0_1"]
end
subgraph IB["Instance B"]
A2["Active task 0_1"]
S3["Standby task 0_2"]
end
subgraph IC["Instance C"]
A3["Active task 0_2"]
S1["Standby task 0_0"]
end
A neat way to picture balanced standbys is a rotation: each instance’s standby duty covers the neighbour’s task. Every instance carries one active and one standby, so loads are equal and no single failure removes any task’s only copy.
Not enough instances
With a single instance, no standby can be placed at all, because there is nowhere different to put it. With two instances and two standbys requested, only one standby per task is possible.
Uneven instance sizes
Assignment works by counting tasks, not by measuring machine size. Mixing very large and very small machines in one application can lead to overloaded small machines.
14The Real Cost of Standby Replicas
Insurance is never free. Understanding the bill helps you choose the right amount.
Disk space
Each standby holds a full copy of the store. One standby doubles the total state disk footprint of the application, and two triple it.
Network traffic
Every update to the changelog is read again by each standby, multiplying read traffic on the brokers by the number of copies.
Broker load
More consumers reading changelog partitions means more work for the brokers that lead those partitions.
CPU on instances
Applying updates to a local database consumes processor time and disk input and output on the standby’s machine.
Memory
Local store caches and buffers are needed per store, including those held for standbys.
| Standbys per task | Total copies of state | Failures tolerated with warm recovery | Typical fit |
|---|---|---|---|
| 0 | 1 | None, every failure means a cold restore | Small state, batch-like or tolerant applications |
| 1 | 2 | One instance failure at a time | Most production applications with meaningful state |
| 2 | 3 | Two overlapping failures | Critical services, larger clusters, zone-spread deployments |
| 3 or more | 4 or more | Very high protection | Rare, only for extreme availability needs |
Extra copies of a vital key cost a little for each key and for safe storage. One spare key with a neighbour covers most lockouts. Ten spare keys spread around town buys very little additional safety for a lot more effort.
A sensible way to decide
Measure the restore time
Time a cold restore of your largest store in a test environment.
Compare with your tolerance
Decide how long a pause your business can accept after a failure.
Price the alternative
Estimate the disk, network and broker cost of one standby.
Choose and verify
Pick the smallest number of standbys that meets your tolerance, and test failover to confirm.
If your stores are small and restore in seconds, standbys add cost without real benefit. Reserve them for applications where restore time is long compared with what the business can tolerate.
15Warm-Up Replicas and the High-Availability Assignor
A standby helps after a failure. Warm-up replicas help during a planned change, like scaling out.
The insight
When a new instance joins, the goal is to give it work. But giving it tasks whose state it does not have would stall those tasks during restoration. A better approach is to leave each task where it is, and separately ask the new instance to build a warm copy in the background. Once the copy has caught up, the task can move with hardly any interruption. This is the idea behind warm-up replicas, introduced with the high-availability task assignor.
A new employee shadows an experienced colleague for a few weeks, keeping up with all the notes, but not yet taking responsibility. Only when the newcomer is fully up to date does the manager hand over the actual duties, so customers never notice a change.
New instance joins
The group rebalances. The assignor calculates the ideal balanced assignment.
Do not move stateful tasks yet
Tasks whose ideal home is the new instance stay on their current instance for now, because the new instance is not ready for them.
Start warm-up copies
The new instance is assigned warm-up replicas of the tasks it will eventually own. They start restoring in the background while the old owners keep processing.
Probe periodically
The library schedules follow-up rebalances, called probing rebalances, to check how far each warm-up copy has progressed.
Move when caught up
When a warm-up copy is close enough to the changelog end, the next rebalance moves the active task to it, and the old owner keeps or drops a standby.
sequenceDiagram
participant O as Old owner
participant N as New instance
participant G as Group leader
N->>G: Join group
G-->>O: Keep task active for now
G-->>N: Build warm-up copy of task
N->>N: Restore in background
G->>G: Probing rebalance, check lag
G-->>N: Copy caught up, become active
G-->>O: Release task, optionally keep standby
Because warm-up replicas are limited in number at any moment, the migration happens in waves, avoiding a sudden flood of restore traffic on the brokers and on the new instance.
16Task Lag, Acceptable Recovery Lag and Probing
The assignor needs a measurable notion of “caught up”. That notion is called lag.
What lag means for a task
The lag of a task’s store on some instance is the number of changelog records that have been written but not yet applied to that instance’s copy. A lag of zero means the copy is perfectly current. A lag of a million means the copy is a million updates behind. Every instance reports the lag of each store it holds, so the group leader can compare candidates for each task.
Two students copy a teacher’s notes. One is three lines behind, another is three chapters behind. If the first student must take over, only three lines are missing. If the second must take over, the whole afternoon is lost. Lag measures how many lines are missing.
The acceptable recovery lag
The library has a setting that defines how far behind a copy may be while still counting as caught up enough to become active. If a copy’s lag is within this threshold, it is considered ready, since catching up the small remainder takes only moments. If it is above the threshold, the copy is still considered too cold to take over, and the assignor prefers to keep the task where it is while the copy continues to catch up.
Acceptable recovery lag
The maximum lag, in records, at which a copy is considered ready to take over as active.
Maximum warm-up replicas
The limit on how many warm-up copies may be restoring at the same time, controlling how fast the migration proceeds.
Probing rebalance interval
How often the library schedules a rebalance just to re-check progress while warm-up copies are still catching up.
Number of standby replicas
How many permanent shadow copies each stateful task gets, separate from temporary warm-up copies.
Trade-offs when tuning
| Change | Benefit | Risk |
|---|---|---|
| Lower acceptable lag | Smaller pause when a copy is promoted | Copies may rarely qualify on busy stores, delaying moves |
| Higher acceptable lag | Moves happen sooner | Longer catch-up pause after promotion |
| More warm-up replicas at once | Faster scale-out completion | Bursts of restore traffic on brokers and instances |
| Fewer warm-up replicas at once | Gentle load, stable cluster | Slower migration to new instances |
| Shorter probing interval | Tasks move promptly once ready | More frequent rebalances |
| Longer probing interval | Fewer rebalances | Tasks wait longer before moving |
During a scale-out you may see several rebalances spaced out over time even though nothing failed. That is the library probing on purpose. Do not mistake them for instability, but do watch that they eventually stop.
17Cooperative Rebalancing and Newer Protocols
Assignment is only half the story. How the handover happens decides how much of the application pauses.
The old way: stop the world
In the original rebalance protocol, every member gave up all of its partitions at the start of each rebalance, waited for the new plan and then resumed. For the whole duration, no member processed anything, even the tasks that would end up exactly where they were. A rebalance was therefore a global pause.
The cooperative way: move only what must move
Cooperative rebalancing changes this. Members keep processing the tasks that are not changing owners, and only the tasks that must move are paused and handed over. The rebalance can take two rounds: first, tasks that need to leave are released, then they are given to their new owners in the following round. Everything else keeps running throughout.
sequenceDiagram
participant A as Instance A
participant B as Instance B
participant G as Group leader
Note over A,B: Both are processing normally
G-->>A: Release task X only
A->>A: Pause and hand over task X
G-->>B: Second round: receive task X
B->>B: Restore or promote and start task X
Note over A,B: All other tasks kept running throughout
When a restaurant reshuffles waiters between tables, the old approach is to make everyone stop serving, wait for the manager’s new list, and start again. The cooperative way is to tell only the two waiters who swap tables to stop, and everyone else keeps serving guests the whole time.
Combined with warm-up replicas
Cooperative rebalancing and warm-up replicas work together. Warm-up copies prepare state in advance, and cooperative rebalancing then moves only the ready tasks, one wave at a time, without pausing the rest of the application. The combined effect is that scaling out and rolling restarts become mostly invisible to downstream consumers.
Newer group protocols
Recent Kafka releases have introduced a newer generation of group protocols in which more of the coordination is moved to the broker side, and there has been work on a dedicated protocol for Kafka Streams applications that lets the broker track and assign tasks. The details depend on the release and feature status, so consult the release notes of the version you run. The underlying concepts in this tutorial, tasks, active and standby roles, lag and warm-up, stay the same.
Modern rebalancing behavior depends on the client library version and sometimes on broker features. Running very old library versions means living with longer pauses that newer versions have already solved.
18Static Membership and Avoiding Needless Rebalances
The cheapest rebalance is the one that never happens.
The cost of routine restarts
Every time an instance restarts, for example during a rolling deployment, the group sees it leave and rejoin, and by default a rebalance occurs each time. In a group of many instances, a rolling restart can trigger a long series of rebalances, each moving tasks around and forcing restorations, only for tasks to end up back where they started.
Static membership
Static membership lets each instance carry a permanent identifier. When an instance restarts and comes back with the same identifier within the session timeout, the group recognizes it as the same member returning and simply gives it back its previous tasks, without a rebalance. Its local state is still on disk, so it only needs a short catch-up from the changelog.
A waiter who steps out for a short break leaves a “back in ten minutes” sign on their tables. The manager does not reassign the tables. Only if the waiter does not come back in time are the tables given to others.
Benefits
- Rolling restarts trigger far fewer rebalances
- Tasks stay on the machines that hold their state
- Local state on disk is reused after restart
- Less churn for downstream consumers
Costs and cautions
- Real failures take longer to detect if the session timeout is set long
- Each instance needs a stable, unique identifier
- The local state directory must survive restarts to be useful
- Duplicate identifiers cause members to fence each other out
Rolling deployments on stable machines
Static membership shines when the same machines or volumes restart quickly and keep their disks, so the old state is still available.
Choosing the session timeout
The session timeout is a balance. Long enough to cover a quick restart, short enough that a genuine failure is detected without an unacceptable delay. Standby replicas then cover the failure case.
Static membership avoids unnecessary moves during planned restarts. Standbys shorten recovery when a machine is truly lost. Together they cover both routine maintenance and real failures.
19Rack-Aware and Zone-Aware Assignment
In the cloud, machines belong to zones, and zones fail together. Assignment can be taught to respect that.
Why location matters
If an active task and its standby happen to sit in the same availability zone, a zone outage removes both. Also, reading input partitions from a broker in a different zone costs network fees and adds latency. Modern assignors can take location into account.
Spread copies across zones
Active tasks and their standbys are placed in different zones so a zone outage leaves a warm copy elsewhere.
Reduce cross-zone traffic
Where possible, tasks are placed near the brokers holding the partitions they read, reducing transfer costs and delay.
Instances must declare their location
Each instance states which rack or zone it runs in, so the assignor knows where it is.
Brokers must declare theirs
Brokers publish their rack information, so partitions and their replicas have known locations.
flowchart LR
subgraph ZA["Zone A"]
A1["Instance 1: active 0_0, standby 0_1"]
end
subgraph ZB["Zone B"]
A2["Instance 2: active 0_1, standby 0_2"]
end
subgraph ZC["Zone C"]
A3["Instance 3: active 0_2, standby 0_0"]
end
A company keeps a backup of its accounts in a second city, not in the same building. A flood in one city cannot destroy both. Zones are the cities in this picture.
| Concern | Without location awareness | With location awareness |
|---|---|---|
| Zone outage | Active and standby may both be lost | A standby survives in another zone |
| Cross-zone data fees | Random, often high | Reduced by keeping traffic local |
| Balance across zones | Uncontrolled | Aimed for by the assignor |
| Configuration effort | None | Requires location settings on instances and brokers |
Rack-aware task assignment arrived in recent library versions and is enabled through settings. Check the documentation for your version to learn the exact strategy options and their trade-offs between traffic cost and balance.
20Scaling Out and In: A Complete Walkthrough
Let us watch a real change unfold, step by step, using everything we have learned.
An application runs on three instances named A, B and C. It has twelve stateful tasks, four on each instance. It is configured with one standby per task. Traffic has grown, so the team adds a fourth instance, D.
D starts and joins the group
D has an empty state directory. It announces itself, and a rebalance begins.
The ideal plan is calculated
With four instances, the ideal is three active tasks each. Three tasks should move to D, one from each of A, B and C.
Actives stay put, warm-ups start
Because D holds no state, those three tasks stay with their current owners. D is given warm-up copies of them and starts restoring in the background.
Normal processing continues
A, B and C keep processing all twelve tasks at full capacity. Downstream sees no pause.
Probing rebalances check progress
At regular intervals the group re-evaluates. Warm-up copies with small lag are declared ready.
Ready tasks move
For each ready task, the active role moves to D. Only a short catch-up is needed. The previous owner may keep a standby copy, which helps balance standby placement.
Steady state
Each of the four instances now holds three active tasks and three standby tasks, and rebalances stop.
Scaling in
Removing an instance follows the reverse pattern. If instance D is shut down gracefully, its tasks are redistributed. Where standbys exist, the instances holding those standbys become the natural new owners, and recovery is quick. If standbys are absent, the new owners must restore from the changelog and processing for those tasks pauses during the restore. Where possible, plan scale-in with warm copies already present.
| Event | Best case | Worst case |
|---|---|---|
| Scale out with warm-up replicas | Tasks move only after they are ready, no pause | Migration takes a long time if stores are large and limits are low |
| Scale out without warm-up support | Small stores, short pauses | Large stores, long stalls on moved tasks |
| Scale in with standbys in place | Standby holders take over quickly | Not enough spare capacity, overloading survivors |
| Scale in without standbys | Small stores restore fast | Large stores restore slowly, pause is long |
Adding or removing one instance at a time, and waiting for rebalances and probing to settle in between, is gentler and more predictable than making large changes all at once.
21Failure Scenarios One by One
A design is proven on its worst day. Here is what happens in the situations operators fear most.
Scenario: one instance crashes, standbys exist
Detection takes up to the session timeout. The rebalance promotes standbys on surviving instances to active. After a short catch-up they resume. The application then creates new standbys elsewhere to restore its protection level.
Scenario: one instance crashes, no standbys
The orphaned tasks are given to survivors, which must restore each store fully from its changelog. Processing for those tasks pauses for the duration of the restore, which could be long for large stores.
Scenario: an instance and its standby holder crash together
With one standby, tasks whose active and standby were both on the failed instances lose their warm copy. Their new owners must restore from the changelog. Additional standbys would have protected against this double failure.
Scenario: a whole zone fails
If copies are spread across zones, standbys in the surviving zones take over. If not, both active and standby may have been in the lost zone, forcing full restores.
Scenario: the state directory is lost but the instance survives
The instance restarts with no local stores. It must restore from changelogs, unless another instance holds a standby and the assignor moves the task there.
Scenario: a broker holding changelog partitions fails
Kafka elects new leaders for those partitions. Tasks and standbys see a short interruption reading or writing the changelog and then continue. Local state is unaffected.
Scenario: a standby falls far behind
If a standby cannot keep up with the update rate, its lag grows. It becomes less useful as a failover target, and the assignor may prefer another copy. Investigate the machine’s disk and processor capacity.
| Failure | Standby present | Standby absent |
|---|---|---|
| Single instance crash | Short pause | Pause equal to restore time |
| Rolling restart | Short catch-ups, especially with static membership | Restores unless disks persist |
| Disk lost, machine alive | Task moves to standby holder | Full restore on the same machine |
| Two simultaneous failures | Depends on standby count and placement | Full restores |
After a failure, the application must build new standby copies to regain its protection level. During that period a second failure is more dangerous, so avoid maintenance actions right after an incident.
22Interactive Queries and Reading From Standbys
State stores are not only for processing. Applications can also query them, and standbys can help with that too.
Queryable state
Kafka Streams lets an application expose its state stores to outside callers, for example a web service answering “what is the current total for customer forty-two”. Because state is spread across instances, a query must be sent to the instance that holds the requested key. The library can tell you which instance is the active owner of a key, so a service can route each request correctly.
Standbys as read replicas
During a failure or rebalance, the active copy of a store may be temporarily unavailable, so queries against it would fail. The library allows queries against standby copies, and against stores that are still restoring, if the caller accepts that the data may be slightly stale. This trades freshness for availability and can keep an interactive service responding through disruptions.
If the head office reference desk is closed for a moment, a branch office with a slightly older copy of the reference book can still answer most questions. The answer may be a few minutes out of date, but it is far better than no answer.
Benefits of querying standbys
- Queries continue during failover and rebalances
- Read load can be spread across more instances
- Standby stores are already warm and cheap to read
Cautions
- Results may be stale by the standby’s lag
- Callers should be told, or should check, how stale a result is
- Not suitable when strict up-to-date answers are required
Dashboards and status pages
Slightly stale numbers are usually acceptable and availability matters more, so standby reads suit them well.
Decisions that must be exact
For actions that need the very latest value, query only the active owner and accept short unavailability during moves.
The library can report how far behind a standby is. Good services use this to reject reads from copies that are too stale, or to label answers with their age.
23Capacity Planning: Disk, Memory and Network
A plan that ignores capacity works in tests and fails in production. Here is how to think about the numbers.
Disk
Each instance stores the local state of every active task and every standby it holds. Total disk across the application is roughly the size of all stores multiplied by one plus the number of standbys. Each instance’s share is that total divided by the instance count, with headroom for uneven task sizes and for the temporary extra copies created during migration. Because the embedded database also needs space for its own maintenance work, leave a comfortable margin rather than filling disks.
Memory
Each store has caches and buffers. Standby stores have them too, even though they process no input. Multiply the per-store memory by the number of stores an instance holds, active and standby together. Running out of memory on an instance can cause it to fail, triggering the very rebalances you wanted to avoid.
Network
Every change to state is written to the changelog once and read once by each standby. During restoration, an instance reads a changelog end to end. A mass restoration, such as many instances restarting with empty disks, can saturate network links and broker capacity. Plan headroom for the worst restoration case, not only for steady state.
Disk per instance
Sum of stores it holds, active and standby, plus margin for maintenance and migration.
Memory per instance
Cache and buffers per store times number of stores, plus the application’s own needs.
Network in steady state
Input reading, output writing, changelog writing, and standby changelog reading.
Network during restoration
Bursts of very heavy reading from changelog partitions, limited by the number of concurrent restores.
Planning storage for a company archive means counting the originals, the backup copies, the room to reorganize shelves, and the extra space needed when a whole department moves offices at once. Counting only the originals would leave the archive overflowing.
| Question | How to estimate |
|---|---|
| How big is one task’s store? | Measure it in a realistic test, after the store has warmed to steady size |
| Total application state? | Task store size times number of stateful tasks |
| Total including copies? | Multiply by one plus standby count |
| Per instance disk? | Total including copies divided by instances, plus at least a comfortable safety margin |
| Worst-case restore time? | Largest store size divided by realistic restore throughput, tested not guessed |
Task stores are rarely equal in size, because some keys are far more popular than others. Plan around the largest tasks, and watch for a single hot task that dominates an instance’s disk or restore time.
24Key Settings Explained in Words
You do not need every setting memorized, but you should know what each family controls.
Application shape
Application identifier
Names the application, its consumer group, its state directory subfolder and its internal topics. Changing it creates a brand-new application with no history.
Number of stream threads
How many worker threads each instance runs. More threads use more of a large machine but share its disk and memory.
State directory
Where local stores are kept on disk. It should live on fast, reliable storage, and on persistent storage if restarts should reuse it.
Replication factor of internal topics
How many broker copies changelog and repartition topics get. Should be at least three in production.
Assignment and standby
| Family | What it controls | Guidance |
|---|---|---|
| Standby replica count | Permanent shadow copies per stateful task | Start with one for stateful production applications, tune from measurements |
| Acceptable recovery lag | How current a copy must be to take over | Keep near the default unless promotions cause noticeable pauses |
| Maximum warm-up replicas | How many background restores run at once | Raise for faster scale-out, lower to protect brokers |
| Probing rebalance interval | How often readiness is re-checked | Default suits most cases |
| Task assignor choice | Which algorithm plans the assignment | Use the default modern assignor unless you have a specific need |
| Rack awareness strategy | Whether and how location is used | Enable in multi-zone deployments after testing |
Group membership
Session timeout
How long a member may be silent before being declared dead. Shorter finds failures faster but risks false alarms.
Heartbeat interval
How often members prove they are alive, kept well below the session timeout.
Maximum poll interval
How long a thread may go without polling before it is considered stuck and removed. Long processing per batch needs a larger value.
Static membership identifier
A permanent name for an instance, so short restarts do not trigger rebalances.
Group and assignment settings interact. Changing several together makes it impossible to tell which one helped or hurt. Change one, observe through a full business cycle, and record the result.
Default values and available options change between library releases. Always check the documentation for the exact version you run before relying on remembered numbers.
25Custom Assignors and Extension Points
The default assignment logic suits most applications, but the library offers ways to adapt it.
Choosing among built-in assignors
The library has shipped several assignment algorithms over the years. An older sticky approach focuses on keeping tasks in place. The high-availability approach adds warm-up replicas and lag awareness. Recent versions let you choose the assignor by configuration, and a fallback option exists for older behavior. For nearly all users, the modern default is the right choice.
Custom assignors
Recent releases have opened an extension point that lets you plug in your own assignor logic. It receives descriptions of the instances, tasks and their state lag, and returns a plan. This is meant for rare, specialized needs, such as placing certain tasks on instances with special hardware, or honoring business rules about data locality.
Hardware-aware placement
An application where some tasks use expensive hardware, such as fast disks, might want those tasks placed only on instances that have it.
Tenant isolation
A multi-tenant application might keep certain tenants’ tasks on dedicated instances for compliance or performance isolation.
Cost-based balancing
When tasks differ greatly in cost, a custom assignor could weigh them by measured cost instead of simply counting them.
A hotel’s default room allocation works for nearly everyone. Occasionally a conference organizer needs all their guests on one floor with a shared lounge. The hotel allows a special arrangement for such cases, but it is rarely used, and it requires extra care.
Writing your own assignor means you own all the subtle rules: fairness, stickiness, standby separation and safe migration. Bugs here cause outages. Use custom assignors only when the default truly cannot meet a need, and test heavily.
26Deployment Patterns: Containers, Volumes and Standbys
How you deploy the application decides how much you need standbys, and how well they work.
Ephemeral disks
In many container deployments, an instance’s disk vanishes when the container is replaced. Every restart is then a cold start that needs a full restore from the changelog. For applications with meaningful state, this makes standbys much more valuable, because a standby lives on a different instance and survives the replacement.
Persistent volumes
Alternatively, each instance can be given a persistent volume that follows it across restarts. A restarted instance finds its old state on disk and only needs a short catch-up. Combined with static membership, this makes rolling restarts smooth even with no standbys. Persistent volumes protect against restarts but not against loss of the volume or the machine.
| Deployment style | Restart behavior | Machine loss behavior | Recommendation |
|---|---|---|---|
| Ephemeral disks, no standby | Full restore each time | Full restore | Avoid for large state |
| Ephemeral disks, with standby | Fast, standby holder takes over | Fast | Good default for stateful applications |
| Persistent volumes, no standby | Fast, state reused | Full restore if the volume is lost | Fine when machine loss is rare and pauses are tolerable |
| Persistent volumes with standby and static membership | Very fast, few rebalances | Fast | Best protection, highest cost |
A traveler who carries their own notebook can resume work after a brief stop. If the notebook may be lost, the traveler should also keep a copy with a friend. Doing both gives the best protection, but it takes the most effort.
Stateful sets and stable identities
Orchestrators that give each instance a stable name and its own volume make static membership and disk reuse natural.
Rolling updates that respect readiness
Update one instance at a time and wait for it to finish catching up before the next. This prevents waves of simultaneous restorations.
Graceful shutdown
Give the application time to close cleanly on termination so it can hand over tasks and write checkpoints, making the next start faster.
Stores keep small checkpoint files recording how far they have read the changelog. A clean shutdown writes them, allowing the next start to resume nearby rather than replaying too much. Abrupt kills may force a longer catch-up.
27Security Considerations
State copies, internal topics and group membership all carry sensitive information that deserves protection.
State on disk
Local stores contain real business data. Protect disks with encryption and access controls, including disks holding standby copies.
Changelog topics
They contain every update to state. Anyone able to read them can reconstruct the stores. Apply the same access rules as to the original data.
Internal topic permissions
The application needs permission to create and use its internal topics, under names derived from its identifier. Grant exactly that, and no more.
Group membership
An unauthorized process that joins the group could receive tasks and read data. Protect the group with authentication and authorization.
Query endpoints
Services exposing interactive queries reveal state to callers. Authenticate and authorize them like any other data service.
Inter-instance traffic
Instances may call each other for queries. Secure these calls with encryption and authentication.
A company that keeps sensitive files must lock the filing cabinet, the backup copies stored elsewhere, and the courier van that carries them. Protecting only the main cabinet leaves the copies as easy targets.
Treat standby disks as production data
Every extra copy of state is another place where data could leak. Apply the same encryption and disposal rules to every instance.
Clean up decommissioned instances
When an instance is retired, its state directory still holds data. Wipe it securely as part of decommissioning.
Scope permissions by application
Use predictable prefixes for internal topics and group names so access rules can grant each application rights only over its own.
28Monitoring, Logging and Metrics
Healthy assignment and standby behavior is quiet. Good monitoring lets you notice trouble early.
How many rebalances are happening?
Rebalance counts and rates should be low. Bursts are expected during deployments, but constant rebalancing signals trouble.
How long do rebalances take?
Rebalance duration reveals whether handovers are smooth or slow.
How far behind are standbys?
Per-task standby lag shows whether warm copies are truly warm.
Are restores in progress?
Restoration activity and its speed show whether tasks are stuck restoring after a move.
Is work evenly spread?
Compare task counts and processing rates across threads and instances to spot imbalance.
Is end-to-end lag under control?
Consumer lag on the input topics shows whether the application is keeping up with its workload.
| Signal | Where to see it | Healthy sign | Warning sign |
|---|---|---|---|
| Rebalance rate | Client metrics and group tooling | Rare, clustered around planned events | Frequent, unrelated to deployments |
| Standby lag per task | Client metrics or state restore listeners | Small and stable | Growing over time |
| Restore progress | Restore listener callbacks and logs | Completes in expected time | Stalls or takes far longer than tested |
| Tasks per instance | Client metadata and thread metrics | Roughly equal | Some instances carry many more |
| Input consumer lag | Group tooling and broker metrics | Flat or drains after spikes | Rises steadily |
| Disk usage of state directory | Host monitoring | Stable with margin | Near full or growing without bound |
The library lets you register a listener that is told when restoration starts, progresses and ends for each store. Publishing these events to your monitoring system gives excellent visibility into slow or stuck restores.
Logs worth reading
Application logs record assignment decisions, restoration starts and finishes, task creations and closures, and probing rebalances. During an incident, collect the logs of every instance and line them up by time. The story of a rebalance is spread across all members, and only the combined picture shows why a task moved or stalled.
Alert on: rebalance rate above baseline for more than a short period, standby lag growing steadily, restores taking much longer than tested, uneven task distribution, and disk usage on state directories approaching capacity.
29Inspecting Assignment With Built-in Tools
You can look at what the application decided rather than guess.
Consumer group tool
Shows the members of the application’s group, which input partitions each reads and the lag on each.
Application metadata API
The library can report which instance holds each store as active or standby, useful for building status pages.
Topology description
Prints the sub-topologies, sources, sinks and state stores, so you can count tasks in advance.
Topic description tool
Confirms partition counts and replication settings of input, repartition and changelog topics.
Practical uses
Predict your task count
Print the topology description and multiply each sub-topology by its input partition count. This tells you the parallelism ceiling before you deploy.
Find out who holds what
Ask the metadata API which instance holds each store as active and standby, and compare with your expectations after a scale change.
Confirm internal topics are healthy
Describe the changelog topics and verify replication, partition counts and compaction settings match your design.
Changelog and repartition topics are managed by the library. Deleting or altering them can destroy state or corrupt the application’s view of the world. Use the application’s supported reset tooling instead.
30Advantages and Trade-offs
Every recovery feature buys resilience at a price. A clear view of both sides guides good decisions.
Advantages
- Failover in seconds instead of a full restore that can take hours
- Scale-out without stalling moved tasks, thanks to warm-up replicas
- Automatic, self-healing assignment with no manual placement work
- Standby copies can serve slightly stale reads during disruptions
- Zone-aware placement survives the loss of a whole zone
- Built into the library, with no extra system to operate
Disadvantages / Trade-offs
- Disk use multiplies with each standby copy
- Extra read traffic on brokers for every standby
- Warm-up migration makes scale-out gradual rather than instant
- Several interacting settings that need careful tuning
- Probing rebalances can look like instability to newcomers
- Standbys need at least as many instances as copies requested
Choosing a protection level
| Situation | Recommended approach | Reason |
|---|---|---|
| Stateless processing | No standbys needed | Nothing to restore |
| Small state that restores in seconds | No standbys, rely on fast restore | Insurance would cost more than it saves |
| Medium state, moderate pause tolerance | One standby | Cuts recovery to a short catch-up at modest cost |
| Large state, strict availability targets | One or two standbys plus zone spread plus static membership | Covers failures, restarts and zone loss |
| Interactive queries on state | At least one standby, allow stale reads | Keeps the query service available during moves |
31Design Patterns and Best Practices
These habits keep Streams applications calm and predictable through failures and scaling.
Measure restore time first
Before deciding on standbys, time a cold restore of your largest store. The number often makes the decision obvious.
Start with one standby for stateful production apps
One standby removes most of the pain of a single failure. Add more only where measurements demand it.
Run more instances than copies
Keep the instance count comfortably above the number of copies so standbys can be placed apart and load can be balanced.
Plan partition counts early
Choose input partition counts with enough headroom for future parallelism, because changing them later is disruptive.
Use static membership for rolling restarts
Give each instance a stable identity and persistent state so routine deployments cause few or no rebalances.
Spread across zones
Enable location-aware assignment in multi-zone environments so copies of a task never share a failure domain.
Scale one step at a time
Add or remove one instance and wait for rebalancing and warm-up to settle before making the next change.
Practise failures deliberately
Kill instances, wipe disks and remove zones in a test environment, and measure the actual pause your users would see.
A checklist before going live
Count tasks and check parallelism
Print the topology, compute the task count, and confirm it exceeds the total thread count you plan to run.
Confirm internal topic settings
Verify replication factors and compaction on changelog topics.
Confirm capacity
Check disk, memory and network for active tasks, standby copies and the worst-case restore.
Confirm monitoring
Ensure dashboards and alerts exist for rebalances, standby lag, restores and disk usage.
Rehearse failure and scaling
Run a crash test and a scale-out test, and record the observed pause and recovery times.
Record your task count, standby settings, expected restore time and the last measured failover time in a short runbook. During an incident, these numbers turn guesswork into clear decisions.
32Anti-patterns to Avoid
Each of these looks harmless until a failure or scaling event makes it expensive.
Problem
Running a stateful application on ephemeral disks with no standby copies.
Why It’s Harmful
Every restart or replacement becomes a full restore from the changelog. Routine deployments cause long pauses, and any machine loss stalls its tasks for as long as restoration takes.
Correct Approach
Keep at least one standby, or use persistent volumes with stable identities, or both.
Problem
Asking for more standbys than there are instances to hold them.
Why It’s Harmful
Copies cannot share an instance with each other or with the active task, so the extra requested copies are never created. The team believes it has more protection than it really does.
Correct Approach
Ensure the number of instances exceeds the number of copies, and verify the actual placement using the metadata tools.
Problem
Adding threads beyond the number of tasks.
Why It’s Harmful
Tasks are the ceiling of parallelism. Extra threads sit idle, consuming memory for no benefit, and give a false sense of capacity.
Correct Approach
Compute the task count first, and size threads and instances to fit within it. Increase input partitions early if more parallelism is needed.
Problem
Changing the number of input partitions after a stateful application is running.
Why It’s Harmful
Keys map to different partitions after the change, so existing state no longer lines up with incoming data. Results become wrong, and the application may need a full reset.
Correct Approach
Plan partition counts up front. If a change is unavoidable, migrate to a new application with a controlled reprocessing.
Problem
Restarting many instances at once during a deployment.
Why It’s Harmful
Mass departures trigger a storm of rebalances and simultaneous restorations, hammering brokers and stalling the whole application at the same time.
Correct Approach
Roll one instance at a time, wait for it to be caught up, and use static membership to avoid unnecessary task movement.
Problem
Setting a very long session timeout to avoid rebalances, without standbys.
Why It’s Harmful
A genuine failure takes a long time to notice, and once noticed, recovery still needs a full restore. The application is silent and stale for a long period.
Correct Approach
Use a moderate timeout, add standbys for fast takeover, and rely on static membership for planned restarts.
Problem
Deleting the local state directory or internal topics to “fix” a problem.
Why It’s Harmful
State is lost or made inconsistent with the changelog, forcing long restores or producing wrong results if topics and stores disagree.
Correct Approach
Use the supported application reset procedure, and investigate the underlying cause instead of removing evidence.
33Common Myths
A few persistent misunderstandings cause a surprising number of production problems.
Myth: Standby replicas process data too
They do not. A standby only copies state from the changelog. It reads no input topic, runs no logic and writes no output.
Myth: Standbys make failover instant
They shorten only the state recovery step. Failure detection and the rebalance still take time, and a short catch-up remains.
Myth: More threads means more fault tolerance
Threads share a machine. Fault tolerance comes from more instances and from standby copies on different instances.
Myth: Standbys are backups of the data in Kafka
The durable copy of state is the changelog topic in Kafka. Standbys are about speed of recovery, not about durability.
Myth: Adding an instance immediately reduces load on the others
With warm-up replicas, tasks move only after their state is ready, so relief arrives gradually, sometimes after several probing rebalances.
Myth: A rebalance always pauses the whole application
With cooperative rebalancing, only the tasks that change owners pause. Everything else keeps running.
Myth: The broker decides where tasks run
The group leader inside your application computes the task plan. Brokers only coordinate group membership and store topics.
34Real-World and Industry Perspectives
Standby replicas and careful assignment appear wherever stateful streaming meets strict availability.
Fraud and risk scoring
Pipelines keep per-customer aggregates in state. A pause during failover means delayed decisions, so operators keep standbys so recovery is a short catch-up rather than a long rebuild.
Real-time personalization
Services that maintain per-user profiles from event streams use standbys and interactive queries so both processing and profile lookups survive machine loss.
Inventory and order tracking
Stateful joins between orders and stock events must stay current. Warm-up replicas allow such applications to scale during peak seasons without stalling.
Telemetry and monitoring aggregation
Windowed aggregates over large device fleets create big stores. Zone-aware standbys protect against zone outages that would otherwise force large restores.
Financial reconciliation
Applications matching payments with ledger entries hold large state and cannot tolerate long pauses at cut-off times, so they invest in copies and rehearsed failovers.
Container platforms
On orchestrators where instances are replaced often, standbys and stable identities are the standard way to keep rolling updates from turning into restore storms.
35Frequently Asked Questions
A task is the smallest unit of work. It is created for each input partition of each independent part of the topology, and it processes that partition’s records and owns its own local state.
Add up, over all sub-topologies, the number of partitions each one reads. Printing the topology description makes this easy to count before you deploy.
An instance is one running copy of the application, usually one process. A thread is a worker inside an instance. Tasks are assigned to instances and then to threads.
A copy of a task’s state store kept up to date on a different instance by reading the changelog, ready to take over if the active task’s instance fails.
They consume some disk, network and processor time for copying, but they do not process input. The effect on capacity depends on how heavily your application updates state.
Yes. Without a setting, no standby copies are kept, and every task move requires restoring state unless the local disk still has it.
No. The assignor always places standbys on different instances, since a shared machine would defeat the purpose.
A temporary standby created on an instance that will soon take over an active task. It restores in the background, and the task moves only after the copy has caught up enough.
The library runs probing rebalances to check the progress of warm-up copies and to move tasks in stages. They should stop once the migration completes.
A threshold on how many changelog records a copy may still be missing while still being considered ready to become active.
An instance that restarts quickly with the same permanent identifier gets its old tasks back without triggering a rebalance, keeping its local state useful.
Persistent volumes help with restarts, but not with loss of the volume or machine. Standbys protect against those. Many teams use both for large-state applications.
Yes, if you allow stale reads. Results may lag behind the active copy, so this suits use cases where availability matters more than perfect freshness.
Doing so with a stateful application breaks the mapping between keys and state. Plan partition counts in advance and treat later changes as a migration.
No. They have no local state to restore, so they can be moved anywhere at no cost.
In the changelog topic in Kafka, which is replicated by the brokers. Local stores and standbys are speed optimizations built on top of it.
Compare the time spent detecting the failure, the time spent rebalancing and the time spent restoring state. Standbys only shrink the last of these, so the other two may need different fixes.
36Summary and Key Takeaways
A Kafka Streams application turns its topology into many small tasks, one for each input partition of each independent part, and hands them out across instances and threads. Stateful tasks keep local stores backed by changelog topics, and moving such a task to a machine without its state forces a slow restoration. Sticky assignment keeps tasks where their state already lives, standby replicas keep warm copies elsewhere so a failure costs only a short catch-up, and warm-up replicas prepare new instances in the background so scale-out does not stall. Cooperative rebalancing, static membership and zone-aware placement complete the picture. Understanding these pieces lets you choose protection levels sensibly, plan capacity honestly and operate stateful streaming with confidence.
Key Takeaways
- Tasks are the unit of assignment — one per input partition per sub-topology, capping total parallelism regardless of how many threads you run.
- State makes movement expensive — a task that moves to a machine without its store must replay the changelog, pausing that task for as long as the restore takes.
- Standbys shorten recovery — a shadow copy on a different instance turns a long restore into a small catch-up, at the cost of disk, network and broker reads.
- Warm-up replicas make scaling gentle — new instances build state in the background and receive tasks only when ready, using lag thresholds and probing rebalances.
- Reduce needless rebalances — cooperative rebalancing pauses only moving tasks, and static membership lets quick restarts keep their tasks and disks.
- Place copies apart — standbys always live on different instances, and location-aware assignment spreads them across zones.
- Measure and rehearse — time your restores, count your tasks, monitor standby lag and rebalances, and practise failures and scaling before production.