Databases

MySQL Group Replication in 2026: Building a Cluster with Automatic Failover Without External Tools

Ruslan Ismailov Published 12 min read
M

Introduction: Why Master-Slave Replication Is No Longer Enough

Classic master-slave replication in MySQL solved the problem of horizontal read scaling, but was never designed for automatic failover. When the master went down, an engineer had to manually promote a replica, update the connection string in the application, check the binary log position — all of this typically happening on a Friday night to the sound of alerts.

The problems with classic replication are well known: asynchronous operation (replicas can lag behind), no built-in automatic failover at the MySQL level, risk of transaction loss during switchover, and the need for external tools like MHA or Orchestrator for automation. In 2026, when most products have SLA requirements of 99.9% or higher, this approach is unacceptable for critical systems.

MySQL Group Replication is a built-in clustering mechanism introduced in MySQL 5.7.17 and significantly enhanced in versions 8.0 and 8.4. It provides synchronous transaction-level consensus, automatic failover, and support for multiple operating modes — without a single line of external code. If you manage MySQL in production yourself and don't want to move to cloud-managed solutions, Group Replication is the most mature choice for building MySQL high availability.

MySQL Group Replication Architecture

Two Operating Modes: Single-Primary and Multi-Primary

Group Replication supports two modes. In single-primary mode, one node acts as the primary and handles all write operations, while the others are secondary nodes available for reads only. This is the safest and recommended mode: it eliminates write conflicts between nodes and matches the familiar "single master" semantics.

In multi-primary mode, all nodes accept writes simultaneously. This increases write throughput but requires careful handling of conflicts: two concurrent UPDATE statements on the same row from different nodes will cause one of the transactions to be rolled back. This mode is suited for specific scenarios involving per-node sharding or very infrequent conflicts.

Paxos Consensus and Quorum

Under the hood, Group Replication uses an adapted Paxos consensus algorithm (specifically, the XCom implementation). Before a transaction is committed, the group must reach consensus: a majority of nodes (quorum) must confirm receipt of the event. For a three-node cluster, the quorum is two nodes. This means:

  • If one node fails, the cluster continues operating.
  • If two out of three nodes fail, the cluster loses quorum and halts writes (protection against split-brain).
  • The minimum recommended number of nodes is three; five nodes are recommended for higher fault tolerance.

Each transaction receives a global identifier (GTID) and is atomically delivered to all group members. A transaction is considered committed only after quorum confirmation — this is the fundamental difference from asynchronous replication, where the master does not wait for replicas.

Infrastructure Requirements

Deploying a Group Replication cluster requires meeting several conditions:

  • MySQL version: 8.0.27+ or 8.4.x (the LTS branch, recommended in 2026). MySQL 8.4 brought improvements to the automatic member recovery process and simplified syntax for several commands.
  • Storage engine: InnoDB only. Tables using MyISAM or other engines are not supported by the group.
  • Primary keys: every table must have a primary key — without one, Group Replication will refuse to commit changes.
  • Network: low latency between nodes (ideally under 5 ms RTT). The group uses a dedicated port for internal communication (default: 33061). All nodes must be able to reach each other on this port.
  • Hosts: unique server_id, unique server_uuid, synchronized time (NTP/chrony is required).
  • GTID: must be enabled on all nodes (gtid_mode=ON, enforce_gtid_consistency=ON).

Step-by-Step Setup of a Three-Node Cluster

my.cnf Configuration

Example configuration for the first node (node1). For node2 and node3, change server_id, report_host, and loose-group_replication_local_address:

# /etc/mysql/mysql.conf.d/mysqld.cnf — node1

[mysqld]
# Basic parameters
server_id = 1
bind-address = 0.0.0.0
report_host = node1.example.com

# GTID
gtid_mode = ON
enforce_gtid_consistency = ON

# Binary log
log_bin = mysql-bin
binlog_format = ROW
binlog_checksum = NONE          # required for GR
log_slave_updates = ON

# Group Replication — plugin
plugin_load_add = group_replication.so

# Group name — UUID, identical for all nodes
loose-group_replication_group_name = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"

# Local node address for internal GR communication
loose-group_replication_local_address = "node1.example.com:33061"

# List of all group nodes
loose-group_replication_group_seeds = \
  "node1.example.com:33061,node2.example.com:33061,node3.example.com:33061"

# Do not start GR automatically on MySQL startup
loose-group_replication_start_on_boot = OFF

# Single-primary mode (recommended)
loose-group_replication_single_primary_mode = ON
loose-group_replication_enforce_update_everywhere_checks = OFF

# Recovery via cloning (MySQL 8.0.17+)
loose-group_replication_recovery_use_ssl = OFF

Initializing the Group on the First Node

After starting MySQL on all three nodes, perform the following steps on node1:

-- 1. Create the replication user for intra-group communication
CREATE USER 'repl'@'%' IDENTIFIED BY 'StrongPassword123!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
GRANT CONNECTION_ADMIN ON *.* TO 'repl'@'%';
GRANT BACKUP_ADMIN ON *.* TO 'repl'@'%';   -- required for cloning
FLUSH PRIVILEGES;

-- 2. Configure the recovery channel
CHANGE MASTER TO
  MASTER_USER='repl',
  MASTER_PASSWORD='StrongPassword123!'
  FOR CHANNEL 'group_replication_recovery';

-- 3. Bootstrap the group (on the bootstrap node only!)
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;

-- 4. Check the status
SELECT * FROM performance_schema.replication_group_members;

Adding node2 and node3

On each of the remaining nodes, run the following (without bootstrapping):

-- On node2 and node3 (identical)
CREATE USER 'repl'@'%' IDENTIFIED BY 'StrongPassword123!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
GRANT CONNECTION_ADMIN ON *.* TO 'repl'@'%';
GRANT BACKUP_ADMIN ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

CHANGE MASTER TO
  MASTER_USER='repl',
  MASTER_PASSWORD='StrongPassword123!'
  FOR CHANNEL 'group_replication_recovery';

-- Simply start — the node will discover the group via seeds
START GROUP_REPLICATION;

-- Verify the node has joined the group
SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE
FROM performance_schema.replication_group_members;

After all three nodes have successfully joined, the replication_group_members table will show three rows with the status ONLINE: one with the role PRIMARY and two with the role SECONDARY.

Automatic Failover: How the Cluster Elects a New Leader

This is the key advantage of MySQL Group Replication over classic replication. When the primary node becomes unavailable, the group initiates an election automatically:

  1. The remaining nodes detect the loss of connection to the primary through the failure detection mechanism (the timeout is configured via group_replication_member_expel_timeout, default 5 seconds).
  2. The group checks for quorum. If two out of three nodes are available, quorum is maintained.
  3. A new primary is elected from the secondary nodes based on weight: group_replication_member_weight (priority, default 50) and MySQL version are taken into account. The node with the higher weight becomes the primary.
  4. The new primary switches to read-write mode; the secondary nodes remain read-only.
  5. All of this happens without administrator intervention, typically within 10–30 seconds.

To control election priority, set the weight explicitly:

-- On node2: increase priority for the preferred primary
SET GLOBAL group_replication_member_weight = 70;

-- On node3: keep the default priority
SET GLOBAL group_replication_member_weight = 50;

Monitoring Group Status

MySQL Group Replication is deeply integrated with performance_schema. Key tables for monitoring:

  • performance_schema.replication_group_members — the state and role of each node.
  • performance_schema.replication_group_member_stats — transaction statistics: certification queue, conflicts, latencies.
  • performance_schema.replication_connection_status — recovery channel status.
-- Overall group status
SELECT
  MEMBER_HOST,
  MEMBER_PORT,
  MEMBER_STATE,
  MEMBER_ROLE,
  MEMBER_VERSION
FROM performance_schema.replication_group_members
ORDER BY MEMBER_ROLE;

-- Certification statistics and conflict queue
SELECT
  MEMBER_ID,
  COUNT_TRANSACTIONS_IN_QUEUE,
  COUNT_TRANSACTIONS_CHECKED,
  COUNT_CONFLICTS_DETECTED,
  COUNT_TRANSACTIONS_ROWS_VALIDATING
FROM performance_schema.replication_group_member_stats;

For automated alerting, integrate these queries into Prometheus via mysqld_exporter or set up periodic checks using custom monitoring scripts. Critical metrics to alert on: MEMBER_STATE != 'ONLINE' and a growing COUNT_CONFLICTS_DETECTED.

Common Issues and How to Resolve Them

Split-Brain and Network Partitioning

If the network between nodes splits in such a way that no subgroup has quorum, Group Replication moves all nodes into ERROR state and refuses to accept writes. This is correct behavior — it is better to stop writes than to allow data divergence. After the network is restored, the nodes must be restarted:

STOP GROUP_REPLICATION;
START GROUP_REPLICATION;

Transaction Conflicts in Multi-Primary Mode

In multi-primary mode, Group Replication uses an optimistic certification mechanism: a transaction is rolled back if another node committed a change to the same row first. The application must handle the error ERROR 1180 (HY000): Got error 149 and retry the transaction. Minimize conflicts by sharding requests across nodes or switching to single-primary mode.

Node Cannot Join the Group

A common cause is a divergence in GTID sets. If a node has been unavailable for a long time, Group Replication activates the distributed recovery mechanism on startup: the node copies missing data from a donor node via cloning (if the mysql_clone.so plugin is installed) or via binary logs. Make sure the clone plugin is installed on all nodes:

INSTALL PLUGIN clone SONAME 'mysql_clone.so';
GRANT CLONE_ADMIN ON *.* TO 'repl'@'%';

Integration with MySQL Router

The application should not need to know which node is currently the primary. MySQL Router is a lightweight proxy from Oracle that automatically routes requests: write operations are directed to the primary, reads go to the secondary. It is included with MySQL Shell and distributed free of charge.

Minimal MySQL Router configuration for a Group Replication cluster:

# /etc/mysqlrouter/mysqlrouter.conf

[DEFAULT]
logging_folder = /var/log/mysqlrouter
runtime_folder = /run/mysqlrouter

[logger]
level = INFO

# Write port — routes only to PRIMARY
[routing:gr_rw]
bind_address = 0.0.0.0
bind_port = 6446
destinations = metadata-cache://mycluster/?role=PRIMARY
routing_strategy = first-available
protocol = classic

# Read port — load-balances across SECONDARY nodes
[routing:gr_ro]
bind_address = 0.0.0.0
bind_port = 6447
destinations = metadata-cache://mycluster/?role=SECONDARY
routing_strategy = round-robin-with-fallback
protocol = classic

[metadata_cache:mycluster]
cluster_type = gr
router_id = 1
user = router_user
metadata_cluster = mycluster
ttl = 0.5
auth_cache_ttl = -1

After an automatic failover, MySQL Router will detect the primary change within the time defined by the ttl parameter (0.5 seconds in the example) and begin routing writes to the new primary node. The application reconnects transparently.

To initialize cluster metadata in MySQL Router, use MySQL Shell:

mysqlsh --uri root@node1.example.com:3306 -- dba configureInstance
mysqlsh --uri root@node1.example.com:3306 -- dba createCluster mycluster
mysqlrouter --bootstrap root@node1.example.com:3306 --directory /etc/mysqlrouter --conf-use-gr-notifications

Comparison with MySQL InnoDB Cluster and Galera Cluster

MySQL InnoDB Cluster is a layer built on top of Group Replication that includes MySQL Shell (cluster management via JavaScript/Python API) and MySQL Router. In essence, InnoDB Cluster uses Group Replication as its transport layer. If you want to manage the cluster through a convenient API and are willing to use MySQL Shell, choose InnoDB Cluster. If you prefer a minimal stack and plain SQL, use Group Replication directly.

Galera Cluster (Percona XtraDB Cluster / MariaDB Galera) is an independent implementation of synchronous multi-primary replication that predates Group Replication. Galera is battle-tested, works well in multi-primary mode, but requires installing third-party packages (Percona or MariaDB) and has its own ecosystem. Group Replication is the official Oracle solution built into MySQL 8.x, simplifying support and licensing. In 2026, for new projects on vanilla MySQL, the choice of Group Replication is clear.

Key differences at a glance:

  • Group Replication: built into MySQL 8.x, supported by Oracle, single/multi-primary, Paxos consensus.
  • InnoDB Cluster: Group Replication + MySQL Shell + MySQL Router, easier management.
  • Galera: third-party package, mature multi-primary, different ecosystem.

Conclusion: When to Choose Group Replication

MySQL Group Replication is the right choice if:

  • You are running MySQL 8.0+ and want automatic failover without external tools.
  • Your SLA requirements do not allow for manual intervention when the primary fails.
  • You manage your own infrastructure and do not want to migrate to cloud-managed databases.
  • Your workload is predominantly read-heavy with moderate writes (single-primary mode).

When to consider alternatives:

  • You need maximum write throughput with minimal conflicts — Galera in multi-primary mode may be better tuned for that scenario.
  • You are already using the Percona or MariaDB ecosystem.
  • Network latency between nodes exceeds 10–15 ms — synchronous consensus will start to noticeably impact write latency.

In 2026, MySQL Group Replication combined with MySQL Router is a production-ready high availability solution for MySQL that requires neither cloud services nor external tools like Orchestrator. Invest time in getting the initial configuration right, set up monitoring through performance_schema — and your cluster will self-heal without requiring an on-call engineer.

Technologies

Tags

Ruslan Ismailov

Senior Web / Backend Developer. Senior web/backend developer with 9 years of experience. Stack: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, microservices, CI/CD. More about me →