New: Supaflow Claude Plugin -- let Claude create, edit, and monitor your data pipelines. Try the plugin

MYSQL → SNOWFLAKE

MySQL to Snowflake

Replicate MySQL tables into Snowflake without paying again when a backfill touches rows you already loaded.

Choose the tables and columns to load, run the first snapshot, then use a date, datetime, or timestamp column for bounded incremental windows. A configurable lookback of up to 86,400 seconds re-reads late writes, while explicit mappings protect MySQL booleans, unsigned integers, sets, and local datetimes on the Snowflake load path. Every connector is included on every Supaflow plan — you pay only for the compute your pipelines consume.

Used by data teams moving operational MySQL tables into Snowflake without binary-log infrastructure or Monthly Active Row pricing — with no per-row fees.

Need the full setup sequence? Read the step-by-step MySQL to Snowflake guide.

What the MySQL to Snowflake connector does

Every row below is an actual capability in the MySQL connector, not a forward-looking promise.

MySQL to Snowflake capability matrix — connector features, how each works, and known limits
FeatureHow it worksLimit / caveat
Table discovery and scopeSupaflow discovers tables, columns, primary keys, and types from the configured MySQL database. Original table and column names are preserved through extraction.Each source targets one database. Views are not exposed; create another source for each additional database.
Bounded incremental windowsFor a selected date, datetime, or timestamp cursor, each run reads a closed lower bound and open upper bound: `[previous cutoff, current cutoff)`. The saved cutoff becomes the next run's lower bound.The initial cursor anchor is January 1, 2000. Use full refresh for older records. This is not binary-log CDC, so hard deletes require an explicit source signal or reconciliation.
Late-write lookbackSet `lookbackTimeSeconds` from 0 to 86,400. Supaflow shifts the next lower bound backward by that amount so rows written slightly out of order are read again.Merge on a stable primary key so rows re-read inside the lookback window update instead of duplicating.
MySQL numeric and boolean types`TINYINT(1)` is discovered through `information_schema` and emitted as JSON booleans. `BIGINT UNSIGNED` maps to `DECIMAL(20,0)` so values above signed 64-bit range keep their precision.If `TINYINT(1)` metadata inspection fails, the connector warns that affected columns may be discovered as integers.
Date and time handlingEvery MySQL connection runs `SET time_zone = '+00:00'`. `DATE` remains a date, while MySQL `DATETIME` and `TIMESTAMP` fields are represented as local datetimes on the connector contract.MySQL and its Python driver do not preserve an original named timezone on these values; validate source columns whose meaning depends on a local business timezone.
`SET` and identifier handlingMySQL `SET` values are converted from Python sets to sorted arrays before JSONL serialization. Legal identifiers containing literal double underscores stay unchanged through extraction.Snowflake still applies its normal case-folding rules to unquoted destination identifiers.
Schema refresh controlSchema metadata refresh defaults to 60 minutes. Set it to `0` to refresh before every pipeline execution or `-1` to disable automatic refresh for a static schema.New tables and columns are selectable only after the source schema refreshes.

Why Supaflow for MySQL to Snowflake

Every connector included, usage-based pricing

Every Supaflow connector is included on every plan at no extra cost. You pay only for compute consumed, measured in Supaflow Credits (1 credit = 1 compute-hour on a Small node). No per-row fees.

Cursor windows with a late-write safety net

Each run has an explicit start and cutoff instead of an unbounded “greater than last value” query. Add up to 86,400 seconds of lookback when application writes arrive out of order, then merge on the source primary key in Snowflake.

MySQL values reach Snowflake in loadable shapes

`TINYINT(1)` becomes a JSON boolean, unsigned 64-bit integers keep 20 digits of precision, and `SET` values become deterministic sorted arrays. These conversions happen before the JSONL load path rather than after a Snowflake cast fails.

4 MySQL quirks that break naive pipelines

Every one of these is something our connector handles specifically. A generic pipeline built in Airflow or a basic ELT tool will hit at least three of them in production.

Quirk 1

`TINYINT(1)` arrives as `0` or `1`, not JSON boolean

Failure mode: The MySQL driver can return a boolean-shaped `TINYINT(1)` as an integer. Snowflake rejects an integer variant when loading it into a BOOLEAN column.

Evidence: The connector queries `information_schema.COLUMNS` for `COLUMN_TYPE LIKE 'tinyint(1)%'`, pins the field to boolean, and converts integer values with `bool(value)` before JSONL emission.

Fix: Supaflow emits JSON `true` or `false` so the Snowflake BOOLEAN load does not depend on an implicit cast.

Quirk 2

`BIGINT UNSIGNED` exceeds the signed 64-bit ceiling

Failure mode: MySQL allows unsigned values up to 18,446,744,073,709,551,615. A signed 64-bit destination tops out at 9,223,372,036,854,775,807.

Evidence: The connector detects the unsigned MySQL BIGINT dialect type and assigns decimal precision 20 with scale 0.

Fix: Supaflow lands the value as `DECIMAL(20,0)` instead of truncating it or rejecting the row as an overflowing integer.

Quirk 3

MySQL `SET` values are not JSON serializable

Failure mode: SQLAlchemy returns MySQL `SET` values as Python set objects, which a JSON encoder cannot serialize directly and whose order is not stable.

Evidence: The MySQL row coercion hook detects `set` values and replaces them with `sorted(value)` before normalization.

Fix: Supaflow emits a deterministic JSON array so the same source value has the same load shape on every run.

Quirk 4

Session time zones can move timestamp boundaries

Failure mode: A MySQL session using a host-dependent timezone can compare a timestamp cursor against a cutoff differently across environments.

Evidence: The connector adds `init_command=SET time_zone = '+00:00'` to every PyMySQL connection and uses typed values for both window bounds.

Fix: Supaflow pins the source session to UTC before discovery and reads so incremental cutoff comparisons remain consistent across runs.

How it works

1

Create a read-only MySQL user

Grant `SELECT` on the database or specific tables, then allow the Supaflow network path to reach the MySQL host and port.

MySQL source docs
2

Connect Snowflake

Choose the Snowflake warehouse, database, schema, and role that will receive the MySQL tables.

Snowflake destination docs
3

Select tables and sync behavior

Use full refresh for small or static tables. For incremental tables, select a reliable date, datetime, or timestamp cursor and set lookback when writes can arrive late.

4

Run and validate

Start the first snapshot, review per-table row counts, and compare primary-key counts and important numeric totals in MySQL and Snowflake.

Step-by-step replication guide

Frequently asked questions

How does Supaflow replicate MySQL tables to Snowflake?

Supaflow discovers tables in one configured MySQL database and loads the selected columns into Snowflake. Use full refresh when records predate January 1, 2000; otherwise a date, datetime, or timestamp cursor can drive bounded incremental windows when the table exposes a reliable change marker.

Does the MySQL source use binary-log CDC?

No. The connector does not read MySQL binary logs and does not capture hard deletes. It uses full refresh or cursor-based incremental reads; model deletes explicitly in a source column or use a periodic reconciliation when delete awareness is required.

How does Supaflow handle late-arriving MySQL writes?

Set the incremental lookback from 0 to 86,400 seconds. Each run shifts its lower bound backward by that amount and re-reads the overlap; use merge with a stable primary key so the repeated rows update instead of duplicating.

Which MySQL objects can I load into Snowflake?

The connector discovers tables in the configured database and preserves their columns and primary-key metadata. It does not expose views, and one source cannot span multiple MySQL databases; create a separate source for each database.

How are MySQL-specific types loaded into Snowflake?

`TINYINT(1)` values become JSON booleans, `BIGINT UNSIGNED` maps to `DECIMAL(20,0)`, and `SET` values become sorted arrays. Dates and local datetimes keep typed representations; validate columns whose business meaning depends on a named timezone.

How is pricing different from Fivetran or Hevo for MySQL to Snowflake?

Fivetran and Hevo often price by Monthly Active Rows or changed-record volume, so a historical backfill or a large lookback window can increase the bill. Every Supaflow connector is included on every plan at no extra cost. You pay only for compute consumed, measured in Supaflow Credits (1 credit = 1 compute-hour on a Small node). No per-row fees. See the pricing page for the credit packages and free tier.

Can I self-host the MySQL to Snowflake pipeline?

Yes. Run the sync agent in your own VPC when the MySQL host is private or when credentials and row content need to stay inside your network. The control plane is managed; the data plane can be managed or self-hosted.

Replicate MySQL into Snowflake

Every connector is included on every Supaflow plan — you pay only for the compute your pipelines consume. Bounded cursor windows, up to 24 hours of lookback, MySQL-specific type handling, and table-level run visibility.