> ## 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.

# CREATE SCHEDULE FOR CHANGEFEED

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>;
};

`CREATE SCHEDULE FOR CHANGEFEED` allows you to create a scheduled changefeed to export data out of CockroachDB. Scheduled changefeeds have the scale, observability, and endpoint sink options that changefeed jobs include, with the convenience of setting a regular schedule. A changefeed job created with `CREATE SCHEDULE FOR CHANGEFEED` performs a one-time table scan using the <InternalLink path="create-changefeed">initial scan</InternalLink> functionality to create an export of your table data.

For more detail on using changefeeds to create an export of your table data, see <InternalLink path="export-data-with-changefeeds">Export Data with Changefeeds</InternalLink>.

## Required privileges

You can <InternalLink path="grant#grant-privileges-on-specific-tables-in-a-database">grant</InternalLink> a user the `CHANGEFEED` privilege to allow them to create changefeeds on a specific table:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
GRANT CHANGEFEED ON TABLE example_table TO user;
```

When you grant a user the `CHANGEFEED` privilege on a set of tables, they can:

* Create changefeeds on the target tables even if the user does **not** have the <InternalLink path="alter-role#role-options">`CONTROLCHANGEFEED` role option</InternalLink> or the `SELECT` privilege on the tables.
* Manage the changefeed jobs running on the tables using the <InternalLink path="show-jobs#show-changefeed-jobs">`SHOW CHANGEFEED JOB`</InternalLink>, <InternalLink path="pause-job">`PAUSE JOB`</InternalLink>, <InternalLink path="resume-job">`RESUME JOB`</InternalLink>, and <InternalLink path="cancel-job">`CANCEL JOB`</InternalLink> commands.

These users will be able to create changefeeds, but they will not be able to run a `SELECT` query on that data directly. However, they could still read this data indirectly if they have read access to the <InternalLink path="changefeed-sinks">sink</InternalLink>.

To restrict a user's access to changefeed data and sink credentials, enable the `changefeed.permissions.require_external_connection_sink.enabled` cluster setting. When you enable this setting, users with the <InternalLink path="create-changefeed#required-privileges">`CHANGEFEED` privilege</InternalLink> on a set of tables can only create changefeeds into <InternalLink path="create-external-connection">external connections</InternalLink>.

You can add `CHANGEFEED` to the user or role's <InternalLink path="security-reference/authorization#default-privileges">default privileges</InternalLink> with <InternalLink path="alter-default-privileges#grant-default-privileges-to-a-specific-role">`ALTER DEFAULT PRIVILEGES`</InternalLink>:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
ALTER DEFAULT PRIVILEGES GRANT CHANGEFEED ON TABLES TO user;
```

### Privilege model

<Tip>
  For fine-grained access control, we recommend using the system-level privileges `CHANGEFEED` and `CONTROLJOB` / `VIEWJOB`.
</Tip>

The following summarizes the operations users can run when they have changefeed privileges on a table:

| Granted privileges                                                                                                               | Usage                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CHANGEFEED`                                                                                                                     | Create changefeeds on tables. View and manage changefeed jobs on tables.                                                                                                                                                                                                                                                                                                                                                                                             |
| `CHANGEFEED` + <InternalLink path="create-external-connection#required-privileges">`USAGE`</InternalLink> on external connection | Create changefeeds on tables to an external connection URI. Manage changefeed jobs on tables. **Note:** If you need to manage access to changefeed sink URIs, set the `changefeed.permissions.require\_external\_connection\_sink.enabled=true` cluster setting. This will mean that users with these privileges can **only** create changefeeds on external connections.                                                                                            |
| `SELECT`                                                                                                                         | Create a sinkless changefeed that emits messages to a SQL client.                                                                                                                                                                                                                                                                                                                                                                                                    |
| **Deprecated**`CONTROLCHANGEFEED` role option + `SELECT`                                                                         | Create changefeeds on tables. Users with the `CONTROLCHANGEFEED` role option must have `SELECT` on each table, even if they are also granted the `CHANGEFEED` privilege.  The `CONTROLCHANGEFEED` role option will be removed in a future release. We recommend using the <InternalLink path="security-reference/authorization#supported-privileges">system-level privileges</InternalLink>`CHANGEFEED` and `CONTROLJOB`/ `VIEWJOB` for fine-grained access control. |
| `admin`                                                                                                                          | Create, view, and manage changefeed jobs.                                                                                                                                                                                                                                                                                                                                                                                                                            |

## Synopsis

<img src="https://mintcdn.com/cockroachlabs/Bc-7BE4092mn9J_1/images/sql-diagrams/v23.2/create_schedule_for_changefeed.svg?fit=max&auto=format&n=Bc-7BE4092mn9J_1&q=85&s=a99c442e06cf52142a86dd56fa175a1e" alt="create_schedule_for_changefeed syntax diagram" style={{maxWidth: "100%", overflowX: "auto"}} width="1235" height="517" data-path="images/sql-diagrams/v23.2/create_schedule_for_changefeed.svg" />

### Parameters

| Parameter             | Description                                                                                                                                                                                                                                               |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IF NOT EXISTS`       | A scheduled changefeed should not be created if the `schedule\_label` already exists. You will receive an error if the schedule label already exists, or if `schedule\_label` is not defined when using `IF NOT EXISTS`.                                  |
| `schedule\_label`     | The name for the scheduled changefeed. This is optional and does not need to be unique. If you do not define a name, the label will default to `CHANGEFEED` with the timestamp of when you created the schedule.                                          |
| `changefeed\_targets` | The tables to target with the changefeed. For example, `movr.users, movr.rides`.                                                                                                                                                                          |
| `changefeed\_sink`    | The <InternalLink path="changefeed-sinks">changefeed sink URI</InternalLink>.                                                                                                                                                                             |
| `changefeed\_option`  | The <InternalLink path="create-changefeed#options">options</InternalLink> to control the behavior of your changefeed. For example, `WITH format = csv, full\_table\_name`. See [Changefeed options](#changefeed-options) for a list of available options. |
| `target\_list`        | The columns to emit data from if you're using a <InternalLink path="cdc-queries">CDC query</InternalLink> expression.                                                                                                                                     |
| `insert\_target`      | The target tables for the changefeed if you're using a <InternalLink path="cdc-queries">CDC query</InternalLink> expression.                                                                                                                              |
| `where\_clause`       | An optional `WHERE` clause to apply filters to the table if you're using a <InternalLink path="cdc-queries">CDC query</InternalLink> expression.                                                                                                          |
| `crontab`             | The frequency of the changefeed. The schedule is specified as a `STRING` in [crontab format](https://wikipedia.org/wiki/Cron). All times in UTC. For example, `'@daily'`, `'@hourly'`, `'1 0 \* \* \*'`.                                                  |
| `schedule\_option`    | The schedule options to control the schedule's behavior. For example, `first\_run = now`. See [Schedule options](#schedule-options).                                                                                                                      |

## Changefeed options

You can include the changefeed options listed on the <InternalLink path="create-changefeed#options">`CREATE CHANGEFEED`</InternalLink> page to modify the behavior of your changefeed. The following options are **not** compatible with scheduled changefeeds:

* `diff`
* `end_time`
* `mvcc_timestamp`
* `resolved`
* `updated`

Scheduled changefeeds have the <InternalLink path="create-changefeed">`initial_scan = 'only'`</InternalLink> option included implicitly. You cannot specify `initial_scan` as `'yes'` or `'no'`.

## Schedule options

| Option                   | Value                                                             | Description                                                                                                                                                                                                                                                                                                                                                                           |
| ------------------------ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `first\_run`             | <InternalLink path="timestamp">`TIMESTAMP`</InternalLink> / `now` | Execute the first run of the schedule at this time. If you do not specify `first\_run`, the schedule will execute based on the next `RECURRING` time set by the crontab.                                                                                                                                                                                                              |
| `on\_execution\_failure` | `retry` / `reschedule` / `pause`                                  | Determine how the schedule handles an error.  `retry`: Retry the changefeed immediately.  `reschedule`: Reschedule the changefeed based on the `RECURRING` expression.  `pause`: Pause the schedule. This requires that you <InternalLink path="resume-schedules">resume the schedule</InternalLink> manually.  **Default:**`reschedule`                                              |
| `on\_previous\_running`  | `start` / `skip` / `wait`                                         | Control whether the changefeed schedule should start a changefeed if the previous scheduled changefeed is still running.  `start`: Start the new changefeed anyway, even if the previous one is running.  `skip`: Skip the new changefeed and run the next changefeed based on the `RECURRING` expression.  `wait`: Wait for the previous changefeed to complete.  **Default:**`wait` |

## Examples

Before running any of the examples in this section, it is necessary to enable the `kv.rangefeed.enabled` cluster setting. If you are working on a CockroachDB Standard or Basic cluster, this cluster setting is enabled by default.

The <InternalLink path="changefeed-sinks">Changefeed Sinks</InternalLink> page provides detail on the available sinks for your change data messages and connection URIs. We recommend using <InternalLink path="create-external-connection">external connections</InternalLink> to interact with external sinks. The examples in this section use an external connection URI for the changefeed sink.

### Create a scheduled changefeed

The following statement sets up a scheduled changefeed named `users_rides_nightly` that will send changefeed messages in `CSV` format 1 minute past midnight every night. As soon as the statement is run, the first changefeed run will execute immediately:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE SCHEDULE users_rides_nightly FOR CHANGEFEED users, rides INTO 'external://kafka-sink' WITH format=csv RECURRING '1 0 * * *' WITH SCHEDULE OPTIONS first_run=now, on_execution_failure=retry, on_previous_running=skip;
```

The <InternalLink path="create-schedule-for-changefeed#schedule-options">schedule options</InternalLink> control the schedule's behavior:

* If it runs into an error, `on_execution_failure=retry` will ensure that the schedule retries the changefeed immediately.
* If the previous scheduled changefeed is still running, `on_previous_running=skip` will skip a new changefeed at the next scheduled time.

The output will confirm that the changefeed has added the `initial_scan = 'only'` option implicitly:

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
     schedule_id     |     label     | status |           first_run           | schedule  |                                                      changefeed_stmt
---------------------+---------------+--------+-------------------------------+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------
  947257854259855361 | users_nightly | ACTIVE | 2024-02-28 20:02:35.716699+00 | 1 0 * * * | CREATE CHANGEFEED FOR TABLE movr.public.users, TABLE movr.public.rides INTO 'external://kafka-sink' WITH OPTIONS (format = 'csv', initial_scan = 'only')
(1 row)

NOTICE: added missing initial_scan='only' option to schedule changefeed
```

### Create a scheduled changefeed with CDC queries

You can use CDC queries with scheduled changefeeds to define expression syntax that selects columns and applies filters to further restrict or transform the data in your changefeed messages. When you add this expression syntax to your changefeed statement, you can only target one table.

For guidance on syntax and more example use cases, see <InternalLink path="cdc-queries">Change Data Capture Queries</InternalLink>.

This scheduled changefeed filters for the usage of promotion codes in the <InternalLink path="movr">`movr`</InternalLink> database and sends the changefeed messages on a daily basis:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE SCHEDULE promo_code FOR CHANGEFEED INTO 'external://kafka-sink' AS SELECT user_id, usage_count FROM movr.user_promo_codes WHERE usage_count > 1 RECURRING '@daily' WITH SCHEDULE OPTIONS first_run=now, on_execution_failure=reschedule, on_previous_running=skip;
```

### View scheduled changefeed details

To <InternalLink path="show-schedules">show</InternalLink> all scheduled changefeeds:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SHOW SCHEDULES FOR CHANGEFEED;
```

To view the details of only running scheduled changefeeds:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SHOW RUNNING SCHEDULES FOR CHANGEFEED;
```

To view the details of only paused scheduled changefeeds:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SHOW PAUSED SCHEDULES FOR CHANGEFEED;
```

To view the details of a specific scheduled changefeed:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SHOW SCHEDULE {schedule ID};
```

To <InternalLink path="pause-schedules">pause</InternalLink> a scheduled changefeed:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
PAUSE SCHEDULE {schedule ID};
```

To <InternalLink path="resume-schedules">resume</InternalLink> a scheduled changefeed:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
RESUME SCHEDULE {schedule ID};
```

To <InternalLink path="drop-schedules">delete</InternalLink> a scheduled changefeed:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
DROP SCHEDULE {schedule ID};
```

To see the full <InternalLink path="show-create-schedule">`CREATE SCHEDULE` statement</InternalLink> for the scheduled changefeed:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
SHOW CREATE SCHEDULE {schedule ID};
```

## See also

* <InternalLink path="create-changefeed">`CREATE CHANGEFEED`</InternalLink>
* <InternalLink path="cdc-queries">Change Data Capture Queries</InternalLink>
* <InternalLink path="export-data-with-changefeeds">Export Data with Changefeeds</InternalLink>
* <InternalLink path="changefeed-sinks">Changefeed Sinks</InternalLink>
