Data migration configuration reference¶
This page documents the workflow YAML and Worker TOML settings for Data Migration. For platform-specific prerequisites, auth methods, extraction strategies, and data type mappings, see the per-platform pages linked from Data migration.
Tip
If you use the Snowflake AIM Agent for Data Warehouses instead of hand-editing these files, see Data migration advanced configuration for common scenarios and the prompts that generate and adjust this configuration for you.
For SnowConvert AI CLI commands that generate and submit these configs, see Data migration.
Workflow configuration reference¶
The Data Migration Workflow configuration file is a YAML file. The CLI and Snowflake AIM Agent for Data Warehouses accept .yaml or .yml files.
Note
Names that require quoting (or brackets) must be manually quoted. For example: tableName: "\"MyCaseSensitiveTable\"".
Top-level object¶
| Property | Type | Required | Description |
|---|---|---|---|
schemaVersion | String | Version of the configuration schema (for example, "1.0.0"). Accepts major, major.minor, or major.minor.patch. Defaults to "1.0.0" when omitted. | |
tables | TableConfiguration[] | Yes | An array of table-specific configurations defining which tables to migrate and how. Must contain at least one entry. |
defaultTableConfiguration | TableConfiguration | Shared settings inherited by all tables in the tables array. Table-specific values override these defaults. | |
affinity | String | Optional affinity tag that routes this workflow’s tasks to matching Workers. See Affinity. | |
intervalHandling | String ("interval", "varchar") | Default handling for source INTERVAL columns across all tables. Defaults to "interval". See INTERVAL data type handling. |
When defaultTableConfiguration is present, each object in tables is merged with those defaults: shared fields apply to every table unless the same field is set again on a specific table entry.
TableConfiguration model¶
Defines the settings for migrating a single table.
| Property | Type | Required | Description |
|---|---|---|---|
source | SourceTargetIdentifier | Identifies the source table. | |
target | SourceTargetIdentifier | Identifies the target table in Snowflake. | |
columnNamesToPartitionBy | String[] | Columns used to partition data during extraction. Can be omitted and inferred automatically. See Automatic partition key selection. | |
extraction | ExtractionStrategy | How data is extracted from the source database. | |
synchronization | SynchronizationStrategy | Settings for incremental synchronization. | |
columnTypeMappings | ColumnTypeMapping | Type conversions applied during migration. | |
columnNameMappings | ColumnNameMapping | Column renaming mappings. | |
primaryKeyColumns | String[] | Primary key columns. Required for trackModifications or trackDeletions under the watermark synchronization strategy. Can be omitted and inferred automatically at runtime. See Automatic partition key selection. | |
targetPartitionSizeMb | Integer | Target partition size in MB. Mutually exclusive with targetPartitionSizeRows. Must be greater than 0. When both are omitted, the orchestrator picks sizes automatically. See Partition size. | |
targetPartitionSizeRows | Integer | Target partition size in rows. Mutually exclusive with targetPartitionSizeMb. Must be greater than 0. When both are omitted, the orchestrator picks sizes automatically. See Partition size. | |
whereClauseCriteria | String | SQL-like filter to select a subset of rows (for example, "is_deleted = 0"). | |
loadSegmentation | LoadSegmentation | Splits a single COPY INTO into multiple parallel statements, each targeting a subset of staged files. Useful when many files are staged for one partition (common with Redshift UNLOAD). See Load segmentation. | |
queryModifiers | QueryModifiers | Optional SQL hints appended to source queries to reduce locking on busy source tables. Default is unset (no hints). See Anti-locking and query modifiers. | |
intervalHandling | String ("interval", "varchar") | Per-table override of the workflow-level intervalHandling setting. See INTERVAL data type handling. |
QueryModifiers model¶
| Property | Type | Description |
|---|---|---|
objectModifier | String | Text appended after the source table in the FROM clause (for example " WITH (NOLOCK)" on SQL Server). |
selectModifier | String | Token inserted immediately after SELECT (for example an Oracle optimizer hint). Use "NONE" to disable Oracle’s automatic parallel hint. |
SourceTargetIdentifier model¶
| Property | Type | Required | Description |
|---|---|---|---|
databaseName | String | Source or target database name. | |
schemaName | String | Schema containing the table. | |
tableName | String | Table to migrate. |
Additional target properties¶
The following optional fields apply only to the target object.
| Property | Type | Required | Description |
|---|---|---|---|
tableType | String | "native" for a standard Snowflake table (default) or "iceberg" for an Apache Iceberg™ table. | |
icebergConfig | Object | For Iceberg targets | Required when tableType is "iceberg". See Iceberg configuration. |
Iceberg configuration (target.icebergConfig)¶
Used when target.tableType is "iceberg". Account setup follows Snowflake’s Apache Iceberg™ tables documentation.
| Property | Type | Required | Description |
|---|---|---|---|
catalog | String | Default SNOWFLAKE for Snowflake-managed Iceberg. Use a catalog integration name for externally cataloged tables. | |
externalVolume | String | For catalog SNOWFLAKE | Snowflake external volume for Iceberg data and metadata. |
baseLocationPrefix | String | Optional path prefix for BASE_LOCATION. | |
catalogTableName | String | For external catalog | Fully qualified name in the external catalog. |
catalogSync | String | Optional catalog integration to sync Snowflake-managed metadata back to an external catalog. | |
sourceDataStage | String | Stage path starting with @ pointing at existing Parquet files. | |
migrationStrategy | String | One of catalog_link, convert_to_managed, or copy_files. |
Note
Iceberg targets don’t support a native INTERVAL type. Source INTERVAL columns are coerced to VARCHAR regardless of intervalHandling. See INTERVAL data type handling.
Partition size¶
Partition size is controlled at the TableConfiguration level with two flat, mutually exclusive fields: targetPartitionSizeMb and targetPartitionSizeRows. When both are omitted, the orchestrator uses auto sizing.
| Form | Description |
|---|---|
| Both omitted (default) | Auto. The orchestrator chooses partition sizes from the source platform, extraction strategy, and table size. |
targetPartitionSizeMb: N | Each partition targets about N megabytes of data. Must be greater than 0. |
targetPartitionSizeRows: N | Each partition targets N rows, regardless of data size. Must be greater than 0. |
Specify at most one of the two fields; setting both on the same table is a configuration error.
Automatic partition key selection¶
When columnNamesToPartitionBy (and, for incremental sync, primaryKeyColumns) is omitted for a table that needs partitioning, AIM DMV infers a key automatically from source catalog metadata rather than scanning the full table sequentially:
- Clustered, sort, or distribution key columns, when the source platform exposes one.
- A unique index, when no clustering key is available.
- The first non-boolean column in the table’s schema, as a last-resort fallback. Boolean columns are never selected because they don’t provide enough distinct values to split partitions evenly.
Inferred keys are cached per source table and reused by later workflows against the same table, so inference runs only once per table. A manually specified columnNamesToPartitionBy (or primaryKeyColumns) always takes precedence over an inferred key.
Note
Automatic key selection applies to tables. Views don’t expose the catalog metadata needed for inference, so you must set columnNamesToPartitionBy explicitly when migrating a view.
Set columnNamesToPartitionBy explicitly when you know a better partitioning column than the one AIM DMV would infer, or when a fallback selection (such as a non-unique first column) would create unevenly sized partitions.
Each configured name must be a real, physical column in the source table. Persisted computed columns (SQL Server) and virtual columns (Oracle) qualify. Bare SQL expressions, pseudo-columns (for example Oracle ROWID, ROWNUM, or ORA_ROWSCN), and hidden system columns are not valid: AIM DMV quotes partition key names as identifiers in ORDER BY and range predicates, so those values won’t resolve. To partition on a derived value, add a persisted or virtual computed column on the source and reference that column name.
Note
Pseudo-columns and system columns can be used as watermark columns for incremental sync (for example Oracle ORA_ROWSCN), but not as partition keys. See SynchronizationStrategy model.
Load segmentation¶
When a large number of files are staged for a single partition (common with Redshift UNLOAD), the orchestrator can split the COPY INTO into multiple parallel statements, each targeting a subset of files. All resulting statements fan in to the same successor task.
| Property | Type | Required | Description |
|---|---|---|---|
targetSegmentSizeMb | Integer | Yes | Target total file size (in MB) per COPY INTO segment. Must be greater than 0. |
When loadSegmentation is omitted, a single COPY INTO loads all files in the partition (the default). Files larger than the target size get their own segment, and Snowflake’s 1,000-file FILES limit is enforced per statement.
ExtractionStrategy model¶
| Field | Type | Required | Description |
|---|---|---|---|
strategy | String ("regular", "unload", "write_nos", "dbms_cloud", "tpt") | regular (default): Worker pulls data over the source connection. unload (Redshift only): Redshift UNLOAD writes Parquet to S3. write_nos (Teradata only): Teradata WRITE_NOS writes to cloud storage. dbms_cloud (Oracle only): Oracle DBMS_CLOUD.EXPORT_DATA writes Parquet to object storage. tpt (Teradata only): Worker runs TPT EXPORT via tbuild. | |
externalStage | String | See description | Required when strategy is unload, write_nos, or dbms_cloud. Snowflake external stage whose URL matches the bucket or container used for the server-side export. Not required for regular or tpt. |
pluginClass | String | Optional. Fully qualified class name of a custom extraction plugin to use instead of a built-in strategy. When set, the Worker’s [connections.source.*] TOML section still supplies connection details, but plugin_class in that section is the field actually read at runtime; this workflow field documents intent alongside the table configuration. |
See Extraction strategies for YAML examples and platform availability.
SynchronizationStrategy model¶
| Field | Type | Required | Description |
|---|---|---|---|
strategy | String ("none", "checksum", "watermark") | Synchronization method. "none" (default) re-extracts fully on every run. | |
checksumExpression | String | checksum only. Custom SQL aggregate expression that returns a single value per partition (for example a row-version column or MAX(last_modified)). Only partitions whose value changed since the last run are cleared and re-extracted. When omitted, the default per-column hash is used. May reference pseudo-columns or system columns (for example MAX(ORA_ROWSCN) on Oracle). | |
watermarkColumn | String | watermark only | Monotonically increasing column name. May be a pseudo-column or system column not present in the migrated schema (for example Oracle ORA_ROWSCN). AIM DMV projects it into the extract for change detection but does not migrate it to the target. |
trackModifications | Boolean | watermark only. If true, uses the primary key to deduplicate modified rows after COPY INTO. Requires primaryKeyColumns. | |
trackDeletions | Boolean | watermark only. If true, extracts a full primary-key snapshot of each source partition on every incremental run and deletes target rows absent from the snapshot before loading new rows. Requires primaryKeyColumns. Independent of trackModifications; the two can be combined. |
Note
Oracle: synchronization.strategy checksum is not supported. Use none or watermark on Oracle projects.
Affinity¶
Affinity routes workflow tasks to specific Workers. Use it when you run more than one Worker pool and need each workflow to land on the right pool, for example SPCS Workers for one source and on-premises Workers for another, or separate pools per team.
Set affinity on the workflow YAML and the same value (or a matching wildcard) on the Worker:
- Workflow: top-level
affinityin the migration or validation YAML - Worker TOML:
[application].affinity - SPCS service:
AGENT_AFFINITYin the container environment
The string format is yours to define. Examples of valid values: sql-server, DEV_SERVER, onprem-redshift, ::blue::.
Matching rules:
- A task without affinity is picked up by any Worker.
- A Worker without affinity picks up any task.
- A task with a given affinity is not picked up by a Worker with a different affinity.
- A Worker affinity may include
*wildcards. For example, Worker affinityteam-*matches workflow affinitiesteam-blueandteam-red.
Validation workflows use the same affinity field and the same matching rules as migration.
INTERVAL data type handling¶
AIM DMV migrates source INTERVAL columns to a native Snowflake INTERVAL target by default, extracting each value as Snowflake-parseable text and loading it with an explicit cast. Set intervalHandling at the workflow root, defaultTableConfiguration, or on an individual table to control this behavior.
| Value | Behavior |
|---|---|
"interval" (default) | Migrate to a native Snowflake INTERVAL column. |
"varchar" | Migrate the column as text (VARCHAR) instead of a native interval. |
Neither option is universally better. On source platforms whose interval type can mix year-month and day-time fields in one value (for example PostgreSQL), "interval" maps the column to Snowflake INTERVAL DAY TO SECOND and folds the year-month part into day-time (via total seconds on PostgreSQL). That keeps a native interval column but loses calendar-accurate year-month precision. Choose "varchar" to preserve the original interval text instead. See INTERVAL columns and intervalHandling on the PostgreSQL migration page for the tradeoff.
Iceberg targets always coerce INTERVAL columns to VARCHAR, regardless of intervalHandling, because Iceberg has no native interval type. See platform-specific notes on the Migrating Data from … pages for interval support by source platform.
Extraction strategies¶
Each table can set extraction.strategy (or inherit from defaultTableConfiguration.extraction). Worker TOML holds connection and platform-specific options (UNLOAD credentials, WRITE_NOS location, TPT tuning).
| Strategy | Platforms | When to use |
|---|---|---|
unload | Redshift only | Recommended default when S3 and a Snowflake external stage are available. Redshift writes Parquet to S3; Snowflake loads from the external stage. Use for all tables from the source. See Migrating Data from Amazon Redshift. |
write_nos | Teradata only | Recommended default when Teradata NOS and a Snowflake external stage are available. Server-side export to S3, Azure Blob, or GCS. Use for all tables from the source. See Migrating Data from Teradata. |
dbms_cloud | Oracle only | Recommended default when object storage and a Snowflake external stage are available. Server-side export via DBMS_CLOUD.EXPORT_DATA. Use for all tables from the source. See Migrating Data from Oracle. |
regular (default) | All | Worker pulls data over ODBC, BCP, Npgsql, or Teradata drivers, then uploads to the Snowflake internal stage. Use when volume is genuinely small, or when server-side export prerequisites aren’t in place yet. |
tpt | Teradata only | Worker-side bulk export via Teradata Parallel Transporter when WRITE_NOS isn’t available. See Migrating Data from Teradata. |
Regular (default):
Redshift unload:
Teradata write_nos:
Oracle dbms_cloud:
Teradata tpt:
Worker configuration¶
The Worker configuration file uses TOML (https://toml.io/) format. For cloud data migration, set selected_task_source to "snowflake_stored_procedure" and provide a matching [task_source.snowflake_stored_procedure] section.
| Section | Property | Type | Description |
|---|---|---|---|
| Top level | selected_task_source | String | Required. Use "snowflake_stored_procedure". |
[task_source.snowflake_stored_procedure] | connection_name | String | Snowflake connection name for task-queue stored procedures, or "@SPCS_CONNECTION" on SPCS. |
[application] | max_parallel_tasks | Integer | Maximum parallel tasks (threads). |
[application] | task_fetch_interval | Integer | Seconds between idle polls for new tasks. |
[application] | lease_refresh_interval | Integer | Optional. Seconds between task lease renewals (default 120). |
[application] | affinity | String | Optional. Worker affinity for task routing. May include * wildcards. See Affinity. |
[application] | snowflake_database_for_metadata | String | Optional. Task-queue database (default SNOWCONVERT_AI). |
[application] | local_results_directory | String | Optional. Base directory for exported Parquet/CSV before upload. |
[connections.source.*] | (per engine) | Object | Source database connection. Typically one active source section. |
[connections.source.*] | plugin_class | String | Optional. Fully qualified class name of a custom extraction plugin that replaces the built-in extractor for this source connection. See Preparing a custom extraction plugin. |
[connections.target.snowflake_connection_name] | connection_name | String | Snowflake profile for data sessions (loads). |
Example minimal Worker config:
Platform-specific [connections.source.*] examples live on each Migrating Data from … page.
Using a custom extraction plugin¶
Set plugin_class on the source connection to replace the built-in extractor entirely. The Worker imports and runs your class in place of the regular (or other built-in) strategy for that connection:
See Preparing a custom extraction plugin for what the plugin must implement and how to package it.
Anti-locking and query modifiers¶
User-configured anti-locking hints are off by default. Unless you set queryModifiers, AIM DMV runs plain source queries. Modifiers apply to source queries only, never the Snowflake target.
Source platforms fall into two groups:
- MVCC / snapshot engines (Oracle, PostgreSQL, Amazon Redshift, and Snowflake itself): readers don’t block writers, so anti-locking hints aren’t needed.
- Lock-based engines (SQL Server and Azure Synapse): shared locks on reads can block or be blocked by production writers. Opt-in hints such as
WITH (NOLOCK)avoid blocking but use read-uncommitted semantics (dirty reads). AIM DMV never auto-applies these hints.
Teradata is a special case: AIM DMV prepends LOCKING ROW FOR ACCESS on every Teradata source scan automatically. This is Teradata’s native, safe row-access pattern (not a dirty read) and cannot be disabled.
Per-platform behavior¶
| Platform | Default behavior | How to customize |
|---|---|---|
| Teradata | LOCKING ROW FOR ACCESS added automatically on every source scan | Not configurable |
| SQL Server | No automatic hint | Set objectModifier: " WITH (NOLOCK)" on defaultTableConfiguration or per table |
| Oracle | Automatic PARALLEL optimizer hint on large tables | Override with selectModifier, or set selectModifier: "NONE" to disable |
| Amazon Redshift | No automatic hint | Opt-in pass-through via queryModifiers |
| PostgreSQL | No automatic hint | Opt-in pass-through via queryModifiers |
Pros and cons¶
| Pros | Source reads no longer block on or wait for locks held by production writers, so migration isn’t stalled by long-running source transactions. On Oracle, the parallel hint can speed large-table scans. |
| Cons | WITH (NOLOCK) (and equivalent read-uncommitted hints) allow dirty reads: scans can see uncommitted rows that later roll back, so migration can copy data that never committed. Many DBAs disallow NOLOCK. Custom modifier strings are passed through verbatim, so an invalid hint can cause source query errors. |
| Recommendation | Leave hints off unless source locking is actually blocking your workflow. When you do enable them, prefer running against a quiesced or low-write window. |
Workflow example¶
Set a default on defaultTableConfiguration and override per table when needed:
Worker TOML example¶
You can also set query modifiers in Worker TOML under the source connection:
Warning
WITH (NOLOCK) uses read-uncommitted semantics. Scans can read uncommitted rows that later roll back, so migrated data may not match what ultimately committed on the source.