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

# PlanetScale CLI commands: move-tables

export const PlatformAvailability = ({current, vitess, postgres, neki}) => {
  const docsHref = path => {
    if (!path) return path;
    const normalized = path.startsWith('/') ? path : `/${path}`;
    return normalized;
  };
  const labels = {
    vitess: 'Vitess',
    postgres: 'Postgres',
    neki: 'Neki'
  };
  const combinedLabels = {
    both: 'Vitess and Postgres',
    all: 'Vitess, Neki, and Postgres',
    'postgres-neki': 'Postgres and Neki'
  };
  if (combinedLabels[current]) {
    return <div className="not-prose mb-5 flex flex-wrap items-center gap-2" role="group" aria-label="Platform availability">
        <span data-engine="both" data-state="current" aria-current="true" className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=neki]:data-[state=current]:border-[#fbca00] data-[engine=neki]:data-[state=current]:bg-[#fbca00] data-[engine=neki]:data-[state=current]:text-[#1a1a1a] dark:data-[engine=neki]:data-[state=current]:border-[#fbca00] dark:data-[engine=neki]:data-[state=current]:bg-[#fbca00] dark:data-[engine=neki]:data-[state=current]:text-[#1a1a1a] data-[engine=neki]:data-[state=link]:border-[#fbca00] data-[engine=neki]:data-[state=link]:bg-transparent data-[engine=neki]:data-[state=link]:text-[#8f7200] dark:data-[engine=neki]:data-[state=link]:border-[#fbca00] dark:data-[engine=neki]:data-[state=link]:bg-transparent dark:data-[engine=neki]:data-[state=link]:text-[#fbca00] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
          {combinedLabels[current]}
        </span>
      </div>;
  }
  const hasVitess = current === 'vitess' || Boolean(vitess);
  const hasPostgres = current === 'postgres' || Boolean(postgres);
  const hasNeki = current === 'neki' || Boolean(neki);
  const only = [hasVitess, hasPostgres, hasNeki].filter(Boolean).length === 1;
  const engines = [];
  if (current === 'vitess' || current === 'postgres' || current === 'neki') engines.push(current);
  if (hasVitess && current !== 'vitess') engines.push('vitess');
  if (hasNeki && current !== 'neki') engines.push('neki');
  if (hasPostgres && current !== 'postgres') engines.push('postgres');
  return <div className="not-prose mb-5 flex flex-wrap items-center gap-2" role="group" aria-label="Platform availability">
      {engines.map(engine => {
    const isCurrent = current === engine;
    const href = docsHref(engine === 'vitess' ? vitess : engine === 'postgres' ? postgres : neki);
    const label = only ? `${labels[engine]} only` : labels[engine];
    const state = isCurrent || !href ? 'current' : 'link';
    if (isCurrent || !href) {
      return <span key={engine} data-engine={engine} data-state={state} aria-current={isCurrent ? 'true' : undefined} className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=neki]:data-[state=current]:border-[#fbca00] data-[engine=neki]:data-[state=current]:bg-[#fbca00] data-[engine=neki]:data-[state=current]:text-[#1a1a1a] dark:data-[engine=neki]:data-[state=current]:border-[#fbca00] dark:data-[engine=neki]:data-[state=current]:bg-[#fbca00] dark:data-[engine=neki]:data-[state=current]:text-[#1a1a1a] data-[engine=neki]:data-[state=link]:border-[#fbca00] data-[engine=neki]:data-[state=link]:bg-transparent data-[engine=neki]:data-[state=link]:text-[#8f7200] dark:data-[engine=neki]:data-[state=link]:border-[#fbca00] dark:data-[engine=neki]:data-[state=link]:bg-transparent dark:data-[engine=neki]:data-[state=link]:text-[#fbca00] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
              {label}
            </span>;
    }
    return <a key={engine} href={href} data-engine={engine} data-state={state} title={`View ${labels[engine]} documentation`} className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=neki]:data-[state=current]:border-[#fbca00] data-[engine=neki]:data-[state=current]:bg-[#fbca00] data-[engine=neki]:data-[state=current]:text-[#1a1a1a] dark:data-[engine=neki]:data-[state=current]:border-[#fbca00] dark:data-[engine=neki]:data-[state=current]:bg-[#fbca00] dark:data-[engine=neki]:data-[state=current]:text-[#1a1a1a] data-[engine=neki]:data-[state=link]:border-[#fbca00] data-[engine=neki]:data-[state=link]:bg-transparent data-[engine=neki]:data-[state=link]:text-[#8f7200] dark:data-[engine=neki]:data-[state=link]:border-[#fbca00] dark:data-[engine=neki]:data-[state=link]:bg-transparent dark:data-[engine=neki]:data-[state=link]:text-[#fbca00] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
            {label}
            <svg aria-hidden="true" width="12" height="12" viewBox="0 0 12 12" fill="none" className="shrink-0">
              <path d="M2.5 6h7M6.5 3l3 3-3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </a>;
  })}
    </div>;
};

<PlatformAvailability current="vitess" />

## Getting Started

Make sure to first [set up your PlanetScale developer environment](/docs/cli/planetscale-environment-setup). Once you've installed the `pscale` CLI, you can interact with PlanetScale and manage your databases straight from the command line.

## The `move-tables` command

Run [Vitess MoveTables](https://vitess.io/docs/user-guides/migration/move-tables/) workflows on a Vitess database branch: copy tables from one keyspace to another, check copy and traffic state, switch reads then writes, and complete or cancel the workflow.

JSON output includes a `next_steps` field with a suggested next command. Use it to see what to run after `list` or `status`.

**Usage:**

```bash theme={null}
pscale branch vtctld move-tables <SUB-COMMAND> <DATABASE_NAME> <BRANCH_NAME>
```

### Available sub-commands

| **Sub-command**                                 | **Sub-command flags**                                                                                                                                                                                                                                                                                                                                                                                                                                                      | **Description**                             |
| :---------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ |
| `list <DATABASE_NAME> <BRANCH_NAME>`            | `--target-keyspace <KEYSPACE_NAME>`                                                                                                                                                                                                                                                                                                                                                                                                                                        | List MoveTables workflows on the branch     |
| `create <DATABASE_NAME> <BRANCH_NAME>`          | `--workflow <NAME>`\*, `--source-keyspace <KEYSPACE_NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*, `--tables <TABLE_NAMES>`, `--all-tables`, `--exclude-tables <TABLE_NAMES>`, `--auto-start`, `--stop-after-copy`, `--defer-secondary-keys`, `--on-ddl <ACTION>`, `--sharded-auto-increment-handling <ACTION>`, `--global-keyspace <KEYSPACE_NAME>`, `--source-time-zone <TIME_ZONE>`, `--tenant-id <ID>`, `--cells <CELLS>`, `--tablet-types <TYPES>`, `--atomic-copy` | Create a MoveTables workflow                |
| `show <DATABASE_NAME> <BRANCH_NAME>`            | `--workflow <NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*                                                                                                                                                                                                                                                                                                                                                                                                               | Show a workflow                             |
| `status <DATABASE_NAME> <BRANCH_NAME>`          | `--workflow <NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*                                                                                                                                                                                                                                                                                                                                                                                                               | Show copy progress and traffic state        |
| `switch-traffic <DATABASE_NAME> <BRANCH_NAME>`  | `--workflow <NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*, `--tablet-types <TYPES>`\*, `--dry-run`, `--initialize-target-sequences`, `--max-replication-lag-allowed <SECONDS>`                                                                                                                                                                                                                                                                                          | Switch traffic to the target keyspace       |
| `reverse-traffic <DATABASE_NAME> <BRANCH_NAME>` | `--workflow <NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*, `--tablet-types <TYPES>`, `--dry-run`, `--max-replication-lag-allowed <SECONDS>`                                                                                                                                                                                                                                                                                                                             | Switch traffic back to the source keyspace  |
| `complete <DATABASE_NAME> <BRANCH_NAME>`        | `--workflow <NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*, `--keep-data`\*, `--keep-routing-rules`\*, `--rename-tables`, `--dry-run`                                                                                                                                                                                                                                                                                                                                    | Finish the workflow and clean up            |
| `cancel <DATABASE_NAME> <BRANCH_NAME>`          | `--workflow <NAME>`\*, `--target-keyspace <KEYSPACE_NAME>`\*, `--keep-data`\*, `--keep-routing-rules`\*                                                                                                                                                                                                                                                                                                                                                                    | Cancel a workflow that is still in progress |

> \* *Flag is required*

`list` also accepts the alias `ls`. Omit `--target-keyspace` on `list` to use the branch's default keyspace.

#### Sub-command flag descriptions

| **Sub-command flag**                         | **Description**                                                                                                            | **Applicable sub-commands**                                                                   |
| :------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- |
| `--workflow <NAME>`                          | Workflow name                                                                                                              | `create`, `show`, `status`, `switch-traffic`, `reverse-traffic`, `complete`, `cancel`         |
| `--source-keyspace <KEYSPACE_NAME>`          | Keyspace to copy tables from                                                                                               | `create`                                                                                      |
| `--target-keyspace <KEYSPACE_NAME>`          | Keyspace to copy tables to. On `list`, defaults to the branch's default keyspace                                           | `list`, `create`, `show`, `status`, `switch-traffic`, `reverse-traffic`, `complete`, `cancel` |
| `--tables <TABLE_NAMES>`                     | Tables to move (comma-separated). Mutually exclusive with `--all-tables` and `--exclude-tables`                            | `create`                                                                                      |
| `--all-tables`                               | Move all tables from the source keyspace                                                                                   | `create`                                                                                      |
| `--exclude-tables <TABLE_NAMES>`             | Tables to skip when moving (comma-separated)                                                                               | `create`                                                                                      |
| `--auto-start`                               | Start the workflow after creation (default `true`)                                                                         | `create`                                                                                      |
| `--stop-after-copy`                          | Stop the workflow after the copy phase                                                                                     | `create`                                                                                      |
| `--defer-secondary-keys`                     | Defer secondary indexes until copy finishes (default `true`)                                                               | `create`                                                                                      |
| `--on-ddl <ACTION>`                          | DDL handling: `IGNORE`, `STOP`, `EXEC`, `EXEC_IGNORE`                                                                      | `create`                                                                                      |
| `--sharded-auto-increment-handling <ACTION>` | `AUTO_INCREMENT` handling for sharded targets: `LEAVE`, `REMOVE`, `REPLACE`                                                | `create`                                                                                      |
| `--global-keyspace <KEYSPACE_NAME>`          | Unsharded keyspace for sequence tables when `--sharded-auto-increment-handling` is `REPLACE`                               | `create`                                                                                      |
| `--source-time-zone <TIME_ZONE>`             | Convert `DATETIME` values from this timezone to UTC                                                                        | `create`                                                                                      |
| `--tenant-id <ID>`                           | Tenant ID for multi-tenant MoveTables                                                                                      | `create`                                                                                      |
| `--cells <CELLS>`                            | Cells to restrict the workflow to (comma-separated)                                                                        | `create`                                                                                      |
| `--tablet-types <TYPES>`                     | Tablet types for the workflow or traffic switch (comma-separated). Use `REPLICA,RDONLY` for reads and `PRIMARY` for writes | `create`, `switch-traffic`, `reverse-traffic`                                                 |
| `--atomic-copy`                              | Use atomic copy                                                                                                            | `create`                                                                                      |
| `--dry-run`                                  | Show what would happen without applying it                                                                                 | `switch-traffic`, `reverse-traffic`, `complete`                                               |
| `--initialize-target-sequences`              | Initialize target sequences when switching traffic                                                                         | `switch-traffic`                                                                              |
| `--max-replication-lag-allowed <SECONDS>`    | Maximum replication lag allowed before switching                                                                           | `switch-traffic`, `reverse-traffic`                                                           |
| `--keep-data`                                | Keep copied data in the target (`true`) or remove it (`false`)                                                             | `complete`, `cancel`                                                                          |
| `--keep-routing-rules`                       | Keep routing rules (`true`) or remove them (`false`)                                                                       | `complete`, `cancel`                                                                          |
| `--rename-tables`                            | Rename source tables instead of dropping them                                                                              | `complete`                                                                                    |

### Available flags

| **Flag**                    | **Description**                       |
| :-------------------------- | :------------------------------------ |
| `-h`, `--help`              | View help for `move-tables`           |
| `--org <ORGANIZATION_NAME>` | The organization for the current user |

### Global flags

| **Command**                     | **Description**                                                                      |
| :------------------------------ | :----------------------------------------------------------------------------------- |
| `--api-token <TOKEN>`           | The API token to use for authenticating against the PlanetScale API.                 |
| `--api-url <URL>`               | The base URL for the PlanetScale API. Default is `https://api.planetscale.com/`.     |
| `--config <CONFIG_FILE>`        | Config file. Default is `$HOME/.config/planetscale/pscale.yml`.                      |
| `--debug`                       | Enable debug mode.                                                                   |
| `-f`, `--format <FORMAT>`       | Show output in a specific format. Possible values: `human` (default), `json`, `csv`. |
| `--no-color`                    | Disable color output.                                                                |
| `--service-token <TOKEN>`       | The service token for authenticating.                                                |
| `--service-token-id <TOKEN_ID>` | The service token ID for authenticating.                                             |

## Lifecycle

A typical MoveTables run looks like this:

1. **Create** the workflow and wait until copy finishes and streams are `Running`.
2. **Verify** with `pscale branch vtctld vdiff create`, then `vdiff show` until it completes with no mismatches. You can skip VDiff and switch replica traffic directly.
3. **Switch replica traffic** with `--tablet-types REPLICA,RDONLY`.
4. **Switch primary traffic** with `--tablet-types PRIMARY`.
5. **Preview cleanup** with `complete --dry-run`, then complete after you review the result.

Use `status` between steps. `traffic_state` values are:

* `Reads Not Switched. Writes Not Switched`
* `All Reads Switched. Writes Not Switched`
* `Reads Not Switched. Writes Switched`
* `All Reads Switched. Writes Switched`

## Examples

List MoveTables workflows and get the next command to run:

```bash theme={null}
pscale branch vtctld move-tables list mydb main --org acme --format json
```

Create a workflow:

```bash theme={null}
pscale branch vtctld move-tables create mydb main \
  --org acme \
  --workflow commerce2customer \
  --source-keyspace commerce \
  --target-keyspace customer \
  --tables customers,orders \
  --format json
```

Check copy and traffic state:

```bash theme={null}
pscale branch vtctld move-tables status mydb main \
  --org acme \
  --workflow commerce2customer \
  --target-keyspace customer \
  --format json
```

Example `status` JSON after replica traffic has switched:

```json theme={null}
{
  "traffic_state": "All Reads Switched. Writes Not Switched",
  "next_steps": [
    {
      "command": "pscale branch vtctld move-tables switch-traffic mydb main --org acme --workflow commerce2customer --target-keyspace customer --tablet-types PRIMARY --format json",
      "reason": "Switch primary traffic after validating replica traffic"
    }
  ]
}
```

Switch replica traffic, then primary traffic:

```bash theme={null}
pscale branch vtctld move-tables switch-traffic mydb main \
  --org acme \
  --workflow commerce2customer \
  --target-keyspace customer \
  --tablet-types REPLICA,RDONLY \
  --format json

pscale branch vtctld move-tables switch-traffic mydb main \
  --org acme \
  --workflow commerce2customer \
  --target-keyspace customer \
  --tablet-types PRIMARY \
  --format json
```

Verify with VDiff before switching traffic:

```bash theme={null}
pscale branch vtctld vdiff create mydb main \
  --org acme \
  --workflow commerce2customer \
  --target-keyspace customer \
  --format json

pscale branch vtctld vdiff show mydb main \
  --org acme \
  --workflow commerce2customer \
  --target-keyspace customer \
  --uuid <VDIFF_UUID> \
  --format json
```

Preview cleanup, then complete:

```bash theme={null}
pscale branch vtctld move-tables complete mydb main \
  --org acme \
  --workflow commerce2customer \
  --target-keyspace customer \
  --keep-data=false \
  --keep-routing-rules=false \
  --dry-run \
  --format json
```

## Need help?

Get help from [the PlanetScale Support team](https://planetscale.com/contact?initial=support), or join our [Discord community](https://pscale.link/community) to see how others are using PlanetScale.
