.cloning.yaml Reference
Understand the Clonio cloning configuration file format.
A .cloning.yaml file describes how Clonio transfers and anonymizes one source database. It is safe to commit because it stores a connection name, not credentials.
version: "1"
connection: production
options:
chunk_size: 1000
enforce_column_types: false
drop_unknown_tables: false
drop_extra_columns: false
recreate_tables: false
disable_foreign_key_checks: true
remap_keys: true
faker_locale: en_US
tables:
users:
rows:
strategy: full
clear: delete
columns:
email:
strategy: fake
faker_method: safeEmail
faker_arguments: []
Top-level fields
| Field | Required | Description |
|---|---|---|
version |
yes | Schema version. Must be "1". |
connection |
yes | Source connection name from clonio.json. |
options |
yes | Global transfer and schema settings. |
tables |
yes | Per-table transfer rules. |
Options
| Field | Description |
|---|---|
chunk_size |
Rows fetched and inserted per batch. |
enforce_column_types |
Add source columns missing from the target. |
drop_unknown_tables |
Drop target tables absent from the source. |
drop_extra_columns |
Drop target columns absent from the source. Destructive. |
recreate_tables |
Optional, default false. Drop each selected table that already exists on the target and re-create it from the source schema. Destructive. See "Recreating drifted tables" in Dry Runs and Schema Sync. |
disable_foreign_key_checks |
Disable target FK checks during transfer where supported. |
remap_keys |
Optional, default true. Set to false to skip key remapping while keeping its definition. |
faker_locale |
Faker locale for fake strategies, such as en_US or de_DE. |
Table names
Table names under tables, in skip:, in key_remapping (the remapped table and each foreign_keys table) and in the --skip-tables / --only-tables flags resolve to source tables like this:
- A name that matches a source table exactly means that table.
- Otherwise, a name that matches exactly one source table when case is ignored means that table.
Usersresolves tousers. - A name that matches several source tables when case is ignored (the source has both
usersandUsers) stops the run with exit code4. Use the exact name. - A name that matches no source table is kept as written. A
tablesentry is then reported asnot_found.
Two tables keys that resolve to the same table (users and Users with only users in the source) also stop the run with exit code 4. The same goes for two key_remapping entries that resolve to the same table, and for a key_remapping entry whose table resolves to a table without a tables entry.
Table patterns
A tables key or a skip: entry written as /pattern/flags is a regular expression (PHP PCRE syntax). It stands for every source table whose name matches it. Quote the key in single quotes so YAML keeps it as written:
tables:
'/^logs_\d{4}$/':
rows:
strategy: last
limit: 1000
sort_by: id
columns:
ip_address:
strategy: "null"
users:
rows:
strategy: full
skip:
- '/^tmp_/'
-
The pattern matches the table name as written, so case counts. Add the
iflag to ignore case:'/^logs_/i'. Anchor it with^and$when it should match the whole name. -
A pattern key becomes one entry per matching table, in source schema order. Its
rowssettings apply to each of them. A column rule applies only to the matching tables that have that column, so one pattern can carry rules for columns some tables lack. -
Each table may match only one
tablesentry. A table that a pattern and a name both match, or that two patterns match, stops the run with exit code4before anything is copied:Table "logs_2024" matches more than one tables: entry: "/^logs_/" and "logs_2024". Each table may match only one entry.To give one table its own settings, leave it out of the pattern, for example with a negative lookahead:tables: '/^logs_(?!critical$)/': rows: strategy: last limit: 1000 sort_by: id logs_critical: rows: strategy: full -
A
skip:pattern skips the configured tables it matches (the tables yourtablesentries resolve to). Tables without atablesentry are not copied anyway. -
A pattern that matches no table prints
Warning: table pattern "/^ghosts_/" matches no table, also with--ci, and is logged astable_pattern_unmatched. The run goes on. A pattern key that matches nothing adds no table, so it is not reported asnot_found. -
A pattern that is not a valid regular expression is a validation error (exit code
4). -
key_remappingneeds table names: a pattern as akey_remappingtable orforeign_keystable, and astrategy: remappingcolumn under a pattern key, are validation errors. -
--skip-tablesand--only-tablestake table names only. A comma inside a pattern would split it, so a flag value that starts with/is a validation error.
Glob patterns such as logs_* are not supported for table names; use '/^logs_/'.
Row strategies
| Strategy | Description |
|---|---|
full |
Copy all rows. |
first |
Copy the first limit rows ordered by sort_by or primary key. |
last |
Copy the last limit rows ordered by sort_by or primary key. |
schema |
Create the table on the target but copy no rows. rows.clear is still honoured. |
skip |
Leave the table out completely: no schema sync, no rows. Tables with a foreign key to a skipped table are skipped too. |
rows.clear can be false, delete, or truncate.
Schema-only tables
Use schema for tables whose structure the application needs but whose rows are transient or sensitive: cache, sessions, queues, password reset and API tokens, debug logs. cloning:dump suggests it for known framework tables.
tables:
sessions:
rows:
strategy: schema
clear: delete # optional: empty existing target rows
Unlike skip, schema does not cascade: tables that reference a schema-only table are still copied, and their foreign key values point to rows that do not exist on the target. cloning:run adds a note to the table result, and inserts fail when foreign key checks are enabled (disable_foreign_key_checks: false). first/last with limit: 0 is rejected; use schema instead.
PostgreSQL partitioned tables
Clonio treats a partitioned table as one table. Reading it returns the rows of all its partitions, so the partitions themselves are not listed: cloning:dump leaves them out, and a tables: entry for a partition (e.g. events_2026) is reported as not_found. Configure the parent table (events) instead. Its rows and columns rules apply to the rows of every partition.
When Clonio creates the table on the target, it creates a plain, non-partitioned table with the parent's columns. To keep partitioning on the target, create the partitioned table and its partitions there yourself (for example with your migrations) and keep the default recreate_tables: false: an existing target table is kept as it is. Rows inserted into the parent are then routed to the matching partition.
Columns
Only list columns that need transformation. Unlisted columns are kept as-is.
columns:
email:
strategy: fake
faker_method: safeEmail
faker_arguments: []
See Anonymization Strategies for strategy details.
To leave a column out of the transfer entirely, use strategy: exclude. Generated columns are detected and left out automatically.