# Update Playbook

For the full operating document covering create, list, query, pause, resume, remove, and update, read [operation-guide.md](operation-guide.md) first. Use this file when the task is specifically about updates.

## Use the safe lifecycle

When modifying a changefeed, prefer this fixed sequence:

1. Query the current changefeed.
2. Pause the changefeed.
3. Modify `sink_uri`, `target_ts`, or config.
4. Resume the changefeed.
5. Query again and confirm both state and config are correct.

Reasons:

- The documentation requires the update flow to follow `pause -> update -> resume`.
- The server implementation only allows update when the changefeed is `stopped` or `failed`.

## Prefer CLI when a TOML file already exists

If a changefeed TOML file already exists, CLI is the simplest path because it merges the TOML patch into the current config instead of forcing manual full JSON construction.

Example:

```bash
cdc cli changefeed pause \
  --server=http://127.0.0.1:8300 \
  --keyspace=default \
  --changefeed-id=test

cdc cli changefeed update \
  --server=http://127.0.0.1:8300 \
  --keyspace=default \
  --changefeed-id=test \
  --config=/path/changefeed.toml \
  --sink-uri='mysql://root:123456@127.0.0.1:3306/'

cdc cli changefeed resume \
  --server=http://127.0.0.1:8300 \
  --keyspace=default \
  --changefeed-id=test
```

Example of a partial TOML patch already present in the repository:

```toml
[scheduler]
enable-table-across-nodes = true
region-threshold = 2

[filter]
rules = ['*.*', '!test.*']
```

This kind of file can be used directly with CLI update, but it must not be used directly as the full `replica_config` replacement for API update.

Do not add `--no-confirm` blindly to CLI update examples.
In the current CLI, it is not only a prompt-skip flag: if verification finds ineligible tables, it also sets `ignore_ineligible_table=true`.

## Use API carefully for update

Key rules for API update:

- First call `GET /api/v2/changefeeds/{id}` and use the returned `config` as the baseline.
- Then merge the new changes into that baseline.
- Finally send `PUT /api/v2/changefeeds/{id}`.
- If you omit a field inside `replica_config`, API update resets that field to its default instead of preserving the old value.

If only `sink_uri` or `target_ts` changes, sending only those fields is acceptable.

Example: change only `sink_uri`:

```bash
curl -X PUT 'http://127.0.0.1:8300/api/v2/changefeeds/test?keyspace=default' \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON'
{
  "sink_uri": "mysql://root:123456@127.0.0.1:3306/"
}
JSON
```

If `replica_config` must change, build the request in this order:

1. Call `GET /api/v2/changefeeds/{id}` and copy the returned `config`.
2. Convert the TOML patch from `kebab-case` keys to the API `snake_case` form.
3. Deep-merge the patch into the copied `config`.
4. Send the merged object back as the full `replica_config` in `PUT /api/v2/changefeeds/{id}`.

Do not send a partial TOML-derived object as the whole `replica_config` unless resetting omitted fields back to defaults is explicitly intended.

Skeleton request:

```bash
curl -X PUT 'http://127.0.0.1:8300/api/v2/changefeeds/test?keyspace=default' \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON'
{
  "replica_config": {
    "...": "merged current config plus requested patch"
  }
}
JSON
```

## Change `sink_uri` only

Decide first whether the task should be stopped:

- If following the standard operational flow, still do pause, then update, then resume.
- If only generating a request or command, still make the full lifecycle requirement explicit in the output.

CLI:

```bash
cdc cli changefeed update \
  --server=http://127.0.0.1:8300 \
  --keyspace=default \
  --changefeed-id=test \
  --sink-uri='kafka://127.0.0.1:9092/topic?protocol=open-protocol'
```

API:

```bash
curl -X PUT 'http://127.0.0.1:8300/api/v2/changefeeds/test?keyspace=default' \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON'
{
  "sink_uri": "kafka://127.0.0.1:9092/topic?protocol=open-protocol"
}
JSON
```

## Resume with checkpoint overwrite

CLI:

- Supports `--overwrite-checkpoint-ts=now`
- Also supports a concrete numeric TSO

API:

- Only accepts numeric `overwrite_checkpoint_ts`
- Requires checking the current or latest TSO before deciding to override

Risks:

- If the new checkpoint is greater than the current checkpoint, data in the skipped range may be lost.
- If the new checkpoint is less than the current checkpoint, downstream duplicate delivery may occur.

## Verify after update

- Run `query` again or call `GET /api/v2/changefeeds/{id}`.
- Confirm that `state` is back to `normal`.
- Confirm that `sink_uri`, `target_ts`, and the important config values match expectations.
- If catch-up status matters, also call `GET /api/v2/changefeeds/{id}/synced`.

## Optional validation targets

- Product docs:
  - the current docs in `https://github.com/pingcap/docs` on `master`
  - the matching `release-x.y` branch in the same repo when the current docs do not match the target deployment
  - under `ticdc/`, especially the changefeed management, OpenAPI v2, and changefeed config docs
- Source code, if a TiCDC checkout is available:
  - the CLI changefeed update and resume implementation
  - the OpenAPI v2 changefeed update and resume implementation
