GitHub, 2016–2026  / field guide
Practitioner field guide · Company dig · 18 October 2026

The cluster nobody finished emptying: ten years of GitHub

GitHub kept one Rails monolith and one MySQL estate for a decade and built, in public, the tooling to operate them: gh-ost, freno, orchestrator, Trilogy, Spokes. This guide rebuilds that decade from GitHub's own postmortems, design posts and repositories, and shows why the shared database it began splitting in 2019 was still being emptied, one table cohort at a time, when agent traffic arrived in 2026.

35 sources, 9 hosts 8 published incidents 3 repositories read with git Evidence through October 2026 Read: 29 min
01

The territory: one shared database, and everything built to keep it alive

Why GitHub, and why now: in August 2026 GitHub moved a 24-table authentication cohort off mysql1, the cluster whose partitioning began in 2019, and served its first production MySQL primary from Azure. The decade can now be read end to end.

24h 11m
Degraded service after a 43-second network partition and an automatic cross-country failover (Oct 2018)
~1M QPS
Replica reads removed from mysql1 by moving one 24-table auth cohort, seven years after partitioning began
2.9B
Monthly commits in August 2026, up from 1.4B in April
58%
Share of platform load served from Azure in August 2026, up from 12% in May

The problem this dig follows, stated without the company's name: how do you keep a product available when most of its features share one relational store, the store lives in buildings you own, and demand grows faster than you can split either? GitHub is the cleanest public case because it chose, again and again, not to rewrite. It kept the Rails monolith (upgraded in place, then bumped to Rails main every week), kept MySQL, and spent its engineering on the layer around them.

The surprise

The partitioning of mysql1 was announced as a success in 2021, with load on the receiving hosts down 50% (GitHub, 2021). Five years later the cluster still held an authentication cohort worth about a million queries per second of replica reads (GitHub, Aug 2026), and a February 2026 outage had overloaded the "core database cluster that handles authentication and user management" (GitHub, Mar 2026). Partitioning removed the easy tables first. The tables left behind were the oldest, the most joined and the hottest, which is to say the ones every request touches.

Figure 1 · A decade in four phases

tools govern change

failover cannot fix sharing

region runs out of room

2016-2017 · Operate the store
DGit / Spokes, 3 Git replicas
gh-ost, triggerless schema change
Kubernetes on own metal
freno lag throttler

2018 · Automate the topology
orchestrator + Consul + GLB
Oct 21: 43 s partition,
24 h 11 m degraded

2019-2023 · Split the shared store
mysql1 partitioning from 2019
Feb 2020, Mar 2022: mysql1 again
MySQL 8.0 on 1,200+ hosts

2025-2026 · Leave the building
Azure memo, Oct 2025
agent load, primaries to Azure
Spokes replaced by blob storage

tools govern change

failover cannot fix sharing

region runs out of room

2016-2017 · Operate the store
DGit / Spokes, 3 Git replicas
gh-ost, triggerless schema change
Kubernetes on own metal
freno lag throttler

2018 · Automate the topology
orchestrator + Consul + GLB
Oct 21: 43 s partition,
24 h 11 m degraded

2019-2023 · Split the shared store
mysql1 partitioning from 2019
Feb 2020, Mar 2022: mysql1 again
MySQL 8.0 on 1,200+ hosts

2025-2026 · Leave the building
Azure memo, Oct 2025
agent load, primaries to Azure
Spokes replaced by blob storage

Every phase is a response to the one before: tools to operate MySQL, then automation that failed across regions, then a split that stopped short, then an exit from owned data centres forced by physical capacity. Sources: GitHub engineering blog and availability reports, 2016 to 2026; first-hand git history of gh-ost and orchestrator.
Diagram source

Scope. This guide covers the github.com runtime: the monolith, its relational tier, Git storage, deploys and the hosting move. It does not cover GitHub Actions runners, Copilot's model serving, Enterprise Server packaging, or organisational changes beyond the 2025 move into Microsoft's CoreAI group as it bears on the Azure decision.

02

How it is actually built: a monolith, a proxy tier, and a ring of tools around MySQL

The shape that held from about 2017 to 2025, reconstructed from GitHub's posts. Each box is attributable to a named source. In 2026 two of them began to change: the primaries started moving to Azure and Spokes is being replaced.

Figure 2 · The github.com runtime, circa 2023

Change path

Request path

Trilogy client

Git RPC

writes primary to

consul-template

may I write?

Rails monolith
on Kubernetes

GLB / HAProxy
writer pools

mysql1, shared core
every postmortem names it

Domain clusters
split since 2019

Spokes
replicated fileservers

orchestrator/raft
failover

Consul KV

gh-ost
schema change

freno
lag throttler

Change path

Request path

Trilogy client

Git RPC

writes primary to

consul-template

may I write?

Rails monolith
on Kubernetes

GLB / HAProxy
writer pools

mysql1, shared core
every postmortem names it

Domain clusters
split since 2019

Spokes
replicated fileservers

orchestrator/raft
failover

Consul KV

gh-ost
schema change

freno
lag throttler

Notice that the tools in the change path (dashed edges) are not in the request path; they decide when the request path may change. That ring is what GitHub built and open-sourced, and it is also what failed in 2018 and 2024. Reconstructed from the MySQL HA post, Trilogy, freno and DGit.
Diagram source

The request path stayed boring on purpose. In 2017 GitHub moved the web and API tier from Unicorn processes supervised by God, deployed by Capistrano over SSH, onto Kubernetes clusters in its "metal cloud" (GitHub, 2017). The application did not change shape. Rails was upgraded in place by dual-booting the app against two lockfiles, which took about eighteen months for 3.2 to 5.2 and avoided a long-lived branch (GitHub, 2018); by 2023 a bot opened a pull request every Monday to move the monolith to the latest Rails main (GitHub, 2023). Even the database driver was owned: Trilogy, GitHub's own implementation of the MySQL wire protocol, served the monolith from 2015 and was open-sourced in 2022 (GitHub, 2022).

The change path is where the engineering went. gh-ost (2016) changes schemas by tailing the binary log instead of installing triggers. freno (2017) is a throttler that batch writers consult before writing, so replication lag is rationed rather than discovered. In 2018 GitHub replaced VIP and DNS failover with orchestrator running raft across data centres, publishing the current primary to Consul's key-value store, from which consul-template rewrites identical HAProxy writer pools on every GLB node (GitHub, 2018). The design goal was explicit: data-centre independence and no "unreliable cooperative workflows". Four months later it produced the decade's longest outage.

mysql1, the shared core

Held "a large portion of the data used by GitHub.com's core features": users, repositories, issues, pull requests. Every postmortem in 2020 and 2022 names it.

Sources: 2021, 2020

Spokes, Git on replicated disks

Three copies per repository in 2016, commit on two acknowledgements; five full copies by default by 2026, with a three-phase quorum commit on ref updates. Being replaced.

Sources: 2016, 2026

The fleet underneath

1,200+ MySQL hosts, 300+ TB, 50+ clusters, 5.5M QPS at the MySQL 8 upgrade, already a mix of Azure VMs and bare metal. In 2026 primaries begin moving to Azure.

Sources: 2023, 2026

One inference worth flagging. GitHub has not published a design document for the August 2026 primary moves, but its own gh-ost repository shows the tool being taught a new job: a --move-tables mode, first committed on 15 May 2026, whose flag text reads "a special mode that allows you to move tables between database clusters" (gh-ost, feature-move-tables). As of 18 October 2026 the branch is not in master. Neither the report nor the branch says the two are connected, but a binlog-tailing copier with a postponed cut-over is exactly the tool you would want for moving a 24-table cohort off a hot cluster.

03

The decisions that matter, and the condition that flips each

Six forks GitHub took in public. Three of them it later reversed or narrowed, which is what makes the "flips when" column checkable rather than speculative.

Decision: should topology automation be allowed to move the primary across regions?

Chosen, 2018
  • orchestrator/raft spanning data centres, any healthy replica eligible
  • Goal: survive the loss of a whole DC with no human in the loop
Rejected, then partly restored
  • VIP and DNS failover, rejected for split-brain and caching
  • After October 2018: no automatic promotion across region boundaries
Flips when
  • The application can tolerate cross-region write latency and the two sides can reconcile divergent writes. GitHub's could not do either in 2018.

Decision: split the shared store by schema domain, or shard it horizontally?

Chosen, 2019
  • Vertical partitioning: group tables into schema domains, move each domain to its own cluster
  • Keeps MySQL, Rails and most queries unchanged
Deferred
  • A distributed database or horizontal sharding of everything
  • Cross-domain transactions and polymorphic tables (reactions spanning issues, PRs and discussions) are the hard cases
Flips when
  • One domain's write rate exceeds a single primary, or the remaining shared tables are the ones every request joins. By 2026 both conditions are visible.

Decision: replicate Git on local disks with a quorum, or store it in an object store?

Chosen, 2016; reversed 2026
  • 2016: application-level replication, three loosely coupled repositories kept in sync by Git itself
  • 2026: authoritative data in Azure Blob Storage, compute workers that fail like a cache miss
Rejected
  • 2016: disk-level replication and identical server pairs
  • 2026: more Spokes replicas, because "adding read replicas slows writes"
Flips when
  • Writes, not reads, dominate growth, and a durable elastic store is available underneath. Agent traffic made both true in 2026.

Figure 3 · When to stop splitting and start leaving

yes

no

no

yes

yes

no

Do most incidents
name one shared store?

Is the remaining load
in tables every request joins?

Fix the change path first:
config, deploys, retries

Partition by domain,
move cold domains out

Can you add hardware
where the primary lives?

Scale up, then move the hot
cohort with a cut-over tool

Move the primary itself:
new region or new provider

yes

no

no

yes

yes

no

Do most incidents
name one shared store?

Is the remaining load
in tables every request joins?

Fix the change path first:
config, deploys, retries

Partition by domain,
move cold domains out

Can you add hardware
where the primary lives?

Scale up, then move the hot
cohort with a cut-over tool

Move the primary itself:
new region or new provider

The tree GitHub's record implies, read from its 2021, 2025 and 2026 decisions. Terminal nodes are actions, and the bottom-right one is where GitHub found itself in October 2025. Derived; GitHub has published no such tree.
Diagram source
DecisionChosenRejectedBecauseFlips whenEvidence
Online schema changeBinlog-tailing copy, gh-ost (2016)Trigger-based toolsTriggers are interpreted, share the query's transaction and contend for locks; concurrent migrations were unsafeMySQL 8 instant DDL covers the change, or the table is small and coldGitHub, 2016
Replication lag controlCooperative throttler, freno (2017)Discovering lag from stale readsBatch jobs and migrations are the lag source and can waitWriters you do not control (third-party clients, agents) generate the loadGitHub, 2017
Primary failoverorchestrator/raft + Consul + GLB (2018)VIP and DNSSplit brain and DNS cachingCross-region promotion: narrowed after Oct 2018InfoQ on GitHub, 2018
Deploy exposure2% then 20% canary, 5-minute automated gates (2021)Single 2% canaryProblems surfaced only after full rolloutThe fault is in a dependency's config, not the deployed codeGitHub, 2021
Monolith runtimeKeep Rails, track main weeklyRewrite into servicesUpgrade cost amortised; product kept shippingHot paths outgrow Ruby: Ruby-to-Go moves are reported in 2026 (secondary sources only)GitHub, 2023
HostingOwn metal (2016 to 2025), Azure from 2025, AWS capacity added 2026Public cloud, until 2025Control and cost; then "limited opportunities to bring more capacity online in the North Virginia region"Physical capacity cannot be added where the primaries liveThe New Stack, 2025

The hosting row is the one an architect should read twice. GitHub's CTO told staff in October 2025 that the move to Azure was "existential", that the plan was eighteen months with a six-month buffer, and that earlier Azure migrations had been, in The New Stack's words, "halting and sometimes failed" (The New Stack, 2025). The reason given was not price or features. It was that the region holding the primaries could not take more servers. A decade of tooling had made a single-region relational core operable; it had not made it portable, and portability became the requirement the moment the building ran out of power and floor space.

04

What broke in production: three failure classes, one recurring dependency

Eight published incidents fall into three classes. The first class names mysql1 outright; the second is the change path to the database; the third is growth outrunning capacity, made worse by retries.

Class A · The shared store saturates and takes every feature with it

Postmortem

February 2020: one query pattern, every dependent service

AssumptionRead-heavy queries go to replicas; the connection proxy has headroom.
What happenedA heavy query meant for replicas reached the mysql1 primary; ProxySQL, its descriptor limit silently downgraded to 65,536, could not keep up; later an application change to query patterns "rapidly increased load on the master".
Blast radiusFour events, 8 hours 14 minutes of degraded service across github.com.
FixAccelerated partitioning of mysql1; configuration audit of the proxy tier.
Design ruleA shared primary turns every team's query change into a platform change. Until the split is finished, query review for that cluster is a platform gate, not a team habit.
Postmortem

March 2022: the same cluster, after the partitioning post

AssumptionThe 2019 to 2021 partitioning had removed mysql1 as a single point of contention.
What happened"Resource contention in our mysql1 cluster" at peak load; the database proxy hit its connection limit and writes failed across Git operations, pull requests and Actions.
Blast radiusFour incidents in eight days (16, 17, 22, 23 March), per contemporaneous coverage.
FixFurther table moves, query fixes, and throttling of the worst offenders.
Design ruleMeasure a partitioning programme by what is left on the shared cluster at peak, not by load removed from it. Fifty per cent down is still a shared blast radius.
Postmortem

February 2026: a cache TTL becomes a database outage

AssumptionShortening a user-settings cache refresh from 12 hours to 2 hours, to speed a model rollout, was a local change.
What happenedWeekend traffic hid the extra writes. Monday peak, client-app updates and another model release combined to overload "the core database cluster that handles authentication and user management".
Blast radiusTwo windows on 9 February (16:12 to 17:39 and 18:53 to 20:09 UTC) across nearly every core service; diagnosis was slow because the read growth was unexplained.
FixDecoupling critical services, backpressure, dedicated hosts for hotspot services, change-management tightening.
Design ruleCache TTLs in front of a shared store are capacity settings. Changing one needs the same review and load test as resizing the database.

Class B · The change path to the database is the outage

Figure 4 · October 2018: 43 seconds, then a day

"Rails app""West DC replica""orchestrator raft""East DC primary""Rails app""West DC replica""orchestrator raft""East DC primary"22:52 UTC, optical maintenance cuts the East hubboth sides hold writes the other lacksabout 40 min of West writesbefore diagnosis24 h 11 m degraded while datareconcileswrites continue for 43 s, not replicatedquorum without East, promoteWestwrites now cross the countryfailback unsafe, fail forward
"Rails app""West DC replica""orchestrator raft""East DC primary""Rails app""West DC replica""orchestrator raft""East DC primary"22:52 UTC, optical maintenance cuts the East hubboth sides hold writes the other lacksabout 40 min of West writesbefore diagnosis24 h 11 m degraded while datareconcileswrites continue for 43 s, not replicatedquorum without East, promoteWestwrites now cross the countryfailback unsafe, fail forward
The failover worked as designed. What made it a 24-hour incident is the sequence after it: writes on both coasts that the other lacked, so the only safe direction was forward, at cross-country latency. Reconstructed from the GitHub postmortem and InfoQ's account.
Diagram source
Postmortem

October 2018: automation chose availability, the app needed locality

AssumptionAny promotable replica is an acceptable primary; a DC-independent failover is strictly better than a human.
What happenedA 43-second partition let orchestrator's quorum promote West Coast primaries; the East had accepted unreplicated writes; the application could not run well at cross-country latency.
Blast radius24 hours 11 minutes degraded; webhooks and Pages builds delayed; manual reconciliation of seconds of writes.
FixNo automatic promotion across region boundaries; an active/active/active data-centre design was announced. No later post reports that design complete.
Design ruleEncode geography in the failover policy. A candidate primary the application cannot use at acceptable latency is not a candidate.
Postmortem

August 2024: a database config change empties the routing pool

AssumptionA configuration change to the database fleet is lower-risk than a code deploy.
What happenedAt 22:59 UTC a faulty change made database hosts fail the routing layer's health checks; the routing service "could not find healthy databases", and the read-only endpoint became unreachable.
Blast radiusgithub.com unavailable for all users from 23:02 to 23:38 UTC; no data lost.
FixRevert; guardrails on database change management; faster rollback.
Design ruleA health check that can mark the whole pool unhealthy at once is a global switch. Cap how much of a pool one change may eject, and fail static when it tries.

Class C · Growth outruns the building, and retries finish the job

Postmortem

17 August 2026: a new peak, an unscaled component, a retry loop

AssumptionCapacity plans set in October 2025 would hold through 2026.
What happenedTraffic reached a new peak; a critical component in the Central US data centre failed to scale; authentication failures spread; during recovery a client-side retry loop added load and had to be mitigated first. GitHub says no code or configuration change caused it.
Blast radiusAbout seven hours; secondary reports cite roughly 20% error rates on web and API.
FixCapacity, efficiency, bottleneck removal; consistent retry limits listed first in secondary summaries.
Design ruleRetry budgets belong in every client you ship, including your own apps; a recovery plan that assumes clients back off is a plan for a different system. The OSDI '22 survey found retries behind over half of sustained overloads.
Postmortem

April 2026: demand rationed at the product layer

AssumptionAgentic workloads are another tenant on the same platform.
What happenedAgent workflows "accelerated sharply" from late December 2025. A merge-queue regression on 23 April corrupted squash merges in 230 repositories and an Elasticsearch overload on 27 April broke search-backed UI.
Blast radiusTen degrading incidents in April 2026 by GitHub's own count; new Copilot Pro, Pro+ and Student sign-ups paused.
FixPriority order stated as availability, then capacity, then features; isolation of critical services; move to public and multiple clouds.
Design ruleWhen the platform cannot grow fast enough, admission control moves up the stack to sign-ups and plans. Design that lever before you need it.

Read across the classes and one pattern stands out. Every Class A incident is a local change (a query, a proxy limit, a cache TTL) that became global because the store underneath was shared. Every Class B incident is a control-plane action that did exactly what it was configured to do. Neither class is solved by more database hardware, and neither was solved by the tooling ring of Figure 2, because the ring governs how the store changes, not who shares it.

05

Numbers you can plan against

Each row is dated. "Measured" means GitHub reported it about its own production; "internal" means a benchmark; "secondary" means only press or summaries carry it.

MetricValueKindContextAs ofSource
Degraded service, Oct 2018 partition24 h 11 mMeasuredTriggered by 43 s of lost connectivity2018-10GitHub
West Coast writes before diagnosis~40 minSecondaryDivergent writes on both coasts2018-10InfoQ
mysql1 incidents, February 20208 h 14 mMeasuredFour events2020-02GitHub
Load drop on hosts that took mysql1 data50%MeasuredAfter 2019 to 2021 partitioning2021-09GitHub
MySQL fleet1,200+ hosts, 300+ TB, 50+ clustersMeasuredAzure VMs plus bare metal2023GitHub
MySQL query rate5.5M QPSMeasuredFleet-wide, at MySQL 8 upgrade2023GitHub
Canary stages2%, then 20%Measured5-minute automated gates2021-01GitHub
Monolith dev environment start45 min to 10 sMeasuredCodespaces with prebuilds2021-08GitHub
Full unavailability, Aug 202436 minMeasured23:02 to 23:38 UTC, database routing2024-08GitHub
Git replicas per repository3 (2016), 5 default (2026)MeasuredQuorum commit on writes2016, 2026GitHub
Git activity473.3B events / monthMeasuredMore than doubled since Sep 20252026-08GitHub
Write throughput, new Git storageup to 35×InternalBenchmark, not production2026-10GitHub
Monthly commits1.4B to 2.9BMeasuredApril to August 20262026-08GitHub
Platform load on Azure12% to 58%MeasuredMay to August 20262026-08GitHub
Replica reads removed from mysql1~1M QPSMeasuredOne 24-table auth cohort moved2026-08GitHub
Query-hygiene savings120k QPS; 59,000 DB-seconds / hourMeasuredSame month2026-08GitHub
Capacity target10× (Oct 2025) to 30× (Feb 2026)SecondarySummaries of the April 2026 CTO post2026-04GitHub (via summaries)
Read these carefully

Two derived figures are mine. First, the 1M QPS removed from mysql1 replicas in 2026 is, on its own, about 18% of the entire 2023 fleet's 5.5M QPS (1.0 / 5.5); the two numbers are three years apart and one is replica-only, so treat it as an order of magnitude, not a ratio. Second, the "seven years" is 2019 (partitioning starts) to 2026 (auth cohort moves). GitHub has never published what fraction of mysql1 remains, its current QPS, or its table count; those are the numbers an architect would most want and they are open.

06

The lesson: a split that stops at "most" leaves the hottest tables in the blast radius

GitHub's decade is not a story of bad choices. Keeping the monolith was right by any measure GitHub published: weekly Rails main, a 10-second dev environment, no rewrite freeze. Keeping MySQL and building gh-ost, freno and orchestrator around it was right too; those tools are still the reference implementations other companies adopt. What the record shows is narrower and more transferable.

"GitHub is constrained on data server capacity with limited opportunities to bring more capacity online in the North Virginia region." GitHub CTO memo, October 2025, as reported by The New Stack

First, decomposition of a shared store has an exit metric or it has no end. Partitioning by schema domain moves cold, self-contained domains first because they are cheap to move. That is rational per step and wrong in aggregate: the residue is the identity, permission and user tables that everything joins, which carry the peak load and the widest blast radius. GitHub's 2021 post measured success as load removed (50%). The 2026 incidents measured what remained. Write the target as "no feature's availability depends on the shared cluster", track the residue, and move the hot cohort while you still have capacity headroom to run a dual-write cut-over, not after.

Second, the tools that operate a store are part of the store's architecture, and they age like people. orchestrator's maintainer stopped reviewing pull requests in February 2023 and the repository was archived in February 2025 with a pointer to Percona's fork (git history). gh-ost fell from 667 commits in 2016 to 20 in 2023, then revived to 87 in 2026 as GitHub needed resumable migrations (October 2025) and a table-mover (May 2026). If your failover or migration path depends on a tool with a bus factor of one, that dependency belongs on the risk register next to the database.

Third, owning the building is a capacity bet with a lead time measured in years. GitHub ran its relational primaries in owned data centres while public-cloud VMs were already in its fleet by 2023. The move only became urgent when the region could not grow, and then it had to happen during the steepest demand curve in the company's history, with feature work deprioritised and AWS capacity added as well. A system whose primaries cannot move without an eighteen-month programme has a portability debt; pay it while demand is flat.

Apply on Monday

List the tables every request touches (sessions, users, permissions, feature flags, settings). For each, write down which cluster holds it, what else shares that cluster, and how long it would take to move it to its own primary in another region. If the answer for the identity tables is "the shared cluster" and "we have not planned it", that is the outage GitHub had in February 2026, waiting for your version of a cache TTL change.

07

The evidence wall

Every source behind this page, graded. GitHub publishes no ADRs; three posts that name a rejected design are graded as decision records. Page retrieval was by search excerpt; repositories were read first-hand with git. The full ledger with quotes is in sources.md.

Postmortem GitHub2018-10

October 21 post-incident analysis

A 43-second partition let orchestrator promote West Coast primaries; both coasts held writes the other lacked, so GitHub failed forward and ran degraded for 24 hours 11 minutes.

Carry forwardFailover policy must encode where the application can actually run, not only which replica is healthy.
github.blog/2018-10-30-oct21-post-incident-analysis/
Eng blog InfoQ2018-11

GitHub incident analysis

Independent account: about 40 minutes of West Coast writes before diagnosis; remediation includes no cross-region primary promotion and an active/active/active design.

Carry forwardRead the remediation list, then look for the follow-up that says it shipped. Here there is none.
www.infoq.com/news/2018/11/github-incident-analysis
Postmortem GitHub2020-03

February service disruptions post-incident analysis

Four events, 8 h 14 m, all from contention in mysql1: a misrouted heavy query, a ProxySQL descriptor limit of 65,536, an application query-pattern change.

Carry forwardOn a shared primary, every team's query change is a platform change.
github.blog/2020-03-26-february-service-disruptions-post-incident-anal
Postmortem GitHub2022-03

An update on recent service disruptions

Six months after the partitioning post, peak-load contention in mysql1 exhausted the database proxy's connections and failed writes across Git, PRs and Actions.

Carry forwardJudge a split by what remains on the shared cluster at peak.
github.blog/2022-03-23-an-update-on-recent-service-disruptions
Postmortem GitHub2024-08

GitHub Availability Report: August 2024

A database configuration change failed routing-layer health checks fleet-wide; the read-only endpoint vanished and github.com was down for all users for 36 minutes.

Carry forwardCap the fraction of a pool any single change can mark unhealthy.
github.blog/enterprise-software/availability-reports/github-availabili
Postmortem GitHub2026-03

Addressing GitHub's recent availability issues

A user-settings cache TTL cut from 12 h to 2 h, plus Monday peak and a model release, overloaded the core authentication and user-management cluster on 9 February.

Carry forwardCache TTLs in front of a shared store are capacity settings.
github.blog/news-insights/company-news/addressing-githubs-recent-avail
Postmortem GitHub2026-04

An update on GitHub availability

Agentic workflows accelerated sharply from late December 2025; a merge-queue regression hit 230 repositories and Elasticsearch overloaded in the same week.

Carry forwardWrite the priority order (availability, capacity, features) down before the load arrives.
github.blog/news-insights/company-news/an-update-on-github-availabilit
Postmortem GitHub2026-08

The August 17 outage, and the work ahead

A Central US component failed to scale at a new peak; a client retry loop slowed recovery. Monthly commits doubled from 1.4B to 2.9B since April; Azure carried 58% of load.

Carry forwardShip retry budgets in your own clients; recovery depends on them.
github.blog/news-insights/company-news/the-august-17-outage-and-the-wo
Postmortem GitHub2026-09

GitHub availability report: August 2026

First production MySQL primary served from Azure on 11 August; a 24-table authentication cohort moved off mysql1, removing about 1M QPS of replica reads.

Carry forwardThe residue of a partitioning programme is where the hot tables are.
github.blog/news-insights/company-news/github-availability-report-augu
Decision record GitHub2016-08

gh-ost: GitHub's online schema migration tool for MySQL

Rejects trigger-based migration: triggers are interpreted, share the query's transaction and contend for a second table's locks; GitHub would not run them concurrently.

Carry forwardMove change work off the primary's hot path; tail the log instead of hooking the transaction.
github.blog/2016-08-01-gh-ost-github-s-online-migration-tool-for-mysql
Decision record GitHub2018-06

MySQL High Availability at GitHub

Replaces VIP and DNS failover with orchestrator/raft across DCs, Consul KV and GLB/HAProxy writer pools, to remove split brain and DNS caching.

Carry forwardGood failover design moves the risk into policy; audit the policy for geography.
github.blog/2018-06-20-mysql-high-availability-at-github/
Decision record GitHub2021-09

Partitioning GitHub's relational databases to handle scale

mysql1 split by schema domain from 2019; receiving hosts' load down 50%; cross-domain transactions and polymorphic tables named as the hard cases.

Carry forwardDomains with shared polymorphic tables are the ones that stay behind; plan them first.
github.blog/2021-09-27-partitioning-githubs-relational-databases-scale
Decision record GitHub2026-10

Building Git infrastructure for agent-scale development

Spokes keeps five full replicas with a quorum commit, so read replicas slow writes; the replacement stores repositories in Azure Blob Storage with cache-like workers. 35x write throughput is an internal benchmark.

Carry forwardWhen writes dominate growth, separate durability from compute.
github.blog/engineering/architecture-optimization/building-git-infrast
Case study GitHub2023-12

Upgrading GitHub.com to MySQL 8.0

1,200+ hosts, 300+ TB, 50+ clusters, 5.5M QPS, a mix of Azure VMs and bare metal, upgraded over a year without SLO impact.

Carry forwardA fleet that can be upgraded in place is not the same as a fleet that can be moved.
github.blog/2023-12-07-upgrading-github-com-to-mysql-8-0/
Eng blog GitHub2016-04

Introducing DGit

Git replicated at the application layer: three copies on three servers, writes committed on two acknowledgements, automatic re-replication on server loss.

Carry forwardQuorum replication buys availability with write latency bound to the slowest replica.
github.blog/2016-04-05-introducing-dgit
Eng blog GitHub2017-08

Kubernetes at GitHub

Web and API moved from Unicorn, God, Puppet and Capistrano onto Kubernetes on GitHub's own metal, without changing the application's shape.

Carry forwardChanging the runtime underneath a monolith is cheaper than splitting it.
github.blog/2017-08-16-kubernetes-at-github/
Eng blog GitHub2018-09

Upgrading GitHub from Rails 3.2 to 5.2

Dual-booting against two lockfiles let the monolith move framework versions over about eighteen months without a long-lived branch.

Carry forwardMake the next version a CI target, not a branch.
github.blog/2018-09-28-upgrading-github-from-rails-3-2-to-5-2
Eng blog GitHub2021-01

Improving how we deploy GitHub

A single 2% canary missed problems; GitHub added a 20% stage and automated 5-minute gates.

Carry forwardA canary too small to see the fault is a delay, not a test.
github.blog/2021-01-25-improving-how-we-deploy-github/
Eng blog GitHub2021-08

GitHub's Engineering Team has moved to Codespaces

The monolith's development environment went from a 45-minute bootstrap to 10 seconds with shallow clones, nightly images and prebuild pools.

Carry forwardMonolith ergonomics are an engineering investment, and they are measurable.
github.blog/2021-08-11-githubs-engineering-team-moved-codespaces/
Eng blog GitHub2022-08

Introducing Trilogy

GitHub's own MySQL wire-protocol client, serving the monolith since 2015 and open-sourced in 2022, with no libmysqlclient dependency.

Carry forwardOwning the driver is how you control timeouts and failure behaviour at the edge of the store.
github.blog/2022-08-25-introducing-trilogy-a-new-database-adapter-for-
Eng blog The New Stack2025-10

GitHub will prioritize migrating to Azure over feature development

CTO memo: capacity-constrained in North Virginia, 18 months plus a 6-month buffer to leave owned DCs, earlier Azure moves halting.

Carry forwardPortability of the primaries is a capacity plan; schedule it before the region is full.
thenewstack.io/github-will-prioritize-migrating-to-azure-over-feature-
Source GitHub2026-05

gh-ost, feature-move-tables branch

From 15 May 2026, a --move-tables mode "to move tables between database clusters", with a mandatory postponed cut-over. Not merged to master as of 18 October 2026.

Carry forwardThe schema-change tool became the data-movement tool; the same binlog copier does both.
github.com/github/gh-ost/tree/feature-move-tables
Source GitHub2025-10

gh-ost PR #1595: Resume from checkpoint

Merged 16 October 2025: long migrations can resume from a checkpoint instead of restarting.

Carry forwardAt large table sizes, restartability matters more than raw copy speed.
github.com/github/gh-ost/pull/1595
Source GitHub2016-2026

gh-ost commit history

Commits per year fell from 667 (2016) to 20 (2023) and recovered to 87 in 2026, tracking GitHub's own need for the tool.

Carry forwardCommit cadence is a proxy for whether the owner still depends on a tool.
github.com/github/gh-ost
Source openark2025-02

orchestrator repository

Maintainer notice in February 2023 ("I will not be reviewing pull requests"); archived on 1 February 2025 with a pointer to Percona's fork.

Carry forwardThe failover brain of a fleet can become unmaintained while still in production elsewhere.
github.com/openark/orchestrator
Source GitHub2022-09

spokes-receive-pack

GitHub replaced git-receive-pack on the push path: "git-receive-pack does more than we need it to"; no outside contributions accepted.

Carry forwardOwning the hot path of a protocol lets you remove work, not only add capacity.
github.com/github/spokes-receive-pack
Paper Huang et al., OSDI '222022-07

Metastable Failures in the Wild

Survey of public incidents: retries are the most common sustaining effect, behind over half of the sustained overloads catalogued.

Carry forwardRecovery capacity must exceed steady capacity plus the retry load your clients will add.
www.usenix.org/conference/osdi22/presentation/huang-lexiang
Paper Google (Rae et al.), PVLDB 6(11)2013

Online, Asynchronous Schema Change in F1

Safe online schema change decomposes into intermediate states such that no server is more than one schema version behind.

Carry forwardgh-ost's postponed cut-over and move-tables are the single-cluster form of the same idea.
research.google/pubs/online-asynchronous-schema-change-in-f1/
Talk KubeCon NA 20172017-12

Kubernetes at GitHub (keynote, Jesse Newland)

GitHub presented its Kubernetes move as a conference keynote. Schedule listing only; the recording was not retrievable, so no timestamped claim is cited.

Carry forwardUse the blog post for claims; the talk confirms the programme was public.
kccncna17.sched.com/jessenewland
Talk Percona Live 20172017-04

Practical orchestrator, BoF, GitHub and other talks at Percona Live 2017

Orchestrator (50-minute hands-on session) and gh-ost (Jonah Berquist) presented as GitHub production tools. Session listing only.

Carry forwardThe tools were offered to the community as GitHub's own; their later maintenance follows the people.
code.openark.org/blog/mysql/practical-orchestrator-bof-github-and-othe
08

Build a miniature, then productionise it

Six rungs that reproduce GitHub's shape and its two dominant failures on a laptop. The line from toy to real is between rungs 3 and 4.

One app, one shared MySQL, one hot table

Run a small web app against a MySQL primary with two replicas (Docker Compose). Give it a users table every request reads and three feature tables that join it.

Done when: a load generator drives all four features and you can see per-table QPS.  Teaches: which tables are the shared core before anyone tells you.

Change a schema under load with gh-ost

Add a column to the busiest feature table with gh-ost while the load runs, then repeat with a trigger-based tool and compare primary latency.

Done when: you have p99 graphs for both runs.  Teaches: why GitHub rejected triggers in 2016.

Reproduce Class A: one local change, global outage

Cut a cache TTL in front of users from hours to minutes and double the load. Watch every feature degrade, including ones that never touch the cache.

Done when: an unrelated feature's error rate rises.  Teaches: the February 2026 mechanism.

Partition by domain, then measure the residue

Move two feature domains to their own primaries. Report load removed from the shared cluster and, separately, the share of peak QPS that remains on it.

Done when: both numbers are on one dashboard.  Teaches: why "50% removed" and "still the blast radius" are both true.

Move the hot cohort with a postponed cut-over

Copy users to a new primary by tailing the binlog, hold the cut-over behind a flag file, then flip it under load and record write unavailability.

Done when: the cut-over pause is measured in milliseconds to seconds and no write is lost.  Teaches: what the gh-ost move-tables branch is for.

Reproduce Class B: failover across a latency boundary

Put a replica behind 70 ms of injected latency, run orchestrator (or Percona's fork), partition the primary for 45 seconds and let it promote. Then forbid cross-boundary promotion and repeat.

Done when: you have divergent GTID sets in run one and none in run two.  Teaches: October 2018, and why geography belongs in failover policy.

09

Keep hunting

The queries and git commands that found the material above.

GitHub's own incident record

  • "GitHub availability report" mysql1
  • github.blog post-incident analysis orchestrator partition
  • "Addressing GitHub's recent availability issues"
  • "The August 17 outage, and the work ahead"

Design posts that name a rejected option

  • "Partitioning GitHub's relational databases" schema domains
  • "MySQL High Availability at GitHub" VIP DNS
  • "Building Git infrastructure for agent-scale development" Spokes
  • gh-ost triggerless "not prepared to run multiple concurrent"

Repositories, read with git

  • git ls-remote https://github.com/github/gh-ost | grep move
  • git log --format='%ad' --date=format:%Y | sort | uniq -c
  • git merge-base --is-ancestor <branch> origin/master

The hosting decision

  • GitHub Azure migration memo North Virginia capacity
  • GitHub AWS capacity 2026 Copilot agents
  • "ran a production MySQL primary from Azure"
10

References

  1. GitHub, October 21 post-incident analysis GitHub, 2018-10. Graded postmortem. Checked 2026-10-18.
  2. InfoQ, GitHub incident analysis InfoQ, 2018-11. Graded eng blog. Checked 2026-10-18.
  3. GitHub, February service disruptions post-incident analysis GitHub, 2020-03. Graded postmortem. Checked 2026-10-18.
  4. GitHub, An update on recent service disruptions GitHub, 2022-03. Graded postmortem. Checked 2026-10-18.
  5. GitHub, GitHub Availability Report: August 2024 GitHub, 2024-08. Graded postmortem. Checked 2026-10-18.
  6. GitHub, Addressing GitHub's recent availability issues GitHub, 2026-03. Graded postmortem. Checked 2026-10-18.
  7. GitHub, An update on GitHub availability GitHub, 2026-04. Graded postmortem. Checked 2026-10-18.
  8. GitHub, The August 17 outage, and the work ahead GitHub, 2026-08. Graded postmortem. Checked 2026-10-18.
  9. GitHub, GitHub availability report: August 2026 GitHub, 2026-09. Graded postmortem. Checked 2026-10-18.
  10. GitHub, gh-ost: GitHub's online schema migration tool for MySQL GitHub, 2016-08. Graded decision record. Checked 2026-10-18.
  11. GitHub, MySQL High Availability at GitHub GitHub, 2018-06. Graded decision record. Checked 2026-10-18.
  12. GitHub, Partitioning GitHub's relational databases to handle scale GitHub, 2021-09. Graded decision record. Checked 2026-10-18.
  13. GitHub, Building Git infrastructure for agent-scale development GitHub, 2026-10. Graded decision record. Checked 2026-10-18.
  14. GitHub, Upgrading GitHub.com to MySQL 8.0 GitHub, 2023-12. Graded case study. Checked 2026-10-18.
  15. GitHub, Introducing DGit GitHub, 2016-04. Graded eng blog. Checked 2026-10-18.
  16. GitHub, Kubernetes at GitHub GitHub, 2017-08. Graded eng blog. Checked 2026-10-18.
  17. GitHub, Mitigating replication lag and reducing read load with freno GitHub, 2017-10. Graded eng blog. Checked 2026-10-18.
  18. GitHub, Upgrading GitHub from Rails 3.2 to 5.2 GitHub, 2018-09. Graded eng blog. Checked 2026-10-18.
  19. GitHub, Improving how we deploy GitHub GitHub, 2021-01. Graded eng blog. Checked 2026-10-18.
  20. GitHub, GitHub's Engineering Team has moved to Codespaces GitHub, 2021-08. Graded eng blog. Checked 2026-10-18.
  21. GitHub, Introducing Trilogy GitHub, 2022-08. Graded eng blog. Checked 2026-10-18.
  22. GitHub, Building GitHub with Ruby and Rails GitHub, 2023-04. Graded eng blog. Checked 2026-10-18.
  23. The New Stack, GitHub will prioritize migrating to Azure over feature development The New Stack, 2025-10. Graded eng blog. Checked 2026-10-18.
  24. The Register, Microsoft's GitHub suspends Copilot account sign-ups The Register, 2026-04. Graded eng blog. Checked 2026-10-18.
  25. The Register, So long, Spokes The Register, 2026-10. Graded eng blog. Checked 2026-10-18.
  26. Shlomi Noach, Reducing my OSS involvement, and how it affects orchestrator & gh-ost Shlomi Noach, 2023-02. Graded eng blog. Checked 2026-10-18.
  27. GitHub, gh-ost, feature-move-tables branch GitHub, 2026-05. Graded source. Checked 2026-10-18.
  28. GitHub, gh-ost PR #1595: Resume from checkpoint GitHub, 2025-10. Graded source. Checked 2026-10-18.
  29. GitHub, gh-ost commit history GitHub, 2016-2026. Graded source. Checked 2026-10-18.
  30. openark, orchestrator repository openark, 2025-02. Graded source. Checked 2026-10-18.
  31. GitHub, spokes-receive-pack GitHub, 2022-09. Graded source. Checked 2026-10-18.
  32. Huang et al., OSDI '22, Metastable Failures in the Wild Huang et al., OSDI '22, 2022-07. Graded paper. Checked 2026-10-18.
  33. Google (Rae et al.), PVLDB 6(11), Online, Asynchronous Schema Change in F1 Google (Rae et al.), PVLDB 6(11), 2013. Graded paper. Checked 2026-10-18.
  34. KubeCon NA 2017, Kubernetes at GitHub (keynote, Jesse Newland) KubeCon NA 2017, 2017-12. Graded talk. Checked 2026-10-18.
  35. Percona Live 2017, Practical orchestrator, BoF, GitHub and other talks at Percona Live 2017 Percona Live 2017, 2017-04. Graded talk. Checked 2026-10-18.