MySQL to Snowflake replication that loads MySQL data into Snowflake on a schedule
The MySQL to Snowflake replication from Adapters loads MySQL tables into Snowflake on an incremental schedule, mapping MySQL types to Snowflake types and merging on the primary key so analysts query production data in the warehouse without a read replica or a hand-built pipeline. Field mapping is no-code, so try it against sample records in the live demo.
No credit card required.
Field mapping auto-plugged · tap a port to rewire
Plug a source port into
Transform on this cable
JSON in
JSON out
5 sample records ready
Last updated September 2026
What running MySQL to Snowflake by hand costs you
- Analysts querying the production MySQL replica slow down the application at exactly the wrong moment, usually month end.
- Hand-rolled load scripts re-import the same rows after a retry and every revenue number quietly doubles.
- MySQL DATETIME columns carry no timezone, so reports land hours off once the data sits next to UTC warehouse tables.
The field mapping, out of the box
These cables are pre-wired when you pick the pair. Rewire any of them, or add your own, in the same visual data mapping tool you use for every adapter.
Input / MYSQL
Output / SNOWFLAKE
Transforms included
Incremental runs use a MySQL updated_at watermark with a short lookback so late edits are caught; DECIMAL keeps its precision as Snowflake NUMBER, TINYINT(1) becomes BOOLEAN, unsigned BIGINT widens so ids survive, DATETIME and TIMESTAMP normalize to TIMESTAMP_TZ in UTC, JSON columns land as VARIANT so nested payloads stay queryable, identifiers fold to Snowflake uppercase, and loads MERGE on the primary key so a replayed batch updates instead of duplicating.
MySQL to Snowflake in depth
Two type systems that both look permissive and are permissive about different things, plus a binlog that gets purged sooner than anyone expects. Read from the MySQL 8.4 Reference Manual and Snowflake documentation, checked 31 August 2026.
Snowflake NUMBER defaults to (38,0) and silently drops the cents
Declare a Snowflake column as plain NUMBER and you get NUMBER(38,0), which has no scale at all. A MySQL DECIMAL(10,2) holding 42.50 lands as 42 or 43 depending on rounding, and no error is raised anywhere. Use NUMBER(18,2) for money, explicitly, on every load. This is the single most common way a MySQL to Snowflake pipeline reconciles on row count and fails on revenue.
Unsigned integers have no Snowflake equivalent either
MySQL BIGINT UNSIGNED reaches 18,446,744,073,709,551,615. Snowflake NUMBER maxes out at 38 digits of precision, so it can hold the value comfortably, which makes this easier than the PostgreSQL case. The trap is the opposite one: a connector that maps the column to a fixed-width integer type on the way past will still overflow. Map unsigned columns to NUMBER with enough precision and stop worrying about it.
Identifier case folds the opposite way from MySQL habits
Snowflake folds unquoted identifiers to UPPERCASE, where PostgreSQL and Redshift fold to lowercase. A MySQL schema full of lowercase table names arrives as ORDERS and CUSTOMERS, and any downstream query written against orders without quoting will still work, while a query that quotes "orders" will not find the table at all. Pick a convention before the first load rather than after the first broken dashboard.
Zero dates will not survive the trip
With strict mode disabled, the MySQL manual states that invalid dates such as 2004-04-31 are converted to 0000-00-00 and only a warning is generated. Those rows are sitting in plenty of long-running production databases. Snowflake has no such value. Count them on the source with a comparison against 1000-01-01 and decide whether they become NULL or get corrected, before the load rather than during it.
MySQL utf8 is three bytes, and the damage is already done
The MySQL utf8 character set is a deprecated alias for utf8mb3, the three byte encoding, which cannot store a four byte character at all. Emoji and extended CJK characters in a utf8 column were lost when they were written, not when they were replicated. Snowflake will happily accept whatever is there. Audit which columns use utf8mb3 so you know what the warehouse is missing rather than assuming the pipeline broke it.
File sizing decides the load cost
Snowflake recommends staged files of 100 to 250 MB compressed and explicitly does not recommend files of 100 GB or more. Snowpipe lands data within about a minute; the default COPY timeout is 24 hours. One enormous file loads serially on a single thread and wastes the warehouse you are paying for. Split the extract into the recommended range and the same warehouse finishes several times faster.
The binlog is the real deadline
Change capture reads the MySQL binary log, and managed MySQL services purge it aggressively to reclaim disk. Set binlog_format to ROW and binlog_row_image to FULL, then raise the retention well beyond the longest backfill you expect. If the pipeline stalls for longer than the retention window, the stream cannot resume and you are re-running a full load rather than catching up.
What we do about all of it
The mapping is declared once, per field, with the Snowflake type written down rather than inferred from a sample. Money columns carry an explicit precision and scale, unsigned columns carry enough digits, and the incremental run merges on the primary key so a replay cannot double-count. If you are moving MySQL to PostgreSQL instead of a warehouse, the type traps differ and are covered on our MySQL to PostgreSQL migration tools page.
How it goes live
Three steps, minutes end to end, covered by flat data integration pricing from $49 a month.
STEP 01
Pick the pair
Connect MySQL and Snowflake with scoped credentials. About a minute each.
STEP 02
Confirm the mapping
The cables above are pre-wired. Adjust any field, preview the transform on sample records, done.
STEP 03
Schedule the sync
Hourly down to every minute, with retries, alerting, and a full log on every run.
Prefer to understand the moving parts first? Our long-form guide to replicating MySQL to Snowflake covers the field-by-field detail, the failure cases, and what changes at volume.
MySQL to Snowflake sync: common questions
How do I replicate MySQL to Snowflake?
Backfill each table once from a read replica, then keep it current with incremental loads. Pick the change mechanism first: a reliable updated-at watermark is simple and sufficient for most tables, while binlog CDC catches hard deletes and rows updated without touching the timestamp. Land changes in a staging table and MERGE into the target on the primary key.
What is the MySQL to Snowflake data type mapping?
INT and BIGINT become NUMBER(38,0), DECIMAL becomes NUMBER with the same precision and scale, VARCHAR and TEXT become VARCHAR, and BLOB becomes BINARY. The ones to decide by hand are TINYINT(1), which MySQL uses for booleans and which should become BOOLEAN, unsigned BIGINT, which needs NUMBER(20,0) to hold its full range, DATETIME, which becomes TIMESTAMP_NTZ, TIMESTAMP, which becomes TIMESTAMP_TZ, and JSON, which becomes VARIANT.
Do you need CDC to sync MySQL to Snowflake?
Only if deletes matter or your rows change without updating a timestamp. A watermark on updated_at is simpler to run, has no binlog retention to manage, and covers most reporting tables. Choose CDC when the warehouse copy has to match the source exactly, including rows that were removed.
How do you avoid duplicate rows in Snowflake?
Never INSERT straight into the target. Load each batch into a staging table, deduplicate within the batch by primary key keeping the latest version, then MERGE into the target. That makes the whole load idempotent, so a retried or replayed run produces the same table rather than a second copy of every row.
How does the MySQL to Snowflake sync work?
The MySQL to Snowflake replication from Adapters loads MySQL tables into Snowflake on an incremental schedule, mapping MySQL types to Snowflake types and merging on the primary key so analysts query production data in the warehouse without a read replica or a hand-built pipeline. Field mapping is no-code, so try it against sample records in the live demo.
Is there a prebuilt MySQL connector for Snowflake?
Yes. This MySQL to Snowflake connector ships prebuilt: the field mapping is wired the moment you pick the pair, transforms are included, and you can try it against sample records in the live demo. No code or engineering sprint required.
How much does the MySQL Snowflake integration cost?
Pricing is flat and monthly: Starter at $49, Growth at $149, Scale at $399. Every plan includes this pair, visual field mapping, and per-record logs. There are no per-task or per-row fees, so the bill stays the same as volume grows.
How often can Adapters sync MySQL to Snowflake?
Hourly on Starter, every 5 minutes on Growth, and down to every minute on Scale. Failed records retry automatically with backoff, and alerting plus a full per-record log come standard on every run.
Do I need to write code to connect MySQL and Snowflake?
No. Fields are auto-mapped the moment you pick the pair, and you can rewire any mapping visually before the first sync. Incremental runs use a MySQL updated_at watermark with a short lookback so late edits are caught; DECIMAL keeps its precision as Snowflake NUMBER, TINYINT(1) becomes BOOLEAN, unsigned BIGINT widens so ids survive, DATETIME and TIMESTAMP normalize to TIMESTAMP_TZ in UTC, JSON columns land as VARIANT so nested payloads stay queryable, identifiers fold to Snowflake uppercase, and loads MERGE on the primary key so a replayed batch updates instead of duplicating.
More pairs from the API connector library
Browse the full api connector library, or request a pair you do not see.
MySQL and Snowflake, finally in agreement
Map the pair once and let it sync on schedule. Flat price from $49 a month, no per-task fees.
No credit card required.