Rebuilding Search for High Availability in GitHub Enterprise Server: A Step-by-Step Guide

Introduction

Search is the backbone of GitHub Enterprise Server. From issue filters and pull request counts to the releases and projects pages, nearly every interaction depends on reliable, fast search indexes. For years, administrators managing High Availability (HA) setups faced a tricky balancing act: keeping Elasticsearch clusters healthy across primary and replica nodes while avoiding locked states and index corruption. This guide walks through the exact process GitHub engineering used to rebuild the search architecture, eliminating fragility and making HA maintenance far less risky. Whether you're planning a migration or just want to understand the logic behind the changes, these steps cover the core challenges, attempted fixes, and the final architecture shift that delivered durability.

Rebuilding Search for High Availability in GitHub Enterprise Server: A Step-by-Step Guide
Source: github.blog

What You Need

Step 1: Understand the Problem with Elasticsearch Clustering Across HA Nodes

Before any rebuild, you must grasp why the old approach failed. In GitHub Enterprise Server HA, the primary node handles all writes and traffic, while replicas stay in sync as read-only followers. Elasticsearch was originally integrated as a cluster spanning both primary and replica nodes. This allowed each node to serve search requests locally, but it introduced a critical flaw: Elasticsearch could elect a primary shard on a replica node. If that replica went down for maintenance, the entire search subsystem could lock up. The replica would wait for Elasticsearch to become healthy, but Elasticsearch couldn’t recover until the replica rejoined—a classic deadlock.

Additionally, upgrades had to follow a precise order; any deviation could corrupt indexes or leave them locked. The clustering across servers gave performance benefits but made the system brittle. Your first job is to document this topology in your environment and map every dependency.

Step 2: Implement Health Checks and Drift Correction

Based on the initial discovery, GitHub engineers added layers of monitoring. They implemented checks to verify Elasticsearch cluster health before allowing replica promotions or maintenance windows. These checks confirmed that all shards were allocated and that no primary shards resided on a replica that might be taken offline.

If drifting state occurred (e.g., a replica became unhealthy while still holding a primary shard), automated scripts tried to reallocate shards or restart Elasticsearch in a safe sequence. However, these were reactive measures, not a cure. They reduced incidents but did not eliminate the root cause. In your rebuild, you should replicate these checks as a temporary safeguard while you design the permanent fix.

Step 3: Attempt a Search Mirroring System

The next major attempt was to build a “search mirroring” system—an alternative that would decouple search data from the HA replication layer. The idea was to have a separate, dedicated Elasticsearch cluster that synchronizes with the primary node independently, avoiding the cross-node shard movement problem.

Database replication is notoriously hard, and GitHub discovered that mirroring without consistency guarantees caused data mismatches. The effort required strong consistency, which conflicted with the eventual consistency model Elasticsearch uses by default. After extensive prototyping, this approach was shelved because it couldn’t meet the reliability bar for production.

Key takeaway from this step: do not rely on naive mirroring. Any solution must preserve consistency and be testable in your staging environment.

Step 4: Adopt a Decoupled Elasticsearch Architecture

The final solution came from stepping back and questioning the assumption that Elasticsearch must be part of the HA cluster. GitHub engineering moved Elasticsearch to a independent cluster that runs separately from the primary/replica topology. This cluster has its own replication and failover, managed entirely by Elasticsearch’s native mechanisms. The primary and replica nodes of GitHub Enterprise Server still exist, but they no longer participate in the Elasticsearch cluster.

Rebuilding Search for High Availability in GitHub Enterprise Server: A Step-by-Step Guide
Source: github.blog

Instead, search requests are routed to the Elasticsearch cluster, which is designed to be resilient independently. If a GitHub replica goes down for maintenance, Elasticsearch continues serving without deadlock. Upgrades become simpler: you can upgrade Elasticsearch nodes in rolling fashion without affecting GitHub server operations.

Implementation steps for this architecture:

  1. Provision a new, dedicated Elasticsearch cluster (e.g., 3 nodes for production).
  2. Configure the GitHub Enterprise Server primary to index data into this new cluster (instead of the old local instance).
  3. Set up replication within the Elasticsearch cluster (e.g., ensure at least one replica shard per index).
  4. Update all search endpoints (issues, releases, projects, counts) to point to the new cluster URL.
  5. Perform a full reindex from GitHub to the new Elasticsearch cluster.
  6. Test all search features in a non-production environment.
  7. Switch traffic to the new cluster and decommission the old cross-node setup.

This change eliminated the primary shard on replica problem entirely. It also simplified maintenance: administrators no longer need to follow a specific order when applying updates.

Tips for a Successful Search Architecture Rebuild

By following these steps, you can rebuild your GitHub Enterprise Server search architecture to be truly high available, reducing maintenance risks and allowing your team to focus on what matters—improving the user experience.

Tags:

Recommended

Discover More

PyPI Supply Chain Attack: OceanLotus Linked to New ZiChatBot MalwareNew Single-Cell Imaging Technique Reveals the Dynamics of Stalled DNA ReplicationHow to Interpret Satellite Evidence of Cyclone-Triggered Landslides: A Step-by-Step GuideGitHub Copilot Individual Plans: Key Changes to Safeguard Service ReliabilityDreaming of CSS ::nth-letter: Why It Doesn't Exist and How to Fake It