Skip to main content

Incident · Senior

GitHub 2012: failover promotes a lagging replica

Real incident. Key points: Consensus Algorithms, Availability Patterns, and Consistency Patterns.

14 min read · Incident on 2012, lasted · Source: GitHub · Content reviewed on October 23, 2026

Short answer

Real incident. Key points: Consensus Algorithms, Availability Patterns, and Consistency Patterns. The availability post GitHub published in September 2012 is the source of this case. It describes two outages early in the same week and points to the automatic failover of the main production database as the root cause of both.

01 · CONTEXT

A new cluster that switches primaries on its own

The availability post GitHub published in September 2012 is the source of this case. It describes two outages early in the same week and points to the automatic failover of the main production database as the root cause of both.

In mid-August, operations replaced a pair of DRBD-based MySQL servers with a three-node cluster. The cluster presents the application with two virtual IPs, one read-write and one read-only, managed by Pacemaker and Heartbeat. Percona Replication Manager coordinates replication and moves the active role (the master that accepts reads and writes) and the standby role (read-only replica) between the nodes.

According to the post, the new design gave more efficient failovers. In the previous architecture, switching databases required a cold start of MySQL; in the new cluster MySQL runs on all nodes all the time, and failover just moves the virtual IP after flushing transactions and setting the read_only variable.

  1. The application talks to the database through the read-write virtual IP, which points to the node in the active role.

    Architecture diagram: MySQL cluster with Pacemaker and Percona Replication Manager
    CPApplication
    NWRead-write virtual IP
    DBActive nodeativo
    DBStandby node
    DBThird node
    NWPacemaker and Percona Replication Manager
  2. The standby node is a read-only replica of the active node.

    Architecture diagram: MySQL cluster with Pacemaker and Percona Replication Manager
    CPApplication
    NWRead-write virtual IP
    DBActive node
    DBStandby nodestandby
    DBThird node
    NWPacemaker and Percona Replication Manager
  3. The cluster manager runs the health checks and moves the virtual IP and the roles between the nodes.

    Architecture diagram: MySQL cluster with Pacemaker and Percona Replication Manager
    CPApplication
    NWRead-write virtual IP
    DBActive node
    DBStandby node
    DBThird node
    NWPacemaker and Percona Replication Managerdecides the failover
  4. Since MySQL already runs on all nodes, failover boils down to moving the virtual IP, with no cold start.

    Architecture diagram: MySQL cluster with Pacemaker and Percona Replication Manager
    CPApplication
    NWRead-write virtual IPonly the IP moves
    DBActive node
    DBStandby node
    DBThird node
    NWPacemaker and Percona Replication Manager

02 · MONDAY

Two failovers nobody wanted

It started with a database migration that generated more load than operations had ever seen from this kind of migration. The load was so heavy that the Percona Replication Manager health checks failed on the master.

In response, the manager moved the active role to another server in the cluster and stopped MySQL on the node it judged failed. The chosen database had a cold InnoDB buffer pool and performed poorly; the site's query load on that cold cache soon made the health checks fail again, and the active role went back to the original server.

  1. With the migration load, the manager's health checks fail on the active node.

    Architecture diagram: Failover to a node with a cold buffer pool
    CPApplication
    NWRead-write virtual IP
    NWPercona Replication Manager
    DBOriginal active nodehealth check failed
    DBChosen node
  2. The manager moves the active role to another server and stops MySQL on the node it judged failed.

    Architecture diagram: Failover to a node with a cold buffer pool
    CPApplication
    NWRead-write virtual IP
    NWPercona Replication Manager
    DBOriginal active nodeMySQL stopped
    DBChosen nodenew active
  3. The chosen node has a cold InnoDB buffer pool and responds poorly to the site's query load.

    Architecture diagram: Failover to a node with a cold buffer pool
    CPApplication
    NWRead-write virtual IP
    NWPercona Replication Manager
    DBOriginal active node
    DBChosen nodecold buffer pool
  4. The health checks fail again and the active role returns to the server where it was.

    Architecture diagram: Failover to a node with a cold buffer pool
    CPApplication
    NWRead-write virtual IP
    NWPercona Replication Manager
    DBOriginal active noderole back
    DBChosen nodehealth check failed
  5. The author of the post turns on maintenance-mode, in which the manager performs no health checks or automatic failover.

    Architecture diagram: Failover to a node with a cold buffer pool
    CPApplication
    NWRead-write virtual IP
    NWPercona Replication Managermaintenance-mode
    DBOriginal active node
    DBChosen node

Site performance recovered gradually, as the buffer pool reached normal levels.

03 · TUESDAY

The partition and the election of the lagging node

The next morning, a developer alerted operations to incorrect query results coming from the node in the standby role. The investigation concluded that the previous day's maintenance-mode had prevented actions that would make the node elected as standby switch replication masters and start replicating.

While trying to turn maintenance-mode off, a Pacemaker segfault occurred that resulted in a partition of the cluster state. Two nodes, called a and b, rejected most of the messages from the third, c, while c rejected most of the messages from the other two.

In the first cluster, the election was interrupted by messages from the second and MySQL was stopped. In the second, a single-node one, node c was elected and later messages from the two-node cluster were discarded. Node c was precisely the one operations had already determined to be out of date.

The team detected the problem and shut down the out-of-date node, to end the partition and prevent further data divergence. As a result, all access to the production database, and therefore to github.com, went down.

  1. The three nodes exchange cluster messages, and the cluster requires majority agreement before acting.

    Architecture diagram: Cluster partition and election of the lagging node
    DBNode a
    DBNode b
    DBNode c
  2. A Pacemaker segfault partitions the cluster: a and b reject most of c's messages, and c rejects theirs.

    Architecture diagram: Cluster partition and election of the lagging node
    DBNode a
    DBNode b
    DBNode cpartition
  3. In the cluster of a and b, the master election is interrupted by messages from the other side and MySQL is stopped.

    Architecture diagram: Cluster partition and election of the lagging node
    DBNode aMySQL stopped
    DBNode bMySQL stopped
    DBNode c
  4. In the single-node cluster, c is elected, and c was the node operations had already determined to be out of date.

    Architecture diagram: Cluster partition and election of the lagging node
    DBNode a
    DBNode b
    DBNode celected and out of date
  5. The team shuts down the out-of-date node to end the partition, and all access to the production database goes down.

    Architecture diagram: Cluster partition and election of the lagging node
    DBNode a
    DBNode b
    DBNode cdesligado

04 · THE DAMAGE

Data out of sync between stores

The data divergence made inconsistencies between MySQL and other data stores possible. GitHub uses Redis to look up dashboard feed entries and repository routes from ids automatically generated by MySQL; for records created in the window, the relationships between the two stores went out of sync.

Effect described by the sourceContexto
DashboardsSome events created in the window appeared on the wrong users' dashboardsRedis is queried with ids generated by MySQL
RoteamentoSome repositories created in the window were routed incorrectlyThe relationships between the stores went out of sync
Private repositoriesSixteen private repositories became accessible to people who were not collaborators or team membersFor seven minutes, according to the post

05 · THE DECISION

Failover only when operations says so

The post states that if someone in operations had been asked whether the failover should have occurred, the answer would be an unequivocal no. It notes that there are many situations in which automatic failover is a great availability strategy, but concludes that availability of the primary production database is not one of them.

For that reason, the Pacemaker configuration was changed so that failover of the active role occurs only when initiated by a member of operations. The company is also investigating ways to keep unavoidable failovers from hurting performance, including mechanisms to warm the buffer pool of the slave databases, and is auditing the Pacemaker and Heartbeat stack.

  1. Failover of the active role now depends on a member of operations, and the manager does not initiate it on its own.

    Architecture diagram: Active-role failover initiated by operations
    CLOperations teamdecide
    NWPacemaker
    NWRead-write virtual IP
    DBActive node
    DBStandby node
  2. For unavoidable failovers, the company is investigating ways to warm the buffer pool of the slave databases.

    Architecture diagram: Active-role failover initiated by operations
    CLOperations team
    NWPacemaker
    NWRead-write virtual IP
    DBActive node
    DBStandby nodewarming under study
  3. The Pacemaker and Heartbeat stack undergoes an audit focused on the code path that triggered the segfault.

    Architecture diagram: Active-role failover initiated by operations
    CLOperations team
    NWPacemakerunder audit
    NWRead-write virtual IP
    DBActive node
    DBStandby node

Frequently asked questions

What is GitHub 2012: failover promotes a lagging replica?

Real incident. Key points: Consensus Algorithms, Availability Patterns, and Consistency Patterns.

What does the GitHub 2012: failover promotes a lagging replica design cover?

It is organized in these sections: A new cluster that switches primaries on its own, Two failovers nobody wanted, The partition and the election of the lagging node, Data out of sync between stores, and Failover only when operations says so.

How long is GitHub 2012: failover promotes a lagging replica and what level is it?

It takes about 14 minutes to read and is rated Senior level.

Now design it yourself

Run this case as an interview in the System Design school: you make the decisions, the tutor challenges them and you see how your design scores.