---
title: "Kafka static membership: group.instance.id avoids rebalances"
description: "Two groups lose a member at once. The static member rejoins within session.timeout.ms and keeps its partition; the dynamic one is evicted and Kafka rebalances."
url: https://monedula.dev/kafka-simulator/scenarios/static-membership/
---

# Kafka static membership: group.instance.id avoids rebalances

Scenario 02.3.3 · Static membership: avoid rebalance. Consumer groups · Intermediate · about 4 min · Apache Kafka 4.3.

A dynamic member that stays down past session.timeout.ms is evicted and its partition rebalances onto a survivor; a STATIC member (group.instance.id) that rejoins within session.timeout.ms keeps its partition and resumes in place with no rebalance.

Run it: https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3

## What you start with

A dynamic member that drops out and stays gone past session.timeout.ms is evicted and its partitions rebalance to a survivor. With static membership (group.instance.id), a member that rejoins within session.timeout.ms keeps its partitions and resumes in place. This scenario crashes one member in each group and contrasts the two reactions.

## Step by step

1. **two groups, two members each** (t+0.000s): Both cg-dyn and cg-stat read the same 2-partition topic with a cooperative-sticky member per partition: member 1 → p0, member 2 → p1. In cg-stat, s2 is STATIC - it carries a group.instance.id (KIP-345); every other member is dynamic. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=0)
2. **warm-up consumed (lag 0)** (t+0.600s): One record per partition has been produced and every member has drained its partition, so both groups sit at lag 0. Nothing distinguishes the static member yet - group.instance.id only matters when a member leaves. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=1)
3. **both p1 owners crash** (t+1.000s): d2 (dynamic) and s2 (static) crash at the same instant. d2 schedules a member_eviction at now + session.timeout.ms (t=3000): if it has not rejoined by then it is removed. s2 is static - the coordinator holds its slot open across the outage, so no rebalance occurs as long as it returns before t=3000. Both keep owning p1, which now stalls. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=2)
4. **session window: p1 stalled in both** (t+2.500s): Midway through the session window. In BOTH groups the crashed member still owns p1 and its backlog grows (the producer kept writing). p0 keeps draining (d1/s1 are alive). Neither member has been removed yet - the divergence depends on who rejoins in time. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=3)
5. **static member rejoins in time** (t+2.900s): s2 restarts with the SAME instance.id at t=2800 - within session.timeout.ms of its crash (1800 ms < 2000 ms here; timings are compressed, real brokers require at least 6 s) - so the coordinator’s held slot lets it resume p1 in place with NO rebalance (s1 still owns only p0). d2 is still absent, its eviction one tick away. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=4)
6. **dynamic member evicted + rebalances** (t+3.200s): d2 never returned, so at t=3000 its session.timeout.ms expires: cg-dyn drops d2 to an evicted ghost and REBALANCES p1 onto the survivor d1. cg-stat already absorbed s2’s restart as a no-op. Same crash, opposite reaction - a static member that rejoined within the timeout kept its partition, while the member that stayed gone past it was reshuffled. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=5)
7. **outcome: rebalance vs retained** (t+4.500s): Final state. cg-dyn: d1 owns [p0,p1] after the rebalance, d2 lingers as an evicted ghost. cg-stat: the assignment never moved - s1 → p0, s2 → p1 - and there is no ghost. Static membership turned a crash-and-restart-within-session.timeout.ms into a no-op for the group. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=02.3.3&t=6)

## The takeaway

Static membership trades fast failure detection for rebalance avoidance: a member can restart or briefly disconnect within session.timeout.ms and resume its exact assignment with no rebalance at all.

## Configs in this scenario

- [`session.timeout.ms`](https://kafka.apache.org/43/configuration/consumer-configs/#consumerconfigs_session.timeout.ms): How long the group coordinator waits for a heartbeat from a classic-protocol consumer before it removes the member and rebalances (default 45000, 45 seconds); with group.protocol=consumer the broker group.consumer.session.timeout.ms applies instead. [How session.timeout.ms works](https://monedula.dev/kafka-simulator/configs/session-timeout-ms/)
- [`group.instance.id`](https://kafka.apache.org/43/configuration/consumer-configs/#consumerconfigs_group.instance.id): Makes the consumer a static member: after a restart within the session timeout it gets its partitions back without a rebalance, and only one member with this id can be in the group at a time.

## Further reading

- [KIP-345 on the Apache Kafka wiki](https://cwiki.apache.org/confluence/display/KAFKA/KIP-345%3A+Introduce+static+membership+protocol+to+reduce+consumer+rebalances)

## Troubleshooting

- [Kafka consumer group keeps rebalancing: causes and fixes](https://monedula.dev/kafka-simulator/troubleshooting/consumer-group-keeps-rebalancing/)
