MySQL to ClickHouse: The Complete Replication Guide

Intergalactic Data Labs
โ
โ
12 min read
As of October 2026 there are four workable ways to replicate MySQL to ClickHouse. ClickHouse can read MySQL through its table engine, ClickHouse Cloud can stream the binlog with ClickPipes, or Debezium can relay changes through Kafka. A replication tool such as Filament, PeerDB, Airbyte, or Estuary can also copy tables on a schedule. What decides between them is deletes, where ClickHouse runs, and the cost unit.
Approach | Deletes land | Works on | Cost unit |
|---|---|---|---|
MySQL table engine | No copy at all | Cloud and self-hosted | ClickHouse compute |
ClickPipes MySQL CDC | Yes, from binlog | ClickHouse Cloud only | Per GB plus compute hours |
Debezium plus Kafka | Partly, sink skips deletes | Cloud and self-hosted | Your Kafka stack |
Batch or incremental tool | Only on full reload | Cloud and self-hosted | Rows, GB, credits, or free |
What decides a MySQL to ClickHouse replication setup?
Five constraints settle this job before any tool comes into it.
Deletes. MySQL analysts delete rows all the time, and ClickHouse has no cheap row-level delete. A lightweight DELETE "is implemented as a mutation that marks rows as deleted but does not immediately physically delete them," per the ClickHouse docs. Only binlog readers see a delete at all, and even they miss cascading deletes, which MySQL does not write to the binlog, as the ClickPipes FAQ notes.
Duplicates. Every upsert path lands on ReplacingMergeTree, and the engine docs are blunt that "Data deduplication occurs only during a merge. Merging occurs in the background at an unknown time, so you can't plan for it." Dashboards either query with FINAL or tolerate duplicates.
Binlog hygiene. Any log-based path needs binlog_format set to ROW, which the MySQL 8.4 manual confirms is the default, plus binlog_row_image set to FULL and retention that outlasts the initial snapshot. MySQL keeps logs for 30 days by default, while Amazon RDS defaults to zero hours, per the Airbyte MySQL docs.
Where ClickHouse runs. ClickPipes and the Fivetran destination work only against ClickHouse Cloud. Self-hosted clusters need a tool that speaks the native protocol.
Cost shape. The managed paths bill per gigabyte or per row. The self-hosted tools cost nothing but compute.
How can you replicate MySQL to ClickHouse?
Every tool that runs this exact route today sits in the table below. Hevo, Stitch, and OLake read MySQL but have no ClickHouse destination, so they are out. MaterializedMySQL, the old in-engine replicator, "has been removed and is no longer available" since ClickHouse 25.1, per the changelog.
Tool | MySQL modes | ClickHouse target | License | Pricing unit |
|---|---|---|---|---|
MySQL table engine | Live read-through | Any | ClickHouse core | Compute |
ClickPipes | Bulk and binlog CDC | Cloud only | Managed | $0.20 per GB on CDC |
PeerDB | Binlog CDC and query | Self-hosted and Cloud | AGPLv3 file | Self-hosted |
Debezium plus Kafka sink | Binlog CDC | Any 23.3 or newer | Apache 2.0 | Self-hosted |
Airbyte | Full, incremental, CDC | Any 21.8 or newer | ELv2 | Credits or capacity |
Fivetran | Binlog CDC | Cloud only | Proprietary | Monthly active rows |
Estuary Flow | Binlog CDC | Self-hosted and Cloud | BSL | $0.50 per GB |
dlt | Query based | Any | Apache 2.0 | Free, dltHub paid |
Sling | Full, incremental, paid CDC | Any | GPLv3 | Pro token for CDC |
ingestr | Full, incremental, CDC | Any | FSL-1.1 | Free |
Filament | Full and incremental | Self-hosted and Cloud | Apache 2.0 | Free, alpha sink |
The MySQL table engine is the zero-infrastructure answer. It "allows you to perform SELECT and INSERT queries on data that is stored on a remote MySQL server," per the engine docs. The mysql() function page shows an INSERT SELECT with a max(id) predicate as a crude incremental copy. Only simple comparisons push down, nothing tracks updates or deletes, and every query scans the source.
ClickPipes is the managed answer and the one ClickHouse now recommends. The MySQL connector reached GA and started billing on September 1, 2026, per gigabyte moved plus compute per hour, per the billing page. It reads RDS, Aurora, Cloud SQL, self-hosted MySQL, and MariaDB, and it propagates added columns but not dropped ones, per the schema changes page. It requires ClickHouse Cloud.
PeerDB is the open-source engine under ClickPipes, which ClickHouse acquired in July 2024, per the acquisition post. Its connector matrix lists MySQL to ClickHouse with CDC and watermark replication. The LICENSE file is AGPLv3 even though the README badge says ELv2, and it ships as a Docker Compose stack with MinIO staging.
Debezium plus the ClickHouse Kafka Connect sink is the self-hosted streaming answer. The Debezium MySQL connector, on its 3.7 release since late September 2026, reads the binlog and emits row-level change events to Kafka. The ClickHouse sink ships with exactly-once semantics but states plainly that "Deletes aren't supported," so you map Debezium envelopes into ReplacingMergeTree yourself.
Airbyte runs the route with a certified MySQL source and a certified ClickHouse destination, per its metadata file. The destination uses ReplacingMergeTree for dedup, per the destination docs. Two documented limits matter. A column removed in MySQL is dropped with its history in ClickHouse, and on self-managed multi-replica clusters data lands only on the node that received the insert.
Fivetran reads the MySQL binlog from MySQL 5.5 onward, per its MySQL docs, and its ClickHouse Cloud destination went GA in May 2026, per the destination changelog. It writes SharedReplacingMergeTree tables versioned by _fivetran_synced and bills by monthly active rows. It does not support self-hosted ClickHouse or primary key changes.
Estuary Flow captures the binlog and "writes to ClickHouse natively, supports hard and soft deletes, and works with both self-hosted and ClickHouse Cloud deployments," per its materialization docs. Data movement costs $0.50 per GB plus a monthly connector fee, per the pricing page, and the platform is BSL licensed.
dlt reaches MySQL through its SQLAlchemy based sql_database source and supports every write disposition on ClickHouse, including an atomic EXCHANGE TABLES replace, per the destination docs. There is no MySQL binlog CDC, and JSON, time, and binary columns all land as text.
Sling runs full and incremental copies on the free CLI and puts MySQL binlog CDC behind a Pro Max token, per its change capture docs. ingestr does the same job in one Go binary with a mysql+cdc:// URI scheme, per its MySQL docs, under an FSL-1.1 license.
Where does Filament fit on this route?
Filament runs MySQL to ClickHouse as a scheduled full or incremental copy, and not as a change stream. Its ClickHouse sink is alpha on the connector roadmap, and the page is direct about the limit. "CDC and incremental delete are not supported because ClickHouse does not offer efficient row-level deletes for this sink." Galaxy builds Filament, so weigh what follows accordingly.
Measured against the five criteria above, it wins on four and concedes one.
Criterion | Filament on this route | Evidence |
|---|---|---|
Deletes | Full reload only | Sink page, no CDC or incremental delete |
Duplicates | Replace mode sidesteps them | Atomic EXCHANGE TABLES at commit |
Binlog hygiene | Not needed for full or incremental | Query-based reads with keyset paging |
Where ClickHouse runs | Self-hosted and Cloud, native protocol | TLS on by default, LZ4 compression |
Cost shape | Apache 2.0, no pricing page | Runs as a binary, Go library, or Helm chart |
Deletes are the concession. If rows must vanish from ClickHouse within seconds of leaving MySQL, use ClickPipes, Estuary, or PeerDB. Filament's incremental mode pages by an updated_at cursor, and the replication modes guide says such a route "cannot see a hard delete."
Replace mode is the strength. The sink loads each table into a staging table and swaps it in with an atomic EXCHANGE TABLES at commit. "Failed replace runs leave the destination exactly as it was," per the sink page. A nightly rebuild of a 50 million row orders table never shows readers a half-loaded table and never leaves duplicate keys behind.
The read side is built for big InnoDB tables. The MySQL source splits a table into as many as 64 primary key ranges and saves the last key so an interrupted read resumes. Each incremental run is bounded at a high watermark inside a consistent snapshot. Before every write the pipeline computes a CRC32-C checksum over the batch and fails the run on a mismatch, per the integrity guide.
There is no public benchmark for this route. The benchmark overview lists six measured routes and none end in ClickHouse, so this guide makes no speed claim.
How to replicate MySQL to ClickHouse with Filament
The walkthrough below uses the local context, which "needs no external services" and runs in process with SQLite, per the CLI guide.
Install the CLI. One command installs the binary, per the installation page.
Prepare MySQL. Filament needs MySQL 8.0 or newer, and full and incremental reads need only SELECT. For incremental reads add an index that starts with the cursor column to avoid a filesort.
Prepare ClickHouse. The sink authenticates against the default database and creates the destination database from there, so grant the user access to both.
Declare the source, sink, and pipeline. The docs show no MySQL to ClickHouse example, so this file is assembled from the documented keys on the source and sink pages.
Validate and run. The CLI "applies it when it changes and creates or updates the declared connections and pipelines," per the CLI guide.
Switch to incremental once the first load is in. Change sync_mode to incremental and write_mode to upsert. The first incremental run captures a watermark and backfills by primary key, and later runs page by the compound watermark. The sink then creates ReplacingMergeTree tables, so read them with FINAL. Add a per-resource lookback if late commits are common, since upsert re-reads the overlap safely.
Schedule it. A pipeline carries one schedule with a cron expression, an IANA timezone, and an overlap policy of SKIP or ALLOW, per the pipelines API. Set it in the web UI or SDK once the pipeline runs on the Helm chart, which the Kubernetes guide covers, and run exactly one control-plane replica.
Which option fits which job?
Pick by the constraint that breaks first.
Job | Pick | Why |
|---|---|---|
Nightly rebuilt analytics tables, any ClickHouse | Filament | Atomic replace, parallel reads, no metered bill |
Hourly fresh tables where deletes can wait for a reload | Filament or dlt | Incremental upsert on a cron |
Deletes within seconds on ClickHouse Cloud | ClickPipes | Managed binlog CDC with GA support |
Deletes within seconds on self-hosted ClickHouse | Estuary or PeerDB | Native writes with delete handling |
Kafka already in production | Debezium plus Kafka sink | Reuse the bus, map deletes yourself |
Small lookup tables, no copy wanted | MySQL table engine | Zero infrastructure |
Many SaaS sources alongside MySQL | Airbyte or Fivetran | Breadth of catalog |
Filament is the pick for the engineer who owns both databases, rebuilds or upserts analytics tables on a schedule, and wants no gigabyte meter and no Kafka. ClickPipes wins once sub-minute deletes on ClickHouse Cloud are the requirement, and Estuary or PeerDB win that requirement on a self-hosted cluster.
Related guides
The Postgres to ClickHouse replication guide covers the same sink from the other common source.
The MySQL to Snowflake replication guide and the MySQL to Postgres migration and replication guide cover the same source into sinks that do accept CDC.
MySQL CDC and binlog replication explained goes deep on the binlog settings every log-based path needs.
Full load vs incremental vs CDC and the complete guide to change data capture explain the modes behind every row of the tables above.
Introducing Filament is the announcement post.
Frequently asked questions
What is the best way to replicate MySQL to ClickHouse?
It depends on whether you need deletes. ClickPipes on ClickHouse Cloud and Debezium through Kafka replay the MySQL binlog, so they carry deletes. Batch tools such as Filament, Airbyte, dlt, and Sling copy whole tables or page by an updated_at cursor, which is cheaper to run but cannot see a hard delete without a full reload.
Does ClickHouse support native MySQL CDC?
Only on ClickHouse Cloud. The MySQL ClickPipe reached general availability in September 2026 and streams binlog changes from RDS, Aurora, Cloud SQL, self-hosted MySQL, and MariaDB. The old MaterializedMySQL database engine for self-hosted servers was removed in ClickHouse 25.1, so self-hosted users need an external tool.
Can ClickHouse query MySQL without copying the data?
Yes. The MySQL table engine and the mysql() table function run SELECT statements against a remote MySQL server on every query. Only simple comparison predicates are pushed down, so each query costs MySQL a scan, which makes this fine for small lookup tables and wrong for analytics on large ones.
Do I need Kafka to move MySQL data to ClickHouse?
No. Kafka is only required for the Debezium path, where the MySQL connector writes change events to topics and the ClickHouse Kafka Connect sink reads them. ClickPipes, PeerDB, Airbyte, Fivetran, Estuary, Filament, dlt, Sling, and ingestr all connect MySQL to ClickHouse without a message bus in between.
Why do my ClickHouse queries need FINAL after replication?
Every tool that writes upserts to ClickHouse uses ReplacingMergeTree, and that engine removes duplicate keys only when parts merge in the background. Until a merge runs, a key can have several rows. Adding FINAL to the SELECT collapses them at query time at the cost of extra work per query.
What MySQL settings does binlog replication need?
The server needs binlog_format set to ROW, binlog_row_image set to FULL, and binlog retention long enough to cover the initial snapshot. Retention defaults to 30 days on MySQL but to zero hours on Amazon RDS. The replication user needs the REPLICATION SLAVE and REPLICATION CLIENT privileges. GTID mode is optional but survives failover.
Does Filament replicate MySQL to ClickHouse with CDC?
Not today. Filament reads the MySQL binlog for sinks that can apply row-level deletes, but its ClickHouse sink supports full replace, full append, and upsert modes only. Pick it when a scheduled full or incremental copy is what you want, and pick a log-based tool when deletes must land in ClickHouse within seconds.
How does Filament handle duplicate rows in ClickHouse?
Upsert modes create a ReplacingMergeTree table keyed on the source primary key, so repeated rows from a resumed run converge by key once parts merge. Replace mode avoids the question entirely by loading into a staging table and swapping it in with one atomic EXCHANGE TABLES at commit.
More articles
Questions
Answered
FAQ
What does Galaxy do?
What is Filament?
What is enterprise context management?
What does working with Galaxy look like?
How do you handle security and compliance?
Why does Galaxy build in the open?
Company
Copyright ยฉ 2026 Galaxy. All rights reserved.