Blog · High availability

How a keenPG cluster fails over in under four seconds

Five steps run every time a primary dies: notice, agree, fence, promote, reconnect. Here is each one, second by second.

KP
keenPG EngineeringReliability team · 9 min read
The short version
  1. Every node reports a heartbeat once a second.
  2. After three missed beats, the healthy nodes vote on whether the primary is really gone.
  3. The old primary is fenced, so it can never accept another write.
  4. The most up-to-date synchronous replica is promoted.
  5. The connection proxy points every app at the new primary.

Most of the time a database failover is invisible. A disk dies at 3 a.m., a replica takes over and the on-call engineer reads about it over breakfast. But "invisible" hides a lot of careful engineering. If any one of the five steps above is skipped or rushed, you get the two outcomes everyone fears: downtime or, worse, two primaries writing different data.

Here is the full timeline of a typical failover on a keenPG cluster:

0.0 sprimary dies3.0agree3.2fencepromote3.8 sreconnectednotice: 3 missed heartbeats
Almost all of the time goes into being sure. The actual switch takes less than a second.
Step 1 · 0.0–3.0 s

Notice

Each node in the cluster writes a heartbeat to a small consensus store every second. The heartbeat carries more than "I'm alive". It includes the node's role, its replication position and its timeline, which gives the rest of the cluster everything it needs to make a decision later.

Why wait for three missed beats instead of one? Because networks hiccup. A single lost packet shouldn't trigger a failover, which has a cost of its own: every connection drops. Three seconds is the balance we've found between reacting quickly and not reacting to noise.

Step 2 · 3.0 s

Agree

A replica that can't see the primary doesn't simply promote itself. The primary might be fine, and the replica might be the one that's cut off. Instead the remaining nodes need a majority: in a three-node cluster, two nodes must agree that the primary is gone.

This is the single most important rule in high availability. A node that loses its majority can never become, or stay, the primary. It is the rule that makes split-brain impossible. You can watch it happen in the "Cut the network" scenario of our failure simulator.

Step 3 · 3.2 s

Fence

Before anything is promoted, the old primary has to be made harmless. If it's merely slow rather than dead, it could wake up and accept writes that the new primary never sees. So it gets fenced: its lease in the consensus store expires, and it demotes itself to read-only the moment it notices. If it can't be reached at all, the platform stops its instance.

Step 4 · 3.4 s

Promote

Now the cluster picks the replica with the most data. With synchronous replication, at least one replica is guaranteed to have every committed transaction, because the primary waited for it before telling your app "OK". That replica is chosen and promoted:

sql
-- what the platform runs on the chosen replica
SELECT pg_promote(wait => true);

You can check how up-to-date each replica is at any moment:

sql
SELECT application_name, sync_state, replay_lag
FROM   pg_stat_replication;

 application_name | sync_state | replay_lag
 pg-b             | sync       | 00:00:00.0004
 pg-c             | async      | 00:00:00.0120
Step 5 · 3.8 s

Reconnect

A promoted primary is no use if your applications are still knocking on the old door. Every keenPG cluster sits behind a connection proxy that watches the consensus store. When the leader changes, the proxy routes new connections to it. Apps don't need a config change or a restart, only the reconnect logic that every database driver already has.

Watch the five steps happen.Kill a primary yourself in the interactive simulator.
Try to break it

What you can tune

The defaults suit most workloads, but every cluster can be adjusted. On keenPG on Kubernetes (KPK), it's part of the cluster spec:

yaml
spec:
  instances: 3
  failover:
    heartbeatInterval: 1s      # how often nodes check in
    missedBeats: 3             # beats before failover starts
    synchronousStandbys: 1     # 0 = faster commits, 1 = zero data loss

A word of caution: lowering missedBeats to 1 makes failover faster on paper, but it also makes it trigger on every network blip. We rarely recommend it.

KP
keenPG Engineering

Written by the engineers who build and run keenPG clusters, and who would rather automate a 3 a.m. failover than live through one.