MariaDB high availability reached a new baseline with MariaDB Server 12.3 LTS, GA on 2026-05-29 as version 12.3.2. For the first time, a MariaDB LTS release ships parallel replication between Galera Clusters (MDEV-20065), closing the throughput gap that constrained multi-datacenter MariaDB high availability designs for years. This guide walks through the complete maximum availability stack on MariaDB 12.3 LTS — GTID-based asynchronous and semi-synchronous replication, Galera Cluster, cluster-to-cluster disaster recovery, and MaxScale automated failover — with tested configuration, the system tables and status variables that prove each layer is healthy, and the upgrade risks you must clear before production.
Every MariaDB high availability recommendation here is version-pinned to MariaDB Community Server 12.3 LTS (with 11.8 LTS noted where behavior differs) and anchored to a named metric or system table. Test everything in a staging environment that mirrors production before applying any change, and maintain a verified backup and disaster recovery posture throughout.
What Maximum Availability Means in Measurable Terms
Maximum availability is not a product SKU — it is an engineering outcome defined by two numbers: Recovery Point Objective (RPO), the data you can afford to lose, and Recovery Time Objective (RTO), the downtime you can afford to absorb. A MariaDB high availability architecture is only as good as the RPO/RTO it can demonstrate under a live failover drill.
MariaDB 12.3 LTS lets you engineer three distinct tiers:
- RPO ≈ seconds, RTO ≈ seconds to minutes — GTID-based asynchronous replication with MaxScale automated failover.
- RPO ≈ 0 (per committed transaction), RTO ≈ seconds — semi-synchronous replication with automated failover.
- RPO = 0, RTO ≈ seconds — Galera Cluster synchronous multi-primary replication, extended across datacenters with cluster-to-cluster asynchronous replication.
Treat these tiers as measurable service levels, not marketing labels. An availability SLO of 99.99% allows roughly 52 minutes of downtime per year — a budget that a single unrehearsed failover can consume entirely. That is why every MariaDB high availability design decision below is paired with the status variable, system table, or log line that proves it works, and why the article closes with the drill program that converts configuration into demonstrated RPO/RTO.
The rest of this article builds each tier bottom-up, then combines them into the reference architecture we deploy for production MariaDB high availability engagements.
MariaDB 12.3 LTS: The Availability-Relevant Release Surface
The MariaDB 12.3 changes and improvements notes contain a dense cluster of replication and Galera work relevant to MariaDB high availability. These are the changes that matter operationally:
| Change | Tracking | Operational impact |
|---|---|---|
| Asynchronous replication between two Galera Clusters can use parallel replication, controlled by slave_parallel_threads | MDEV-20065 | Removes the single-threaded applier ceiling on cluster-to-cluster DR links |
| Write set apply retry via wsrep_applier_retry_count | MDEV-36077 | Transient applier conflicts retry instead of forcing node aborts |
| Unnecessary foreign key checks avoided during Incremental State Transfer (IST) | MDEV-34822 | Faster node rejoin after short outages |
| Binary logging performance improved by removing a synchronization requirement | MDEV-34705 | Lower commit-path latency on binlog-enabled primaries |
| ROW events larger than max_packet_size can be fragmented | MDEV-32570 | Large-row workloads stop breaking replication |
| Galera package dependency removed from server packages | MDEV-38744 | Install the Galera provider package explicitly on cluster nodes |
Carry-over from 11.8 LTS that completes the picture: slave_abort_blocking_timeout (MDEV-34857) automatically aborts long-running transactions that block the replication applier, and asynchronous rollback during crash recovery lets a recovering server accept connections before large rollbacks finish — measure recovery as startup-to-accepting-connections, not total rollback completion.
Tier 1: GTID Replication with Semi-Synchronous Commit
Standard replication remains the foundation of MariaDB high availability. On 12.3 LTS, always run it with GTID (MariaDB format: Domain-ServerID-Sequence) so failover targets can be repointed without file/position arithmetic.
Primary and Replica Configuration
# /etc/my.cnf.d/replication.cnf -- MariaDB 12.3 LTS # Restart required for server_id and log_bin changes [mariadb] server_id = 101 # unique per server log_bin = mariadb-bin binlog_format = ROW log_slave_updates = ON gtid_domain_id = 1 # distinct per replication domain gtid_strict_mode = ON # Durability on the primary: RPO depends on these two innodb_flush_log_at_trx_commit = 1 sync_binlog = 1 # Parallel applier on replicas slave_parallel_threads = 8 # size from workload, see below slave_parallel_mode = optimistic
Point the replica at the primary using GTID:
CHANGE MASTER TO
MASTER_HOST = 'primary.db.internal',
MASTER_USER = '${REPL_USER}',
MASTER_PASSWORD = '${REPL_PASSWORD}',
MASTER_USE_GTID = slave_pos,
MASTER_SSL = 1;
START REPLICA;
Asynchronous replication alone leaves a nonzero RPO: transactions committed on the primary but not yet shipped are lost on failover. Semi-synchronous replication, built into MariaDB Server (no plugin installation required since 10.3), closes that gap by refusing to acknowledge a commit to the client until at least one replica has received the event:
-- Primary (dynamic, no restart) SET GLOBAL rpl_semi_sync_master_enabled = ON; SET GLOBAL rpl_semi_sync_master_timeout = 2000; -- ms; then falls back to async SET GLOBAL rpl_semi_sync_master_wait_point = AFTER_SYNC; -- lossless wait point -- Each replica (dynamic, no restart) SET GLOBAL rpl_semi_sync_slave_enabled = ON;
Figure 3: Semi-synchronous commit path in a MariaDB high availability replication pair — the RPO guarantee and its fallback behavior.
Verify the guarantee is actually active — a silent fallback to asynchronous mode is the classic semi-sync failure mode:
SHOW GLOBAL STATUS
WHERE Variable_name IN
('Rpl_semi_sync_master_status',
'Rpl_semi_sync_master_yes_tx',
'Rpl_semi_sync_master_no_tx');
Alert when Rpl_semi_sync_master_status reads OFF or Rpl_semi_sync_master_no_tx grows: both mean commits are proceeding without the semi-sync guarantee. For replica lag, do not rely on Seconds_Behind_Master alone — track gtid_slave_pos against gtid_binlog_pos on the primary, and on 12.3 monitor per-worker state in information_schema.SLAVE_WORKER_THREADS when tuning slave_parallel_threads. For replica provisioning at scale, see our note on transferring backups efficiently to a MariaDB replica.
Sizing the Parallel Applier
slave_parallel_threads is not a bigger-is-better knob. In optimistic mode the applier speculatively executes transactions in parallel and rolls back on conflict, so a write pattern with hot rows can spend more time retrying than applying. Size it empirically: start at 4–8 threads, replay production-shaped load, and compare the drain rate of gtid_slave_pos against the primary while watching the retry counters in SHOW GLOBAL STATUS LIKE 'Slave_retried_transactions'.
On replicas dedicated to failover (rather than read scaling), keep innodb_flush_log_at_trx_commit = 1 and sync_binlog = 1 as well — a failover target with relaxed durability quietly converts your semi-sync RPO ≈ 0 design back into a data-loss scenario the moment it is promoted.
Tier 2: Galera Cluster — Synchronous Multi-Primary
MariaDB Galera Cluster is the core of any zero-data-loss MariaDB high availability design: it delivers RPO = 0 inside a datacenter through certification-based synchronous replication: a transaction commits only after its write set has been replicated to and certified by every node in the cluster. A minimum of three nodes preserves quorum through any single node failure.
Figure 1: MariaDB high availability reference topology — three-node Galera Cluster behind MaxScale automated failover.
Cluster Configuration on 12.3 LTS
Note MDEV-38744: from 12.3, server packages no longer pull the Galera provider — install the galera-4 package explicitly on every node.
# /etc/my.cnf.d/galera.cnf -- MariaDB 12.3 LTS, Galera 4
# Restart required for wsrep_provider changes
[mariadb]
wsrep_on = ON
wsrep_provider = /usr/lib64/galera-4/libgalera_smm.so
wsrep_cluster_name = prod_cluster_dc1
wsrep_cluster_address = gcomm://10.0.1.11,10.0.1.12,10.0.1.13
wsrep_node_name = db-dc1-node1
wsrep_node_address = 10.0.1.11
# Galera requirements
binlog_format = ROW
innodb_autoinc_lock_mode = 2
log_slave_updates = ON # required for cluster-to-cluster replication
# Applier parallelism and 12.3 retry behavior
wsrep_slave_threads = 8
wsrep_applier_retry_count = 4 # new in 12.3, MDEV-36077
# State transfer
wsrep_sst_method = mariabackup
wsrep_sst_auth = ${SST_USER}:${SST_PASSWORD}
# Provider tuning: size gcache so short outages recover via IST, not SST
wsrep_provider_options = "gcache.size=4G;gcs.fc_limit=256"
Size gcache.size from your write volume: it must hold more write sets than accumulate during your longest tolerated node outage, because a node that finds its missing transactions in the donor gcache rejoins via Incremental State Transfer (IST) instead of a full State Snapshot Transfer (SST).
MariaDB 12.3 makes IST cheaper again by skipping unnecessary foreign key checks during the transfer (MDEV-34822).
Proving Cluster Health
SHOW GLOBAL STATUS
WHERE Variable_name IN
('wsrep_cluster_status', -- must be Primary
'wsrep_cluster_size', -- expected node count
'wsrep_local_state_comment', -- Synced on a healthy node
'wsrep_flow_control_paused', -- fraction of time paused; alert above 0.1
'wsrep_local_recv_queue_avg', -- sustained > 0.5 means applier lag
'wsrep_cert_deps_distance'); -- guides wsrep_slave_threads sizing
wsrep_flow_control_paused is the number that tells you the cluster is throttling writes to protect its slowest node — the mechanism behind most "Galera is slow" incidents. We covered the full diagnostic sequence in Troubleshooting Galera Cluster for Performance Issues. Remember the standing Galera constraints: InnoDB tables with primary keys only, write-set certification conflicts surface as deadlock errors to the application, and large transactions are bounded by wsrep_max_ws_size.
Two design decisions determine whether Galera delivers its RPO = 0 promise in practice. First, quorum arithmetic: always deploy an odd number of nodes (or two nodes plus a Galera arbitrator) so a network partition leaves exactly one primary component; a 50/50 split freezes both halves, which protects consistency at the cost of availability.
Second, write-conflict discipline: Galera is multi-primary, but pointing all writes at a single node through your proxy layer eliminates certification conflicts for most OLTP workloads and makes wsrep_cert_deps_distance far more predictable. Reserve true multi-node writes for workloads you have tested for conflict rate — the counter to watch is wsrep_local_cert_failures.
Multi-Datacenter Design: Parallel Galera-to-Galera Replication in 12.3
Stretching one Galera Cluster across WAN links penalizes every commit with inter-DC round trips. The production-grade pattern for MariaDB high availability across regions is one Galera Cluster per datacenter, connected by GTID-based asynchronous replication — and this is exactly where MariaDB 12.3 LTS delivers its headline improvement: the asynchronous link between two Galera Clusters can now use parallel replication (MDEV-20065).
Before 12.3, the cluster-to-cluster applier was effectively single-threaded, so a write-heavy primary cluster could permanently outrun its DR cluster. Now the replica-side applier fans out through slave_parallel_threads:
Figure 2: Multi-datacenter MariaDB high availability — one Galera Cluster per DC linked by parallel asynchronous replication (new in 12.3).
-- On one node of the DR cluster (DC2)
-- Each cluster keeps a distinct gtid_domain_id (e.g., DC1 = 1, DC2 = 2)
SET GLOBAL slave_parallel_threads = 8;
SET GLOBAL slave_parallel_mode = optimistic;
CHANGE MASTER TO
MASTER_HOST = 'dc1-vip.db.internal',
MASTER_USER = '${REPL_USER}',
MASTER_PASSWORD = '${REPL_PASSWORD}',
MASTER_USE_GTID = slave_pos,
MASTER_SSL = 1;
START REPLICA;
-- Verify parallel apply is active and lag is draining
SHOW REPLICA STATUS\G
SELECT @@gtid_slave_pos, @@gtid_binlog_pos;
Every node in each cluster must run log_slave_updates = ON so replicated transactions re-enter the local cluster's write-set replication, and the replication user should exist on all nodes of the source cluster so the link can be re-pointed after a node failure. Combine this with slave_abort_blocking_timeout (11.8+) on the DR side so a stray analytical query cannot stall the applier indefinitely.
If you do stretch a single Galera Cluster across sites instead — legitimate for metro-distance, low-latency links — declare WAN topology to the provider with gmcast.segment in wsrep_provider_options (a distinct segment ID per site), so Galera relays traffic once per segment instead of once per node and picks IST/SST donors within the local segment. Measure the commit-latency cost before choosing this path: every transaction pays the inter-site round trip at certification time, which is precisely what the cluster-per-DC design above avoids.
Automated Failover with MariaDB MaxScale 25.10
Replication and Galera provide redundancy; MariaDB high availability additionally requires something to detect failure and redirect traffic in seconds. MariaDB MaxScale 25.10 (current release 25.10.3, GA 2026-06-15) pairs a readwritesplit router with automatic failover driven by the MariaDB Monitor:
# /etc/maxscale.cnf -- MaxScale 25.10.3
[Replication-Monitor]
type = monitor
module = mariadbmon
servers = db1,db2,db3
user = ${MAXSCALE_USER}
password = ${MAXSCALE_PASSWORD}
replication_user = ${REPL_USER}
replication_password = ${REPL_PASSWORD}
monitor_interval = 2s
auto_failover = true
auto_rejoin = true
failcount = 3 # 3 x 2s = failure declared after ~6s
[RW-Split-Service]
type = service
router = readwritesplit
servers = db1,db2,db3
user = ${MAXSCALE_USER}
password = ${MAXSCALE_PASSWORD}
transaction_replay = true # replays in-flight transactions after failover
With auto_failover enabled, MaxScale promotes the most up-to-date replica when the primary fails, repoints the remaining replicas, and auto_rejoin re-subordinates the old primary when it returns — no split brain, no manual CHANGE MASTER. Planned maintenance uses a zero-data-loss switchover instead:
# Verify topology state before acting maxctrl list servers # Planned promotion of db2 (waits for replicas to catch up) maxctrl call command mariadbmon switchover Replication-Monitor db2 # Validate: db2 is Master, others are Slave, Running maxctrl list servers
Two disclosures belong in every MaxScale design. First, licensing: MaxScale is distributed under the Business Source License (BSL) — not OSI open source — and production use beyond the license grant requires a MariaDB subscription. Second, vendor neutrality: ProxySQL and HAProxy (with an external failover orchestrator) remain capable open-source alternatives; MaxScale earns its place when you need integrated automated failover, transaction replay, and Galera-aware routing in one component. Choose per requirement, not by default.
Do not let the proxy become the new single point of failure. Run at least two MaxScale instances — either behind keepalived with a virtual IP, or using MaxScale cooperative monitoring so only one instance performs failover actions at a time — and monitor them with the same seriousness as the database tier. The availability of a MariaDB high availability stack is the availability of its weakest routing component.
Choosing Your MariaDB High Availability Topology
There is no single correct MariaDB high availability topology — there is a correct topology per RPO/RTO requirement, write pattern, and operational maturity. The matrix below summarizes the trade-offs on MariaDB 12.3 LTS:
| Topology (MariaDB 12.3 LTS) | RPO | RTO | Write scaling | Operational complexity |
|---|---|---|---|---|
| Async GTID replication + MaxScale auto_failover | Seconds (replication lag) | ~5–15 s | Single primary | Low |
| Semi-sync replication + MaxScale auto_failover | ≈ 0 per acknowledged commit | ~5–15 s | Single primary | Low–medium |
| Galera Cluster (3+ nodes, single DC) | 0 | Seconds (connection re-route) | Multi-primary (conflict-bound) | Medium |
| Galera per DC + parallel cluster-to-cluster replication | 0 in-DC; seconds cross-DC | Seconds in-DC; minutes for DC failover | Multi-primary per DC | High |
RTO figures are illustrative planning values, not benchmarks — validate them with failover drills on your own workload and infrastructure.
Upgrade Risks to Clear Before 12.3 LTS
An upgrade executed carelessly is itself an availability incident, so treat the move to 12.3 LTS as part of the MariaDB high availability program. Three 12.3 changes have direct availability implications:
- innodb_snapshot_isolation now defaults to ON. REPEATABLE READ behaves as true snapshot isolation, and applications written against the previous semantics can see new conflict errors under concurrency. Load-test transaction-heavy paths on a 12.3 clone while watching Innodb_row_lock_% status counters and application error rates by SQL digest. Rollback is dynamic, no restart: SET GLOBAL innodb_snapshot_isolation = OFF;
- Three new reserved words: CONVERSION, ST_COLLECT, TO_DATE. Pre-flight scan information_schema.COLUMNS, TABLES, and ROUTINES for these identifiers before upgrading; rename rather than quote.
- A known replication issue affects master_use_gtid settings during upgrade to 12.3. Capture SHOW REPLICA STATUS (Using_Gtid, Gtid_IO_Pos) and SELECT @@gtid_slave_pos, @@gtid_binlog_pos; on every replica before upgrading, upgrade replicas before the primary, and explicitly re-assert MASTER_USE_GTID after the upgrade instead of trusting persistence.
Also plan the support horizon: under the MariaDB maintenance policy, Community LTS binaries are supported for three years from GA — 12.3 to roughly mid-2029, 11.8 to 2028-06-04 — with two further years of source-only fixes. Estates still on 10.6 passed community binary EOL on 2026-07-06 and need a dated migration plan.
Backups Are Part of the MariaDB High Availability Design
Replication multiplies data; it does not protect it. A DROP TABLE, an application bug, or ransomware replicates to every node and every datacenter in milliseconds, which is why a MariaDB high availability architecture without tested backups is incomplete. Run mariabackup for physical backups from a designated Galera node or replica (the same tooling already serving as your SST method), keep binary logs for point-in-time recovery between backup sets, and store at least one copy outside the failure domain of both datacenters.
The metric that matters is not backup success rate — it is restore time, measured by actually restoring: schedule a quarterly restore drill and record the wall-clock duration against your RTO budget. Backup validation belongs in the same review cadence as failover drills, because the two protect against different failure classes.
Prove It: Drills and Standing Telemetry
A MariaDB high availability stack that has not survived a rehearsed failure is an assumption, not an architecture. Institutionalize quarterly MariaDB high availability drills: kill the primary and measure detection-to-promotion from MaxScale logs; kill a Galera node and measure IST rejoin duration from the error log and wsrep_local_state_comment transitions; fail an entire DC and measure cluster-to-cluster catch-up by watching gtid_slave_pos converge.
Alert continuously on wsrep_cluster_status, wsrep_flow_control_paused, Rpl_semi_sync_master_status, and GTID position drift — these four catch the large majority of MariaDB high availability regressions before customers do.
Conclusion
MariaDB 12.3 LTS is the strongest availability release in the MariaDB Server line to date: parallel cluster-to-cluster replication removes the last structural bottleneck in the dual-DC Galera reference architecture, applier retry and cheaper IST harden day-2 operations, and the surrounding LTS window gives you a platform stable through 2029. Engineered deliberately — GTID everywhere, semi-sync or Galera where RPO demands it, MaxScale or an open-source proxy layer for sub-15-second failover, and drills that prove the numbers — MariaDB high availability on 12.3 LTS supports RPO = 0 designs with single-digit-second in-DC recovery.
MinervaDB builds, audits, and operates these architectures for enterprises worldwide — from topology design and failover automation to 24×7 monitoring with the exact telemetry described above. If you are planning a 12.3 LTS upgrade or a high availability redesign, our MariaDB Remote DBA and Support team can help you get there with measured RPO/RTO outcomes. Contact us at contact@minervadb.com.