PostgreSQL to TiDB: How to Move Your Data
Move PostgreSQL into TiDB with Airbyte. Why normalization needs v5.4.0, handling Postgres-only types against a MySQL-compatible database, and slot monitoring.

Moving PostgreSQL into TiDB is usually a scale decision. TiDB is an open-source distributed NewSQL database supporting hybrid transactional and analytical workloads, MySQL compatible, with horizontal scalability and high availability. Those are the properties a single Postgres instance cannot offer however large the machine gets.
This guide covers the managed path with Airbyte. Two things shape it: TiDB's MySQL compatibility means the type questions are MySQL's type questions, and the destination has a version prerequisite that decides what your tables actually look like.
PostgreSQL to TiDB at a glance:
Why move data from PostgreSQL to TiDB?
Two situations account for most of these pipelines.
The first is outgrowing a single instance. Postgres scales vertically well and eventually stops, and sharding it yourself is a project nobody enjoys. TiDB distributes horizontally by design, so a migration is often about removing a ceiling rather than gaining a feature.
The second is running transactional and analytical work in one place. TiDB's hybrid design means queries that would compete with your application on Postgres can be served without a separate warehouse. If you already run a warehouse and Postgres is comfortably within its limits, this pipeline solves a problem you do not have.
What do you need before you start?
One prerequisite affects your source database's health and one decides what your tables look like:
Logical replication on PostgreSQL, plus monitoring. A replication slot and a publication, and an alert on slot lag. An unconsumed slot means PostgreSQL retains write-ahead log it cannot discard, which on a busy database fills the disk of the system serving your application rather than anything belonging to Airbyte.
TiDB v5.4.0 or above, if you want normalized tables. Syncing with normalization requires that version at minimum. Below it you get the raw output format, which is covered below and is not what most people expect. The TiDB destination documentation states the requirement.
A TiDB user with six permissions. Create, insert, select, drop, create view and alter. That is broader than a read and write account, because the connector manages table structure as well as contents, and it is worth raising with whoever administers the cluster rather than requesting quietly.
A list of your Postgres-specific columns. Arrays, ranges, enums, composite types and anything from an extension. Because TiDB is MySQL compatible, these need the same decisions they would need for a MySQL destination, and making them before the first sync is far easier than after.
If your cluster sits in a private network, the connector supports an SSH tunnel through a bastion. If it restricts inbound traffic by IP instead, add the Airbyte Cloud IP addresses to the allow list.
How do you build a PostgreSQL to TiDB pipeline in Airbyte?
Step 1: Check your TiDB version and plan the types
Confirm the cluster is on v5.4.0 or above, since that determines whether you get typed tables or raw JSON. Then go through your Postgres schema and decide how the types MySQL has no equivalent for should land. An array becomes JSON or a child table, and those lead to different downstream code, so choose rather than discover.
Step 2: Configure the PostgreSQL source
Click Sources in the left navigation, then New Source, and select Postgres, following adding a source. Supply the host, port, database, schema and credentials, and choose logical replication as the replication method with your slot and publication names, so deletions reach TiDB rather than leaving orphaned rows.
Step 3: Configure the TiDB destination
Click Destinations, then New Destination, and select TiDB, following adding a destination. Supply the host, port, database and the credentials for the user you created. If the cluster has no public address, set the SSH tunnel method to key or password authentication and supply the bastion details, remembering that the SSH login is the bastion's operating system user rather than your TiDB user.
Step 4: Create the connection and verify a subset
Click Connections, then New connection, select your tables and a sync mode per stream. Run against a handful of tables first and compare the resulting column types and a sample of values against Postgres before extending. On a migration the copy becomes the system of record, so verification is worth more here than on a reporting pipeline.
Remember that the pipeline moves rows. Indexes, constraints, triggers, sequences and any procedural logic have to be recreated separately, and on a distributed database some of those decisions look different from how they looked in Postgres.
What do the tables actually look like?
By default each stream becomes its own table carrying three columns: an identifier Airbyte assigns to every processed event, stored as a variable-length string; a timestamp recording when the event was pulled from the source; and a column holding the event data as a JSON blob, which in TiDB uses the JSON type.
That raw shape is not what an application can query comfortably. Normalization is what turns it into typed tables with real columns, and normalization is what requires v5.4.0 or above. So the version check is not a footnote about compatibility, it decides whether your destination holds a queryable schema or a column of JSON.
Check this before you promise anyone a delivery date, particularly on an older self-managed cluster where upgrading is a piece of work in itself. Discovering it after the first sync means either an upgrade you had not scoped or a modelling layer you had not planned.
Which Postgres types cause trouble?
The ones MySQL has no equivalent for, because TiDB is MySQL compatible. Arrays are the most common: a text array column is idiomatic Postgres and has no counterpart, so it becomes JSON or gets normalised into a child table. Range types, composite types and extension-provided types have the same problem.
JSONB maps reasonably onto a JSON column, and the operators your existing queries use will not carry across, so downstream SQL touching those columns needs rewriting rather than repointing. Enums exist on both sides but behave differently enough to be worth checking, particularly around values no longer in the definition.
One thing that is not a problem: identifier length. PostgreSQL allows 63 characters and MySQL-compatible databases 64, so column and table names travel in this direction without collisions. Going the other way is where names can be too long.
Frequently asked questions
Why are my TiDB tables just a JSON column?
That is the raw output format. Normalization produces typed tables and requires TiDB v5.4.0 or above, so check your cluster version.
What permissions does the TiDB user need?
Create, insert, select, drop, create view and alter. That is broader than read and write because the connector manages table structure as well as contents.
What happens to my array columns?
TiDB is MySQL compatible and has no array type, so they land as JSON or need normalising into a child table. Decide which before the first sync.
Why is my PostgreSQL disk filling up?
An unconsumed logical replication slot. PostgreSQL retains write-ahead log beyond the slot's position, so monitor slot lag and drop slots you no longer use.
Can I do this without writing code?
The Airbyte setup is entirely UI-driven. You may want PostgreSQL views to shape awkward types deliberately, and downstream SQL using Postgres-specific JSON operators will need rewriting.
Get your PostgreSQL data into TiDB
Check the cluster version first, because it decides whether you get typed tables or raw JSON. Then list your Postgres-specific columns and decide how each should land, request the full permission set up front, verify types on a subset, and monitor the replication slot as a database health metric.
Airbyte's connector catalog includes 600+ pre-built connectors, so the same PostgreSQL source can feed a warehouse alongside this one. For the same type decisions against a single-node destination, see PostgreSQL to MySQL, and for PostgreSQL into a lakehouse, PostgreSQL to Databricks.
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.
