Skip to main content

MSK KRaft Migration CLI Reference

All migration commands use the subcommand structure:

kafka-backup migrate msk-kraft <SUBCOMMAND> [OPTIONS]

plan

Generate a migration plan without making any changes. No license required.

kafka-backup migrate msk-kraft plan \
--config <PATH> \
[--format <FORMAT>] \
[--out-dir <PATH>] \
[--migration-id <ID>] \
[--force]
FlagTypeRequiredDefaultDescription
--configPATHYesPath to migration config YAML
--formatenumNojsonOutput format: json, runbook, aws-cli, iam-policy, cost, all
--out-dirPATHNoDirectory for output artifacts. Required when --format all.
--migration-idstringNoauto-generatedPin the migration ID for deterministic output
--forceflagNofalseOverwrite existing files in --out-dir

Output artifacts (--format all)

FileDescription
plan.jsonMachine-readable migration plan
runbook.mdStep-by-step operator runbook
aws-cli.shAWS CLI commands for infrastructure setup
iam-policy-templated.jsonIAM policy template with placeholders
iam-policy-concrete.jsonIAM policy with your actual ARNs
cost-estimate.jsonEstimated S3 and data transfer costs

Example

kafka-backup migrate msk-kraft plan \
--config migration.yaml \
--format all \
--out-dir ./migration-plan

precheck

Read-only infrastructure and compatibility checks. No license required.

kafka-backup migrate msk-kraft precheck --config <PATH>
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML

Output

JSON-formatted report with findings categorized as Blocker, Warning, or Info. See Precheck Codes Reference for all codes.

Example output:

W04 warn: could not verify target message-size floor (target broker DescribeConfigs returned no message.max.bytes or replica.fetch.max.bytes (dynamic-config only on this broker)) — ensure target `message.max.bytes` and `replica.fetch.max.bytes` ≥ largest source topic's effective max.message.bytes
W03 info: KMS key ARN set on backup channel — CMK access is not verified by this precheck phase; ensure the caller has kms:Encrypt/Decrypt/GenerateDataKey
I01 info: target is IAM-auth — ACLs will be emitted as access-map.json for customer IaC to translate to IAM policies (tool does not apply IAM)

Exit codes

CodeMeaning
0All checks passed (warnings are OK)
1One or more blockers detected

execute

Run the migration from planned through drain_ready. Blocks until the data is caught up, then returns. License required.

kafka-backup migrate msk-kraft execute \
--config <PATH> \
[--migration-id <ID>] \
[--journal-dir <PATH>] \
[--force-restart]
FlagTypeRequiredDefaultDescription
--configPATHYesPath to migration config YAML
--migration-idstringNoauto-generatedResume a specific migration. If omitted, a new migration starts.
--journal-dirPATHNoLocal directory for the migration journal. If omitted, journal is stored in S3.
--force-restartflagNofalseAllow re-running seed after a partial run. Accepts risk of duplicate records on target.

State transitions

planned → precheck → topology_copy → seed → tail → drain_ready

Example journal excerpt:

2026-04-25T06:15:07.512121Z topology_copy -> seed
2026-04-25T06:25:30.777840Z seed -> tail
2026-04-25T06:26:19.079610Z tail -> drain_ready drain ready: max_partition_lag=0 records_replayed=0 bytes_replayed=0

Exit codes

CodeMeaning
0Migration reached drain_ready successfully
1Migration failed (check logs and journal)

Example

kafka-backup migrate msk-kraft execute \
--config migration.yaml \
--journal-dir ./journal

# With debug logging
RUST_LOG=debug kafka-backup migrate msk-kraft execute \
--config migration.yaml \
--journal-dir ./journal

resume

Resume an in-flight migration from its last journal entry. License required.

kafka-backup migrate msk-kraft resume \
--config <PATH> \
--migration-id <ID> \
[--journal-dir <PATH>]
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML
--migration-idstringYesID of the migration to resume
--journal-dirPATHNoDirectory where the journal is stored

Exit codes

CodeMeaning
0Migration advanced or reached a terminal state
1Resume failed
10Migration is waiting on operator action (check stderr for next_command)

status

Show current state and live lag for a migration. License required.

kafka-backup migrate msk-kraft status \
--config <PATH> \
--migration-id <ID> \
[--journal-dir <PATH>]
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML
--migration-idstringYesID of the migration to query
--journal-dirPATHNoDirectory where the journal is stored

Output

Prints migration state, per-partition lag, and operational notes.


cutover

Transition from drain_ready through producer freeze, sentinel publishing, offset translation, to awaiting_client_switch. License required.

kafka-backup migrate msk-kraft cutover \
--config <PATH> \
--migration-id <ID> \
[--journal-dir <PATH>]
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML
--migration-idstringYesID of the migration
--journal-dirPATHNoDirectory where the journal is stored

What happens during cutover

  1. Freezes producers (via webhook or TTY prompt)
  2. Publishes sentinel records to every partition on source
  3. Drains final records from source to target
  4. Snapshots all consumer group offsets from source
  5. Translates offsets using the offset map
  6. Commits translated offsets on target
  7. Verifies target log-start offsets have not advanced past the copied data
  8. Logs READY_FOR_CLIENT_SWITCH

Example output:

2026-04-25T06:40:46.854037Z cutover -> awaiting_client_switch READY_FOR_CLIENT_SWITCH: groups_translated=0 offsets_committed=0 warnings=0

Exit codes

CodeMeaning
0Cutover completed, ready for client switch
1Cutover failed (producers are automatically unfrozen on failure)

cutover-ack

Acknowledge that clients have switched to the target cluster. Transitions from awaiting_client_switch to validating. License required.

kafka-backup migrate msk-kraft cutover-ack \
--config <PATH> \
--migration-id <ID> \
[--journal-dir <PATH>]
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML
--migration-idstringYesID of the migration
--journal-dirPATHNoDirectory where the journal is stored

rollback

Abort the migration and mark it as rolled back. Only available before cutover completes. License required.

kafka-backup migrate msk-kraft rollback \
--config <PATH> \
--migration-id <ID> \
[--journal-dir <PATH>]
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML
--migration-idstringYesID of the migration
--journal-dirPATHNoDirectory where the journal is stored

Available from states

planned, precheck, topology_copy, seed, tail, drain_ready

Not available from states

cutover, awaiting_client_switch, validating, finalized

What rollback does

  • Unfreezes producers (if frozen)
  • Marks migration as rolled_back in the journal
  • Uploads rollback report to evidence bucket
  • Does not delete topics or data on the target (manual cleanup)

finalize

Run the 5-check validation suite and produce the signed evidence bundle. Transitions from validating to finalized when validation passes. If a previous validation attempt found a repairable issue, finalize can be retried from failed after the repair. License required.

kafka-backup migrate msk-kraft finalize \
--config <PATH> \
--migration-id <ID> \
[--journal-dir <PATH>]
FlagTypeRequiredDescription
--configPATHYesPath to migration config YAML
--migration-idstringYesID of the migration
--journal-dirPATHNoDirectory where the journal is stored

Validation checks

  1. Topic parity — partition counts match
  2. Counts & offsets — record counts within tolerance
  3. Spot-check records — sampled records byte-equal
  4. Sentinel presence — cutover markers landed
  5. Consumer group reconciliation — translated offsets committed

Exit codes

CodeMeaning
0Validation passed, evidence bundle uploaded
1Validation failed (review the validation report)

Example successful verification output:

partitions_checked=306
target_behind_or_missing=0
earliest_partitions_checked=306
earliest_mismatches=0
latest_partitions_checked=306
latest_mismatches=0

Common Flags

These flags appear across most subcommands:

FlagDescription
--config <PATH>Path to migration configuration YAML (always required)
--migration-id <ID>Migration identifier (auto-generated by execute, required by others)
--journal-dir <PATH>Local journal directory (if omitted, journal stored in S3)

Next Steps