MySQL to Convex: How to Move Your Data

Move MySQL into Convex with Airbyte. Why deletes propagate end to end with CDC, Convex table naming rules, and what short binlog retention breaks.

Summarize with AI:

Moving MySQL into Convex is not an analytics pipeline, and being clear about that first saves a wasted project. Convex is an application backend, so the reason to put relational data there is to power something users see: a feature that needs data currently locked in a legacy database, or a staged migration where the new application reads Convex while the old one still writes MySQL.

This guide covers the managed path with Airbyte. The pleasant surprise here is that both ends handle deletions properly, which is rarer than it should be: MySQL's change data capture reads the binary log, and the Convex destination supports replicating incremental deletes. Get the setup right and a row deleted in MySQL disappears from your application.

MySQL to Convex at a glance:

CapabilitySupportedWhat it means for this pipeline
Deletes end to endYesMySQL CDC captures them and Convex can replicate them
DirectionInto Convex onlyStreaming export from Convex via Airbyte is not supported
Table namesRestrictedLetters, digits and underscores, and no leading underscore
Sync modePrefer incrementalPerformance suffers with large, frequent full refresh syncs
Binlog retentionYou configure itToo short and the connection restarts from a full snapshot

Why move data from MySQL to Convex?

Two situations account for nearly all of these pipelines, and both are about building product rather than analysing it.

The first is a new feature over old data. You are building something in Convex and it needs customer records, catalogue data or entitlements that live in a MySQL database owned by another team or another era. Rather than opening a connection to that database from your new application, you replicate the slice you need.

The second is a migration in flight, where Convex becomes the read path while MySQL is still the write path, and traffic moves gradually. If instead you want to analyse this data alongside revenue or support, a warehouse is the right destination and putting analytical load on an application backend will be both awkward and expensive.

What do you need before you start?

Two of these are MySQL configuration and two are Convex specifics that fail the sync if you skip them:

Binary logging with generous retention. Around ten days, expressed as 864000 seconds, is the figure commonly used. On Amazon RDS the setting is different, called binlog retention hours, and it defaults to zero, which purges logs immediately and makes change data capture impossible until you change it.

A dedicated read-only MySQL user. With replication permissions rather than an application account. Encryption is required by default and the connection fails if the source will not encrypt. The MySQL source documentation covers the available SSL modes.

A Convex deployment and deploy key. The deployment URL and a deploy key from the Convex dashboard settings. Point this at a production deployment rather than a development one, since the connector will be creating and writing tables. Convex describes its Airbyte integration as a beta feature, so validate it on a non-critical table before a customer-facing feature depends on it.

Table names Convex will accept. Convex table names can contain only letters, digits and underscores, and may not begin with an underscore. MySQL table names are more permissive, so check yours against that rule before the first sync rather than debugging a failure afterwards. The Convex destination documentation covers the behaviour.

One direction worth confirming: Airbyte moves data into Convex, and streaming export out of Convex through Airbyte is not supported. If you also need Convex data in a warehouse, that is a separate problem with a separate tool.

How do you build a MySQL to Convex pipeline in Airbyte?

Step 1: Decide which tables your feature actually reads

Because the destination is an application backend rather than a warehouse, replicating the whole schema is actively harmful: it bloats your deployment and none of it is queried. Write down the specific tables your Convex functions read, and check their names against Convex's naming rules while you are at it.

Step 2: Configure the MySQL source

Click Sources in the left navigation, then New Source, and select MySQL, following adding a source. Supply the host, port, database, credentials and SSL mode, and choose Read Changes using Binary Log as the replication method so deletions are captured. Enable binary logging and set retention before this step, because a connection against a server with no binlog passes its credential test and then fails in a way that looks like a connector problem.

Step 3: Configure the Convex destination

Click Destinations, then New Destination, and select Convex, following adding a destination. Supply the deployment URL and deploy key. Each stream becomes a table, each row becomes a document, and Convex assigns its own identifier and creation time fields during the sync, which sit alongside your columns rather than replacing them.

Step 4: Use incremental sync so deletes propagate

Click Connections, then New connection, select your tables and an incremental sync mode. This matters twice over. Incremental is how deletions reach Convex, and the destination explicitly warns that performance suffers with large, frequent full refresh syncs, so it is both the correct choice and the fast one.

One behaviour to note on incremental dedup: Convex does not keep a history table the way some warehouse destinations do, it stores a deduped snapshot instead. That is what an application wants, since your functions read current state, and it does mean the history is not sitting there if someone later asks for it.

Why do deletes work properly on this pipeline?

Because both halves support them, which is unusual. MySQL's change data capture reads the binary log, so a deletion is an event rather than something you infer from a row's absence. And the Convex destination lists support for replicating incremental deletes, so that event can be applied rather than discarded.

That matters far more here than on an analytical destination. A warehouse holding a deleted customer is a modelling inconvenience you can filter around. An application backend holding one means your product shows a record that no longer exists, to a real person, which is the kind of bug that gets reported by a customer rather than noticed by an engineer.

The condition is that you use an incremental sync mode. Choose full refresh and you lose the mechanism entirely, because a full refresh has no concept of an individual deletion, it just replaces contents. Given the performance warning on full refresh as well, there is no situation on this pairing where it is the better choice for a table of any size.

What happens if binlog retention is too short?

The connection quietly reverts to full snapshots. Airbyte records the binlog position when it starts, then reads forward from there, and if the logs covering that position are purged before it resumes, it cannot continue and starts again from scratch. Look for a log message saying the saved offset is no longer present on the server.

On this pipeline that has a second consequence beyond wasted work. A full snapshot has no deletions in it, so while the connection is stuck in that loop your Convex tables stop reflecting removals even though syncs keep reporting success. The symptom appears in your product rather than in your monitoring.

Set retention generously before the first sync, and on a large source check that the initial snapshot itself completes inside the retention window, because if it does not the connection loops indefinitely without ever failing. Alert on repeated full refreshes rather than only on sync errors.

Frequently asked questions

Do deletions in MySQL reach Convex?

Yes, with an incremental sync mode and CDC on the source. MySQL's binary log captures deletions and the Convex destination supports replicating incremental deletes. Full refresh loses that mechanism.

Why did my sync fail on a table name?

Convex table names can contain only letters, digits and underscores, and cannot start with an underscore. MySQL is more permissive, so check your table names against that rule.

Can Airbyte move data out of Convex as well as into it?

No. Airbyte supports streaming import into Convex. Moving Convex data elsewhere needs a different tool.

Does incremental dedup keep history in Convex?

No. Unlike some warehouse destinations, Convex stores a deduped snapshot rather than a history table. Current state is preserved, previous versions are not.

Can I do this without writing code?

Yes. The setup above is entirely UI-driven, from creating the source through to scheduling the connection. Your Convex functions then read the synced tables like any others.

Get your MySQL data into Convex

Replicate only the tables your functions read, check their names against Convex's rules, set binlog retention generously, and use incremental sync so deletions propagate. Because this data now sits behind something users see, alert on repeated full refreshes rather than only on failures.

Airbyte's connector catalog includes 700+ pre-built connectors, so the same MySQL source can feed a warehouse for analysis alongside this one. For that pairing, see MySQL to Snowflake, and for another source feeding an application backend, PostHog to Convex.

Start syncing now →

Integrate with 700+ apps using Airbyte

Move data from 700+ sources into warehouses, lakes, and beyond. Set up pipelines in minutes with pre-built connectors and the Connector Builder.