DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
...
This page is meant as a template for writing a KIP. To create a KIP choose Tools->Copy on this page and modify with your content and replace the heading with the next KIP number and a description of your issue. Replace anything in italics with your own description.
Status
Current state: [One of "Under Discussion", "Accepted", "Rejected"]Under discussion
Discussion thread: here [Change the link from the KIP proposal email archive to your own email thread]
...
Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).
Motivation
Describe the problems you are trying to solve.
Public Interfaces
Briefly list any new interfaces that will be introduced as part of this proposal or any existing interfaces that will be removed or changed. The purpose of this section is to concisely call out the public contract that will come along with this feature.
A public interface is any change to the following:
Binary log format
The network protocol and api behavior
Any class in the public packages under clientsConfiguration, especially client configuration
org/apache/kafka/common/serialization
org/apache/kafka/common
org/apache/kafka/common/errors
org/apache/kafka/clients/producer
org/apache/kafka/clients/consumer (eventually, once stable)
Monitoring
Command line tools and arguments
- Anything else that will likely break existing users in some way when they upgrade
Proposed Changes
Describe the new thing you want to do in appropriate detail. This may be fairly extensive and have large subsections of its own. Or it may be a few sentences. Use judgement based on the scope of the change.
Compatibility, Deprecation, and Migration Plan
- What impact (if any) will there be on existing users?
- If we are changing behavior how will we phase out the older behavior?
- If we need special migration tools, describe them here.
- When will we remove the existing behavior?
Test Plan
Describe in few sentences how the KIP will be tested. We are mostly interested in system tests (since unit-tests are specific to implementation details). How will we know that the implementation works as expected? How will we know nothing broke?
Rejected Alternatives
...
Summary
Today, kafka-reassign-partitions.sh --execute submits all partition reassignments from the JSON in oneAdminClient#alterPartitionReassignments call (unless the user manually splits work). For large clusters this can create large bursts of replication traffic and controller work.
This KIP proposes tool-only pacing controls:
- --reassignment-batch-size — caps how many topic partitions are submitted per step (semantics differ slightly depending on mode; see below). 0 preserves legacy behavior (single request for the entire plan).
- --incremental — optional mode used with--reassignment-batch-size > 0 to keep at most N partition reassignments in flight for this execution, submitting the next partition from a deterministic queue when a slot frees up.
Ordering for both modes is (topic name, partition index), not the order of entries in the JSON file.
No broker protocol, controller, or metadata changes are required; pacing is implemented entirely in the reassignment tool using existing Admin APIs (alterPartitionReassignments, listPartitionReassignments, metadata reads).
Motivation
Problem
- Operational risk: Submitting hundreds or thousands of partition reassignments in one RPC can stress replication links, disk, and the controller in ways that are hard to predict during maintenance windows.
- Limited operator control: Throttling (--throttle) limits bandwidth but does not limit how many partitions are simultaneously moving; operators often want serialised waves or bounded concurrency without hand-splitting JSON files.
- Manual workarounds: Teams split reassignment JSON by hand or wrap the tool in scripts that call alterPartitionReassignments in chunks — error-prone and inconsistent across deployments.
Goals
- Provide first-class, documented pacing in the supported reassignment tool.
- Preserve full backward compatibility when defaults are unchanged (--reassignment-batch-size 0, no --incremental).
- Keep behavior deterministic and explainable (stable partition ordering).
Non-goals
- Replacing cluster-wide replication quotas or broker-side limits.
- Changing how the controller executes reassignments (same server-side semantics).
- Global coordination across multiple concurrent tool processes (each execute remains independent).
Public interfaces
CLI (kafka-reassign-partitions.sh)
Option | Applies to | Semantics |
--reassignment-batch-size <int> | --execute only | Default 0: legacy — entire plan in onealterPartitionReassignments request; no extra waits in the tool.> 0 without --incremental: split the plan into contiguous batches of at most Npartitions (sorted by topic, then partition id). After each batch except the last, the tool blocks until every partition in that batch reports complete (current ISR matches target and reassignment not active) before submitting the next batch.> 0 with --incremental:N is the maximum number of partition reassignments from this JSON that may be active at once; when one completes, the tool submits the next partition from the sorted queue. |
--incremental | --execute only | Requires--reassignment-batch-size > 0. Mutually exclusive interpretation of batch size as in-flight cap (see above). |
Validation and compatibility
- --reassignment-batch-size must be ≥ 0. Negative values are rejected.
- --incremental without --reassignment-batch-size > 0 is rejected at argument validation time.
- --reassignment-batch-size and --incremental are not permitted with --list, --generate, --verify, or --cancel (same pattern as other execute-only options).
Programmatic API
ReassignPartitionsCommand.executeAssignment gains parameters:
- int reassignmentBatchSize
- boolean incremental
Existing callers that omit pacing pass 0 and false to preserve legacy behaviour.
Detailed design
Partition counting
One row in the JSON (one TopicPartition) = one partition reassignment for pacing purposes, regardless of how many brokers join or leave the replica set in that single move.
Batch construction (non-incremental, reassignmentBatchSize > 0)
- Build the map of TopicPartition → target replicas from the JSON.
- Split into batches: sort keys with compareTopicPartitions, then chunk in groups of N partitions.
- For each batch except the last:
alterPartitionReassignments(batch) → wait until all partitions in that batch are complete → next batch. - For the last batch:
alterPartitionReassignments only — the tool does not wait for completion before printing success (same family as legacy “started” messaging). Operators should run --verify for full completion.
Incremental mode (--incremental)
- Sort partitions deterministically (compareTopicPartitions).
- Maintain a pending deque and an in-flight map (submissions for this execute only).
- Loop until pending is empty: remove completed partitions from in-flight (using the same completion predicate as non-incremental wait paths), then submit new partitions up to the N in-flight cap.
- Poll interval between iterations when work remains: INCREMENTAL_REASSIGNMENT_POLL_INTERVAL_MS (500 ms in the default implementation).
Semantics: The tool returns after all partitions in this JSON have been successfully submitted to alterPartitionReassignments, not necessarily after all replication has finished (consistent with legacy execute for “completion” of submission).
Non-incremental wait between batches
- Poll interval: BATCH_REASSIGNMENT_POLL_INTERVAL_MS (500 ms in the reference implementation).
- Completion uses existing findPartitionReassignmentStates / PartitionReassignmentState logic; inconsistent terminal states produce TerseException (same class of errors as today’s verify path).
Interaction with --additional
--additional only bypasses the “existing reassignment on cluster” guard. It does not merge pacing across concurrent executes: --reassignment-batch-size applies per process invocation to that JSON. Multiple overlapping executes can each contribute up to N in-flight partition reassignments from their respective plans.
Interaction with throttles
Existing --throttle / --replica-alter-log-dirs-throttle behaviour is unchanged; pacing is orthogonal and can be combined.
Compatibility
- Default CLI: unchanged legacy path (reassignment-batch-size defaults to 0; incremental absent).
- Brokers / ZK / KRaft: no change.
- Wire protocol: unchanged (same Admin APIs).
Limitations and future work
- No timeout on batch-completion waits in the reference implementation; stuck reassignments can poll indefinitely until operator intervention (same class of risk as long-running admin operations without deadlines).
- Incremental + --additional: total cluster in-flight work can exceed N when multiple tool processes run overlapping plans; documentation / optional warnings are recommended.
Rejected alternatives
- Only documentation: “Split your JSON manually” — does not scale and yields inconsistent operations.
- New broker-side “max concurrent reassignments” quota: much larger scope; tool-side pacing addresses the common case without protocol work.
- Order = JSON file order only: rejected in favour of deterministic sorted order so behaviour is reproducible and independent of file editing.
Test plan
- Unit tests: batch splitting; incremental ordering; failure on second batch; completion predicate shared between wait and incremental removal.
- Args tests: invalid combinations; execute-only restriction for new flags.
- Integration / cluster tests: execute with small batch sizes (including batch size 1) in KRaft and ZK modes where the project already runs ClusterTest.
- Manual: large plan with --reassignment-batch-size and --list / --verify to observe waves and completion.
Documentation
- Extend the kafka-reassign-partitions section of the Kafka documentation / ops guides: semantics of 0, non-incremental batching, incremental, --additional, and verification with --verify.