> ## Documentation Index
> Fetch the complete documentation index at: https://cockroachlabs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# How Does a Changefeed Work?

export const InternalLink = ({version, path = "", children, ...props}) => {
  let detectedVersion = version || "stable";
  if (typeof window !== 'undefined' && !version) {
    const match = window.location.pathname.match(/\/docs\/([^/]+)/);
    if (match) {
      detectedVersion = match[1];
    }
  }
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
  return <a href={`/docs/${detectedVersion}/${normalizedPath}`} {...props}>
      {children}
    </a>;
};

When a changefeed that will emit changes to a sink is started on a node, that node becomes the *coordinator* for the changefeed job (**Node 2** in the diagram). The coordinator node acts as an administrator: keeping track of all other nodes during job execution and the changefeed work as it completes. The changefeed job will run across nodes in the cluster to access changed data in the watched table. The job will evenly distribute changefeed work across the cluster by assigning it to any <InternalLink path="architecture/replication-layer">replica</InternalLink> for a particular range, which determines the node that will emit the changefeed data. If a <InternalLink path="changefeeds-in-multi-region-deployments#run-a-changefeed-job-by-locality">locality filter</InternalLink> is specified, work is distributed to a node from those that match the locality filter and has the most locality tiers in common with a node that has a replica.

Each node uses its *aggregator processors* to send back checkpoint progress to the coordinator, which gathers this information to update the *high-water mark timestamp*. The high-water mark acts as a checkpoint for the changefeed’s job progress, and guarantees that all changes before (or at) the timestamp have been emitted. In the unlikely event that the changefeed’s coordinating node were to fail during the job, that role will move to a different node and the changefeed will restart from the last checkpoint. If restarted, the changefeed may <InternalLink path="changefeed-messages#duplicate-messages">re-emit messages</InternalLink> starting at the high-water mark time to the current time. Refer to <InternalLink path="changefeed-messages#ordering-and-delivery-guarantees">Ordering Guarantees</InternalLink> for detail on CockroachDB's at-least-once-delivery-guarantee and how per-key message ordering is applied.

<img src="https://mintcdn.com/cockroachlabs/_ajVjtIOzaJKY_2M/images/v25.4/changefeed-structure.png?fit=max&auto=format&n=_ajVjtIOzaJKY_2M&q=85&s=2798157168565777c883b822c3fb6017" alt="Changefeed process in a 3-node cluster" width="4498" height="3369" data-path="images/v25.4/changefeed-structure.png" />

With <InternalLink path="create-changefeed">`resolved`</InternalLink> specified when a changefeed is started, the coordinator will send the resolved timestamp (i.e., the high-water mark) to each endpoint in the sink. For example, when using <InternalLink path="changefeed-sinks#kafka">Kafka</InternalLink> this will be sent as a message to each partition; for <InternalLink path="changefeed-sinks#cloud-storage-sink">cloud storage</InternalLink>, this will be emitted as a resolved timestamp file.

As rows are updated, added, and deleted in the targeted table(s), the node sends the row changes through the <InternalLink path="create-and-configure-changefeeds#enable-rangefeeds">rangefeed mechanism</InternalLink> to the changefeed encoder, which encodes these changes into the <InternalLink path="changefeed-messages">final message format</InternalLink>. The message is emitted from the encoder to the sink—it can emit to any endpoint in the sink. In the diagram example, this means that the messages can emit to any Kafka Broker.

If you are running changefeeds from a <InternalLink path="multiregion-overview">multi-region</InternalLink> cluster, you may want to define which nodes take part in running the changefeed job. You can use the <InternalLink path="changefeeds-in-multi-region-deployments#run-a-changefeed-job-by-locality">`execution_locality` option</InternalLink> with key-value pairs to specify the locality requirements nodes must meet. See <InternalLink path="changefeeds-in-multi-region-deployments#job-coordination-using-the-execution-locality-option">Job coordination using the execution locality option</InternalLink> for detail on how a changefeed job works with this option.

See the following for more detail on changefeed setup and use:

* <InternalLink path="create-and-configure-changefeeds#enable-rangefeeds">Enable rangefeeds</InternalLink>
* <InternalLink path="changefeed-sinks">Changefeed Sinks</InternalLink>
* <InternalLink path="changefeed-examples">Changefeed Examples</InternalLink>
