GitHub to MySQL: How to Sync Your Data
Replicate GitHub into MySQL with Airbyte. Why REST and GraphQL rate limits are budgeted separately, splitting the sync, and modelling nested payloads.

Replicating GitHub into MySQL puts engineering activity where an application or an internal tool can query it. A team dashboard, a release tracker or a service catalogue that needs to know what happened in your repositories is far simpler to build against a database than against GitHub's API with its own rate limits.
This guide covers the managed path with Airbyte. The thing that makes this connector unusual is that you are budgeting against two rate limits at once that have nothing to do with each other, and a sync can stop halfway because a handful of streams were spending a different currency from the rest.
GitHub to MySQL at a glance:
Why move data from GitHub to MySQL?
Two situations account for most of these pipelines.
The first is powering an internal tool. Something that shows which services have recent releases, who owns what, or where review load is concentrated, reading from a database it already connects to rather than holding GitHub credentials of its own.
The second is joining engineering data to whatever already lives in that database, such as service ownership or incident records. If you want multi-year delivery analytics across a large organisation, a warehouse is the better destination for reasons of volume.
What do you need before you start?
Most of this is deciding scope rather than gathering credentials:
A token owned by a service account. The token inherits its owner's access, so one created against an individual sees what they see and stops working when they leave. Scope a service account to the repositories or organisation you actually want.
A deliberate list of streams. Select streams because something will read them, not because they were ticked by default. On a source with two independent rate limits, an unused stream competes for capacity with a used one.
A realistic view of volume. Airbyte recommends relational destinations for roughly 10GB or less. Commits and comments across a large organisation exceed that, so select repositories and streams with the destination in mind rather than syncing everything available.
A MySQL user with write access. On the target schema, ideally one dedicated to synced data so the pipeline cannot collide with application tables. Airbyte adds its own metadata columns, so plan to expose views rather than raw tables.
If your organisation restricts inbound traffic by IP, add the Airbyte Cloud IP addresses to the allow list on the MySQL side before you begin.
How do you build a GitHub to MySQL pipeline in Airbyte?
Step 1: Sort your streams by which API they use
Before opening Airbyte, split your wanted streams into two lists. Most use the REST API. Pull request stats, reviews, pull request comment reactions, issue reactions, releases and the projects endpoint use GraphQL. That split is the basis of the connection design in step 4, and doing it now takes five minutes.
Step 2: Configure the GitHub source
Click Sources in the left navigation, then New Source, and select GitHub, following adding a source. Authenticate with your service account token, set a start date, and name the repositories or organisation you decided on.
Step 3: Configure the MySQL destination
Click Destinations, then New Destination, and select MySQL, following adding a destination. Supply the host, port, database and credentials. Watch identifier lengths, since MySQL allows 64 characters and GitHub's nested field names can produce long column names once flattened.
Step 4: Build two connections, not one
Click Connections, then New connection, and build one connection for the REST-backed streams on a frequent schedule, and a second for the GraphQL-backed streams on a slower one. Use an incremental sync mode on both, so each has its own budget, schedule and failure boundary.
This is the recommendation people most often skip, and it is the one that makes the difference on any organisation large enough to hit the limits at all.
Why did my sync stop before reading every stream?
Because you exhausted one of GitHub's two rate limits. The REST API counts requests. The GraphQL API counts points, where each query costs an amount GitHub calculates from what you asked for. The two are tracked separately, so one can be empty while the other is untouched.
The reaction streams deserve particular attention. They are high-volume, usually the least useful thing in the catalogue for an application, and they draw down the same point budget that reviews and releases need. Deselecting them is frequently the cheapest fix available.
When limits are reached before every stream has been read, the remedies are incremental sync, a longer interval, and splitting into separate connections. They compound rather than compete, and the third is the most useful and least used.
What do you do about the nested payloads?
GitHub API responses nest heavily. A pull request record carries user objects, label arrays, milestone objects and repository references inside it, and Airbyte preserves that structure rather than guessing at a flattening.
That is correct behaviour and genuinely awkward in MySQL, which has a JSON type but none of the ergonomics a warehouse offers for working with it. So the modelling layer is not optional here the way it might be elsewhere: build views extracting the fields your application reads, and let it query those.
Exposing views rather than raw tables has a second benefit on a pipeline feeding an application. The metadata columns Airbyte adds stay invisible, and a future schema change on GitHub's side can be absorbed in the view rather than breaking whatever reads it.
Frequently asked questions
Why did my GitHub sync stop before reading every stream?
You exhausted one of GitHub's two rate limits. REST and GraphQL are budgeted separately, so check which streams were still pending and which API they use.
Which streams use the GraphQL API?
Pull request stats, reviews, pull request comment reactions, issue reactions, releases and the projects endpoint. These consume calculated query points rather than request counts.
Is MySQL big enough for GitHub data?
For a focused set of repositories and streams, comfortably. Airbyte recommends relational destinations for roughly 10GB or less, and commits and comments across a large organisation will exceed that.
Why is my pull request data full of nested columns?
GitHub responses nest objects and arrays inside each record and Airbyte preserves that. Build MySQL views extracting the specific fields your application reads.
Can I do this without writing code?
The Airbyte setup is entirely UI-driven. You will want SQL views over the nested payloads, which on this destination is closer to a requirement than a nicety.
Get your GitHub data into MySQL
Sort your streams by API before configuring anything, build two connections rather than one, keep the scope tight given the volume guidance, and expose views rather than raw tables so your application reads a stable interface.
Airbyte's connector catalog includes 700+ pre-built connectors, so engineering data can reach an application and a warehouse at once. For the analytical version, see GitHub to Snowflake, and for the other major code host, GitLab to BigQuery.
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.
