Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

RPC

Component

ACL Operation

ACL Resource

Purpose

CreateMirrorControllerCreateClusterMirrorCreate a new cluster mirror
AddTopicsToMirrorControllerAlterClusterMirrorAdd topics to an existing mirror
RemoveTopicsFromMirrorControllerAlterClusterMirrorRemove topics from a mirror (failover)
PauseMirrorTopicsControllerAlterClusterMirrorPause replication for topics
ResumeMirrorTopicsControllerAlterClusterMirrorResume replication for topics
DeleteMirrorControllerAlterClusterMirrorDelete a cluster mirror
ListMirrorsBrokerDescribeClusterMirrorList configured mirrors
DescribeMirrorsBrokerDescribeClusterMirrorDescribe mirror state and lag
DescribeConfigsBrokerDescribeConfigsClusterMirrorDescribe mirror configuration
WriteMirrorStatesMCClusterActionClusterPersist partition state to coordinator
ReadMirrorStatesMCClusterActionClusterRead partition state from coordinator
LastMirroredOffsetsBrokerClusterActionClusterQuery last mirrored offset for truncation
FindCoordinatorBrokerClusterActionClusterLocate mirror coordinator for a partition
CreateTopicsMMMCreateTopicCreate topics with source topic ID
CreatePartitionsMMM

Scale partitions to match source
IncrementalAlterConfigsMMM

Modify mirror configuration
OffsetCommitMMM

Sync consumer group offsets
CreateAclsMMM

Sync ACLs from source
DeleteAclsMMM

Remove stale ACLs

...

Delete a mirror including its topics and configuration (the mirror must be empty or include only stopped partitions):

Code Block
languagebash
TODO$ bin/kafka-mirrors.sh --bootstrap-server :9094 --delete --mirror my-mirror
Deleted mirror my-mirror

Pause mirroring for a specific topic or set of topics (topics remain read-only):

...

Code Block
languagejava
/**
 * Create a new cluster mirror.
 *
 * @param mirrorName The name of the cluster mirror
 * @param configs Configuration for the cluster mirror, including bootstrap servers and security settings
 * @param options Options for the create mirror operation
 * @return The CreateMirrorResult
 */
CreateMirrorResult createMirror(String mirrorName, Map<String, String> configs, CreateMirrorOptions options);

/**
 * Add topics to an existing cluster mirror for cross-cluster replication.
 *
 * When topics are added to a mirror, they become read-only on the destination cluster and start
 * replicating data from the source cluster. This operation marks the specified topics with the
 * mirror name, preventing local writes and enabling the MirrorFetcherThread to begin replication.
 *
 * @param mirrorName The mirror name to add the topics to
 * @param topics Set of topic names to add to mirroring
 * @param options Options for the add topics to mirror operation
 * @return The AddTopicsToMirrorResult containing futures for each topic addition
 */
AddTopicsToMirrorResult addTopicsToMirror(String mirrorName, Set<String> topics, AddTopicsToMirrorOptions options);

/**
 * Remove topics from cluster mirror, making them writable on the destination cluster.
 *
 * This operation is typically used during failover scenarios when the destination cluster needs to
 * be promoted from passive (read-only mirror) to active (accepting writes). Removing topics from
 * the mirror clears the mirrorName field from partition metadata, which allows producers to write
 * to these partitions.
 *
 * @param mirrorName The mirror name to remove the topics from
 * @param topics Set of topic names to remove from mirroring
 * @param options Options for the remove topics from mirror operation
 * @return The RemoveTopicsFromMirrorResult containing futures for each topic removal
 */
RemoveTopicsFromMirrorResult removeTopicsFromMirror(String mirrorName, Set<String> topics, RemoveTopicsFromMirrorOptions options);

/**
 * Pause mirroring for the specified topics.
 *
 * Paused topics remain read-only on the destination cluster but stop fetching new data from the
 * source cluster. The mirror fetcher threads are removed for these partitions, preserving the
 * current replicated state. Mirroring can be resumed later with {@link #resumeMirrorTopics}.
 *
 * @param mirrorName The mirror name to pause the topics for
 * @param topics Set of topic names to pause mirroring for
 * @param options Options for the pause mirror topics operation
 * @return The PauseMirrorTopicsResult containing futures for each topic
 */
PauseMirrorTopicsResult pauseMirrorTopics(String mirrorName, Set<String> topics, PauseMirrorTopicsOptions options);

/**
 * Resume mirroring for previously paused topics.
 *
 * Resumed topics restart fetching data from the source cluster, picking up from where they
 * left off. New mirror fetcher threads are created and the partitions transition back to the
 * MIRRORING state.
 *
 * @param mirrorName The mirror name to resume the topics for
 * @param topics Set of topic names to resume mirroring for
 * @param options Options for the resume mirror topics operation
 * @return The ResumeMirrorTopicsResult containing futures for each topic
 */
ResumeMirrorTopicsResult resumeMirrorTopics(String mirrorName, Set<String> topics, ResumeMirrorTopicsOptions options);

/**
  * ListDelete thea cluster mirrorsmirror availableincluding inits the clusterconfiguration.
  *
  * @paramThe optionsmirror Themust optionsbe toempty use(no whentopics) listingor theall mirrors.
its *topics @returnmust Thehave ListMirrorsResult.
 */
ListMirrorsResult listMirrors(ListMirrorsOptions options);

/**
 * Describe cluster mirrors.
 *
 * This operation retrieves detailed information about cluster mirrors including:
 * - Topics being mirrored
 * - Partition-level lag information (source offset vs destination offset)
 * - Mirroring state for each partition (INITIALIZING, PREPARING, MIRRORING, etc.)
 *
 * @param mirrorNames The names of the mirrors to describebeen removed (in STOPPED
  * state). After deletion, all mirror metadata are tombstoned and failback is no longer possible.
  *
  * @param mirrorName The name of the cluster mirror to delete
  * @param options Options for the delete mirror operation
  * @return The DeleteMirrorResult
  */
DeleteMirrorResult deleteMirror(String mirrorName, DeleteMirrorOptions options);

/**
 * List the cluster mirrors available in the cluster.
 *
 * @param options The options to use when describinglisting the mirrors.
 * @return The DescribeMirrorsResultListMirrorsResult.
 */
DescribeMirrorsResultListMirrorsResult describeMirrors(Collection<String> mirrorNames, DescribeMirrorsOptions listMirrors(ListMirrorsOptions options);

Protocol Changes

This KIP extends CreateTopic API, but also introduces some new APIs and metadata records.

CreateTopic

The CreateTopic API is extended to add information required for mirror topic creation.

Code Block
// new added
{ "name": "MirrorInfo", "type": "MirrorInfo", "versions": "8+", "nullableVersions": "8+", "ignorable": true,
  "about": "Mirror information for creating a mirror topic from a source cluster.", "fields": [
    { "name": "TopicId", "type": "uuid", "versions": "8+",
    "about": "The topic ID from the source cluster." }
]}

The topic ID field ensures mirror topics retain the same topic ID as the source cluster topic. This allows fetch requests to pass validation on the source broker, and enables the system to verify that a topic being mirrored to a same-named topic in the destination cluster is indeed the same logical topic, not a name collision.

In normal topic creation, the MirrorInfo field will be null. When receiving the CreateTopic request, the controller will check the new field. If it is not set, the topic ID will be generated with random UUID as usual. Otherwise, the controller will do the following validation:

  1. This topic ID is not used by other topics in the current cluster
  2. The replicas for the partition assignment are all active and not in fenced or controlled shutdown. This is to make sure when a topic gets deleted and re-created with the same topic ID, the stale offline log dir won’t be treated as the active log dir after it becomes online (KAFKA-16234).

EntityType

A new entity type is added for the message generator to provide schema-level type validation for mirror name fields:

Code Block
public enum EntityType {
    // ... existing types ...
    @JsonProperty("mirrorName")
    MIRROR_NAME(FieldType.StringFieldType.INSTANCE); // New type
}

ResourceType

A new resource type is added to the ResourceType enum to enable per-mirror authorization:

Code Block
public enum ResourceType {
    // ... existing types ...
    /**
     * A cluster mirror.
     */
    CLUSTER_MIRROR((byte) 8); // New type

CreateMirror

Allows users to create a mirror and supply its configuration. When the broker receives the request, it validates that the mirror name is not already in use, contains only permitted characters, and does not end with the ".removed" suffix. Once validated, the request is forwarded to the controller, which persists the configuration in the metadata log.

...

/**
 * Describe cluster mirrors.
 *
 * This operation retrieves detailed information about cluster mirrors including:
 * - Topics being mirrored
 * - Partition-level lag information (source offset vs destination offset)
 * - Mirroring state for each partition (INITIALIZING, PREPARING, MIRRORING, etc.)
 *
 * @param mirrorNames The names of the mirrors to describe
 * @param options The options to use when describing mirrors
 * @return The DescribeMirrorsResult
 */
DescribeMirrorsResult describeMirrors(Collection<String> mirrorNames, DescribeMirrorsOptions options);

Protocol Changes

This KIP extends CreateTopic API, but also introduces some new APIs and metadata records.

CreateTopic

The CreateTopic API is extended to add information required for mirror topic creation.

Code Block
// new added
{ "name": "MirrorInfo", "type": "MirrorInfo", "versions": "8+", "nullableVersions": "8+", "ignorable": true,
  "about": "Mirror information for creating a mirror topic from a source cluster.", "fields": [
    { "name": "TopicId", "type": "uuid", "versions": "8+",
    "about": "The topic ID from the source cluster." }
]}

The topic ID field ensures mirror topics retain the same topic ID as the source cluster topic. This allows fetch requests to pass validation on the source broker, and enables the system to verify that a topic being mirrored to a same-named topic in the destination cluster is indeed the same logical topic, not a name collision.

In normal topic creation, the MirrorInfo field will be null. When receiving the CreateTopic request, the controller will check the new field. If it is not set, the topic ID will be generated with random UUID as usual. Otherwise, the controller will do the following validation:

  1. This topic ID is not used by other topics in the current cluster
  2. The replicas for the partition assignment are all active and not in fenced or controlled shutdown. This is to make sure when a topic gets deleted and re-created with the same topic ID, the stale offline log dir won’t be treated as the active log dir after it becomes online (KAFKA-16234).

EntityType

A new entity type is added for the message generator to provide schema-level type validation for mirror name fields:

Code Block
public enum EntityType {
    // ... existing types ...
    @JsonProperty("mirrorName")
    MIRROR_NAME(FieldType.StringFieldType.INSTANCE); // New type
}

ResourceType

A new resource type is added to the ResourceType enum to enable per-mirror authorization:

Code Block
public enum ResourceType {
    // ... existing types ...
    /**
     * A cluster mirror.
     */
    CLUSTER_MIRROR((byte) 8); // New type

CreateMirror

Allows users to create a mirror and supply its configuration. When the broker receives the request, it validates that the mirror name is not already in use, contains only permitted characters, and does not end with the ".removed" suffix. Once validated, the request is forwarded to the controller, which persists the configuration in the metadata log.

CreateMirrorRequest

Code Block
{
  "apiKey": TBD,
  "type": "request",
  "listeners": ["broker", "controller"],
  "name": "CreateMirrorRequest",
  "latestVersionUnstable": true,
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorName", "type": "string", "versions": "0+", "entityType": "mirrorName",
      "about": "The cluster mirror name."},
    { "name": "Config", "type": "[]MirrorConfig", "versions": "0+",
      "about": "The cluster mirror configurations.",  "fields": [
      { "name": "Name", "type": "string", "versions": "0+", "mapKey": true,
        "about": "The configuration key name." },
      { "name": "Value", "type": "string", "versions": "0+", "nullableVersions": "0+",
        "about": "The value to set for the configuration key."}
    ]}
  ]
}

CreateMirrorResponse

Code Block
{
  "apiKey": TBD,
  "type": "request",
  "listeners": ["broker", "controller"]response",
  "name": "CreateMirrorRequestCreateMirrorResponse",
  "latestVersionUnstable": true,
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorNameThrottleTimeMs", "type": "stringint32", "versions": "0+", "entityType": "mirrorName",
      "about": "The clusterduration in mirror name."},
    { "name": "Config", "type": "[]MirrorConfig", "versions": "0+",
      "about": "The cluster mirror configurations.",  "fields": [
      milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "NameErrorCode", "type": "stringint16", "versions": "0+", "mapKey": true,
        "about": "The configuration key name error code, or 0 if there was no error." },
      { "name": "ValueErrorMessage", "type": "string", "versions": "0+", "nullableVersions": "0+",
        "about": "The error message, valueor tonull setif forthere thewas configurationno keyerror."}
    ]}
  ]
}

...

AddTopicsToMirror

Adds topics to a specified mirror. The broker validates that all target topic partitions are in either UNKNOWN or STOPPED state; otherwise, the request is rejected with an INVALID_REQUEST error. Once validated, the request is forwarded to the controller, which sets the mirror.name topic config to the specified mirror name.

AddTopicsToMirrorRequest

Code Block
{
  "apiKey": TBD,
  "type": "request",
  "listeners": ["broker", "responsecontroller"],
  "name": "CreateMirrorResponseAddTopicsToMirrorRequest",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorName", "type": "string", "versions": "ThrottleTimeMs "0+", "entityType": "mirrorName",
      "about": "The cluster mirror name." },
    { "name": "Topics", "type": "int32[]TopicData", "versions": "0+",
      "about": "The duration in millisecondsdata for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
topics.",
      "fields": [
        { "name": "ErrorCodeTopicId", "type": "int16uuid", "versions": "0+",
      "about": "The errorunique code, or 0 if there was no errortopic ID." },
        { "name": "ErrorMessageTopicName", "type": "string", "versions": "0+", "nullableVersionsmapKey": "0+",
     true, "aboutentityType": "topicName"The,
  error message, or null if there was no error." }
  ]
}

AddTopicsToMirror

Adds topics to a specified mirror. The broker validates that all target topic partitions are in either UNKNOWN or STOPPED state; otherwise, the request is rejected with an INVALID_REQUEST error. Once validated, the request is forwarded to the controller, which sets the mirror.name topic config to the specified mirror name.

...

"about": "The topic name." }
      ]}
  ]
}

AddTopicsToMirrorResponse

Code Block
{
  "apiKey": TBD,
  "type": "requestresponse",
  "listeners": ["broker", "controller"],
  "name": "AddTopicsToMirrorRequestAddTopicsToMirrorResponse",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorNameThrottleTimeMs", "type": "stringint32", "versions": "0+",
      "entityTypeabout": "mirrorName",
      "about": "The cluster mirror nameThe duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
      { "name": "TopicsErrorCode", "type": "[]TopicDataint16", "versions": "0+",
      "about": "The dataerror forcode, the topics.",
      "fields": [or 0 if there was no error." },
    { "name": "ErrorMessage",  {"type": "string", "nameversions": "TopicId0+", "typenullableVersions": "uuid0+", "versionsdefault": "0+null",
      "about": "The unique topic ID."},
     top-level error message, or null if there was no error." },
    { "name": "TopicNameMirrorName", "type": "string", "versions": "0+", "mapKey": true, "entityType": "topicNamemirrorName",
          "about": "The cluster topicmirror name." },
      ]}
  ]
}

AddTopicsToMirrorResponse

Code Block
{
  "apiKey": TBD,
     { "name": "Topics", "type": "response[]TopicResult",
  "nameversions": "AddTopicsToMirrorResponse0",
  // Version 0 is the initial version.
  "validVersionsabout": "0",
  "flexibleVersions": "0+",
  The results for the topics.", "fields": [
      { "name": "ThrottleTimeMsName", "type": "int32string", "versions": "0+",
      "aboutentityType": "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota"topicName",
        "about": "The topic name." },
      { "name": "ErrorCode", "type": "int16", "versions": "0+",
        "about": "The error code, or 0 if there was no error." },
    ]}
  ]
}

RemoveTopicsFromMirror

Allows users to detach topics from their associated mirror. The broker validates that all target topic partitions are in either PREPARING or MIRRORING state. Once validated, the request is forwarded to the controller, which appends the ".removed" suffix to the mirror.name topic config to mark the topics as no longer mirrored.

RemoveTopicsFromMirrorRequest

Code Block
{
  "nameapiKey": "ErrorMessage"TBD,
  "type": "stringrequest",
  "versionslisteners": ["0+broker", "nullableVersionscontroller": "0+",],
  "defaultname": "nullRemoveTopicsFromMirrorRequest",
  // Version 0 is the initial version.
  "aboutvalidVersions": "The top-level error message, or null if there was no error." },0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorName", "type": "string", "versions": "0+string", "entityTypeversions": "mirrorName0+",
      "about": "The cluster mirror name." },
    { "name": "Topics", "type": "[]TopicResultTopicData", "versions": "0+",
      "about": "The resultsdata for the topics.",
      "fields": [
        { "name": "NameTopicId", "type": "stringuuid", "versions": "0+", "entityType": "topicName",
        "about": "The unique topic nameID." },
        { "name": "ErrorCodeTopicName", "type": "int16string", "versions": "0+", "mapKey": true, "entityType": "topicName",
          "about": "The error code, or 0 if there was no errortopic name." }
      ]}
  ]
}

RemoveTopicsFromMirror

Allows users to detach topics from their associated mirror. The broker validates that all target topic partitions are in either PREPARING or MIRRORING state. Once validated, the request is forwarded to the controller, which appends the ".removed" suffix to the mirror.name topic config to mark the topics as no longer mirrored.

RemoveTopicsFromMirrorRequest

RemoveTopicsFromMirrorResponse

Code Block
{
  "apiKey": TBD,
  "type": "request",
  "listeners": ["broker", "controller"]response",
  "name": "RemoveTopicsFromMirrorRequestRemoveTopicsFromMirrorResponse",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorNameThrottleTimeMs", "type": "stringint32", "versions": "0+",
      "about": "The cluster mirror name duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
      { "name": "TopicsErrorCode", "type": "[]TopicDataint16", "versions": "0+",
      "about": "The dataerror forcode, the topics.",
      "fields": [
    or 0 if there was no error." },
    { "name": "TopicIdErrorMessage", "type": "uuidstring", "versions": "0+", "nullableVersions": "0+", "default": "null",
      "about": "The unique topic ID."},
     top-level error message, or null if there was no error." },
    { "name": "TopicNameMirrorName", "type": "string", "versions": "0+", "mapKey": true, "entityType": "topicNamemirrorName",
          "about": "The topic name." }
      ]}
  ]
}

RemoveTopicsFromMirrorResponse

Code Block
{
  "apiKey": TBD,
   "The cluster mirror name." },
    { "name": "Topics", "type": "response[]TopicResult",
  "nameversions": "RemoveTopicsFromMirrorResponse0",
  // Version 0 is the initial version.
  "validVersionsabout": "0",
  "flexibleVersions": "0+",
 The results for the topics.", "fields": [
      { "name": "ThrottleTimeMsName", "type": "int32string", "versions": "0+",
      "aboutentityType": "ThetopicName",
 duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota"about": "The topic name." },
      { "name": "ErrorCode", "type": "int16", "versions": "0+",
        "about": "The error code, or 0 if there was no error." }
    ]}
  ]
}

PauseMirrorTopics

Pauses data replication and metadata sync for the specified mirror topics, keeping them read-only on the destination cluster.

PauseMirrorTopicsRequest

Code Block
{
  "apiKey": TBD,
 " },
    { "name": "ErrorMessage", "type": "stringrequest",
  "versionslisteners": ["0+broker", "nullableVersionscontroller": "0+",],
  "defaultname": "nullPauseMirrorTopicsRequest",
  // Version 0 is the initial version.
  "aboutvalidVersions": "0"The,
 top-level error message, or null if there was no error." }, "flexibleVersions": "0+",
  "fields": [
    { "name": "MirrorName", "type": "string", "versions": "0+", "entityType": "mirrorName",
      "about": "The cluster mirror name to pause the topics for." },
    { "name": "Topics", "type": "[]TopicResultTopicData", "versions": "0+",
      "about": "The resultsdata for the topics.",
      "fields": [
        { "name": "NameTopicId", "type": "stringuuid", "versions": "0+", "entityTypeabout": "topicName"The unique topic ID."},
        { "aboutname": "TopicName"The topic name." },
      { "name, "type": "string", "versions": "ErrorCode0+", "typemapKey": "int16"true, "versionsentityType": "0topicName",
          "about": "The error code, or 0 if there was no errortopic name." }
      ]}
  ]
}

PauseMirrorTopics

Pauses data replication and metadata sync for the specified mirror topics, keeping them read-only on the destination cluster.

PauseMirrorTopicsRequest

PauseMirrorTopicsResponse

Code Block
{
  "apiKey": TBD,
  "type": "requestresponse",
  "name": "listeners"PauseMirrorTopicsResponse",
  // Version 0 is the initial version.
  "validVersions": ["broker0",
  "flexibleVersions": "controller0+"],
 ,
  "fields": [
    { "name": "PauseMirrorTopicsRequestThrottleTimeMs",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": ["type": "int32", "versions": "0+",
      "about": "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "MirrorNameErrorCode", "type": "stringint16", "versions": "0+",
      "about": "The error code, mirroror name0 toif pausethere thewas topicsno forerror." },
      { "name": "TopicsErrorMessage", "type": "[]TopicDatastring", "versions": "0+", "aboutnullableVersions": "0+"The data for the topics., "default": "null",
      "fieldsabout": [
     "The top-level error message, or null if there was no error." },
    { "name": "TopicIdMirrorName", "type": "uuidstring", "versions": "0+", "entityType": "mirrorName",
      "about": "The uniquecluster topicmirror IDname." },
          { "name": "TopicNameTopics", "type": "string[]TopicResult", "versions": "0+", "mapKey": true, "entityType": "topicName",
          "about": "The topic name." }
 results for the topics.", "fields": [
     ]}
  ]
}

PauseMirrorTopicsResponse

Code Block
{
  "apiKeyname": TBD"Name",
  "type": "responsestring",
  "versions": "0", "nameentityType": "PauseMirrorTopicsResponsetopicName",
  // Version 0 is the initial version.
  "validVersionsabout": "0",
The topic "flexibleVersionsname.": "0+"},
  "fields": [
    { "name": "ThrottleTimeMsErrorCode", "type": "int32int16", "versions": "0+",
        "about": "The durationerror incode, millisecondsor for0 whichif the requestthere was throttledno error." }
    ]}
  ]
}

ResumeMirrorTopics

Resumes data replication and metadata sync for previously paused mirror topics from where they left off.

ResumeMirrorTopicsRequest

Code Block
{
  "apiKey": TBD,
  "type": "request",
  "listeners": ["broker", "controller"],
  "name": "ResumeMirrorTopicsRequest",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "ErrorCode", "type": "int16", "versions": "0+",
      "about": "The error code, or 0 if there was no error." },
    { "name": "ErrorMessageMirrorName", "type": "string", "versions": "0+", "nullableVersions": "0+", "default": "null",
      "about": "The top-levelcluster error message, or null if there was no errormirror name." },
      { "name": "MirrorNameTopics", "type": "string[]TopicData", "versions": "0+", "entityTypeabout": "mirrorNameThe data for the topics.",
      "aboutfields": [
 "The  cluster mirror name." },
    { "name": "TopicsTopicId", "type": "[]TopicResultuuid", "versions": "0+",
      "about": "The resultsunique fortopic the topicsID."},
 "fields": [
      { "name": "NameTopicName", "type": "string", "versions": "0+", "mapKey": "0"true, "entityType": "topicName",
          "about": "The topic name." },
      ]}
  ]
}

ResumeMirrorTopicsResponse

Code Block
{
  "nameapiKey": "ErrorCode"103,
  "type": "int16response",
  "versionsname": "0ResumeMirrorTopicsResponse",
  // Version 0 is the initial version.
  "aboutvalidVersions": "0"The,
 error code, or 0 if there was no error." }
    ]}
  ]
}

ResumeMirrorTopics

Resumes data replication and metadata sync for previously paused mirror topics from where they left off.

ResumeMirrorTopicsRequest

Code Block
{
  "apiKey": TBD,
  "flexibleVersions": "0+",
  "fields": [
    { "name": "ThrottleTimeMs", "type": "requestint32",
  "listenersversions": ["broker0+", "controller"],

      "nameabout": "ResumeMirrorTopicsRequest",
The duration //in Versionmilliseconds 0for iswhich the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [request was throttled due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "MirrorNameErrorCode", "type": "stringint16", "versions": "0+",
      "about": "The cluster mirror name error code, or 0 if there was no error." },
      { "name": "TopicsErrorMessage", "type": "[]TopicDatastring", "versions": "0+", "aboutnullableVersions": "0+"The data for the topics., "default": "null",
      "fieldsabout": [
     "The top-level error message, or null if there was no error." },
    { "name": "TopicIdMirrorName", "type": "uuidstring", "versions": "0+", "entityType": "mirrorName",
      "about": "The uniquecluster topicmirror IDname." },
          { "name": "TopicNameTopics", "type": "string[]TopicResult", "versions": "0+", "mapKey": true, "entityType": "topicName",
          "about": "The topic name." }
   results for the topics.", "fields": [
    ]}
  ]
}

ResumeMirrorTopicsResponse

Code Block
{
  "apiKeyname": 103"Name",
  "type": "responsestring",
  "versions": "0", "nameentityType": "ResumeMirrorTopicsResponsetopicName",
  // Version 0 is the initial version.
  "validVersionsabout": "0",
The topic "flexibleVersionsname.": "0+"},
  "fields": [
    { "name": "ThrottleTimeMsErrorCode", "type": "int32int16", "versions": "0+",
        "about": "The durationerror incode, millisecondsor for0 whichif the requestthere was throttledno due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "ErrorCode", "type": "int16", "versions": "0+",
      "about": "The error code, or 0 if there was no error." },error." }
    ]}
  ]
}

DeleteMirror

Permanently deletes a cluster mirror, including its configuration. The mirror must be empty (no topics) or all its partitions must be in STOPPED state. After deletion, all metadata are tombstoned, making failback impossible. This is an irreversible operation.

DeleteMirrorRequest

Code Block
{
  "apiKey": 104,
  "type": "request",
  "listeners": ["broker", "controller"],
  "name": "DeleteMirrorRequest",
  "latestVersionUnstable": true,
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "ErrorMessageMirrorName", "type": "string", "versions": "0+", "nullableVersionsentityType": "0+", "default": "nullmirrorName",
      "about": "The top-levelcluster errormirror message,name to delete."}
  ]
}

DeleteMirrorResponse

Code Block
{
  "apiKey": 104,
  "typeor null if there was no error." },
    { "name": "MirrorNameresponse",
  "typename": "stringDeleteMirrorResponse",
  // Version 0 "versionsis the initial version.
  "validVersions": "0+",
  "entityTypeflexibleVersions": "mirrorName0+",
      "aboutfields": "The cluster mirror name." },
   [
    { "name": "TopicsThrottleTimeMs", "type": "[]TopicResultint32", "versions": "0+",
      "about": "The duration in resultsmilliseconds for which the topics.", "fields": [request was throttled due to a quota violation, or zero if the request did not violate any quota." },
      { "name": "NameErrorCode", "type": "stringint16", "versions": "0", "entityType": "topicName+",
        "about": "The topic name error code, or 0 if there was no error." },
      { "name": "ErrorCodeErrorMessage", "type": "int16string", "versions": "0+",
 "nullableVersions": "0+",
      "about": "The error codemessage, or 0null if there was no error." }
    ]}
  ]
}

ListMirrors

Returns the current mirror names and their associated topic counts in the cluster. It also includes source cluster ID and bootstrap server.

ListMirrorsRequest

Code Block
{
  "apiKey": TBD,
  "type": "request",
  "listeners": ["broker"],
  "name": "ListMirrorsRequest",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": []
}

...

Code Block
{
  "apiKey": TBD,
  "type": "response",
  "name": "ListMirrorsResponse",
  // Version 0 is the initial version.
  "validVersions": "0",
  "flexibleVersions": "0+",
  "fields": [
    { "name": "ThrottleTimeMs", "type": "int32", "versions": "0+",
      "about": "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "ErrorCode", "type": "int16", "versions": "0+",
      "about": "The error code, or 0 if there was no error." },
    { "name": "ErrorMessage", "type": "string", "versions": "0+", "nullableVersions": "0+", "default": "null",
      "about": "The top-level error message, or null if there was no error." },
    { "name": "Mirrors", "type": "[]ListedMirror", "versions": "0+",
      "about": "Each mirror in the response.", "fields": [
      { "name": "MirrorName", "type": "string", "versions": "0+", "entityType": "mirrorName",
        "about": "The cluster mirror name." },
      { "name": "SourceBootstrap", "type": "string", "versions": "0+",
        "about": "The source cluster bootstrap servers." },
      { "name": "SourceClusterId", "type": "string", "versions": "0+", "default": "",
        "about": "The source cluster ID, or empty if not yet resolved." },
      { "name": "TopicCount", "type": "int32", "versions": "0+", "default": "0",
        "about": "The number of topics configured for this mirror. 0 indicates an empty mirror with no topics." }
    ]}
  ]
}

DescribeMirrors

 Returns Returns the current mirroring status, state, and configuration for the specified mirror topics on the destination cluster.

...

Error CodeNameMessageUsed By
3UNKNOWN_TOPIC_OR_PARTITIONThe topic does not exist on the target clusterRemoveTopicsFromMirror, PauseMirrorTopics, ResumeMirrorTopics
15COORDINATOR_NOT_AVAILABLEThe mirror coordinator is not activeWriteMirrorStates, ReadMirrorStates, LastMirroredOffsets
31CLUSTER_AUTHORIZATION_FAILEDThe client is not authorized to perform the mirror operation

CreateMirror, AddTopicsToMirror, RemoveTopicsFromMirror, PauseMirrorTopics, ResumeMirrorTopics,

ListMirrors, DescribeMirrors, WriteMirrorStates, ReadMirrorStates, LastMirroredOffsets

35UNSUPPORTED_VERSIONCluster mirroring is disabled (mirror.version=0)

CreateMirror, AddTopicsToMirror, RemoveTopicsFromMirror, PauseMirrorTopics, ResumeMirrorTopics,

ListMirrors, DescribeMirrors, WriteMirrorStates, ReadMirrorStates, LastMirroredOffsets

38INVALID_REPLICATION_FACTORInsufficient brokers available to replicate the mirror topicCreateMirror
39INVALID_REPLICA_ASSIGNMENTBrokers in the partition assignment are fenced or in controlled shutdownCreateMirror
TBDREAD_ONLY_TOPICThe topic is read-only because it is a mirror topic on the target clusterProduce
TBDINVALID_MIRROR_NAMEThe mirror name does not meet the naming rulesCreateMirror
TBDUNKNOWN_MIRRORThe topic is not assigned to any mirrorRemoveTopicsFromMirror, PauseMirrorTopics, ResumeMirrorTopics
TBDTOPIC_ALREADY_IN_MIRRORThe topic is already assigned to a mirrorAddTopicsToMirror
TBDTOPIC_NOT_IN_MIRRORThe topic does not belong to the specified mirrorRemoveTopicsFromMirror, PauseMirrorTopics, ResumeMirrorTopics
TBDMIRROR_TOPIC_ALREADY_PAUSEDThe mirror topic is already pausedPauseMirrorTopics
TBDMIRROR_TOPIC_NOT_PAUSEDThe mirror topic is not pausedResumeMirrorTopics
TBDMIRROR_TOPIC_BEING_REMOVEDThe mirror topic is being removedResumeMirrorTopics
TBDMIRROR_NOT_EMPTYThe mirror still has active or non-removed topicsDeleteMirror

Compatibility, Deprecation, and Migration Plan

...