Configuring Redis Sentinel Quorum for Automatic Failover
You run a single Redis primary behind a fleet of application workers, and the night it crashes you discover that nothing promoted a replica — every request is now failing against a dead socket. Redis Sentinel exists to close exactly this gap: a small set of observer processes that agree the primary is down, elect one of themselves to run the failover, and promote a replica without a human in the loop. The delicate part is the quorum — the number of Sentinels that must independently agree the primary is unreachable before a failover is authorized. Set it too low and a single misconfigured Sentinel can trigger a needless promotion; set it too high and a real outage never clears the agreement bar. This page configures a three-Sentinel deployment end to end, tunes the four directives that govern detection and promotion speed, wires up async client discovery, and proves the whole chain works by killing a primary on purpose.
Prerequisites
- Redis 7.x running as one primary with at least one attached replica (
REPLICAOF), reachable from every Sentinel host. - Three hosts (or three failure domains) to run one
redis-sentinelprocess each — an odd count so a majority always exists. redis-py5.x on Python 3.10+ (pip install "redis>=5,<6"); examples use theredis.asyncioclient.- Network reachability on the Sentinel port (default
26379) between all Sentinels and from application hosts. - Understanding that Sentinel manages a single logical primary with its replicas, not a sharded keyspace — if you need sharding, see replication and read scaling and the MOVED redirection model instead.
Step-by-Step Implementation
1. Deploy three or more Sentinel processes
Run one Sentinel per failure domain so that losing a host or a rack never drops you below a majority. Give each an identical sentinel.conf and start it as its own process; three is the smallest count that tolerates one Sentinel failure while still forming a majority.
# /etc/redis/sentinel.conf — identical on each of the three hosts
port 26379
sentinel resolve-hostnames yes
# start it: run this on host-a, host-b, and host-c
redis-sentinel /etc/redis/sentinel.conf
2. Point every Sentinel at the primary with a quorum
The sentinel monitor directive names the primary (mymaster), gives its address, and sets the quorum — how many Sentinels must agree the primary is unreachable to start a failover. With three Sentinels a quorum of 2 is the standard choice: it needs agreement from a strict majority without demanding unanimity.
# mymaster is the logical name; 2 is the quorum out of 3 Sentinels
sentinel monitor mymaster 10.0.1.10 6379 2
# authentication if the primary requires it
sentinel auth-pass mymaster "s3cr3t-primary-password"
3. Tune failure detection with down-after-milliseconds
down-after-milliseconds is how long a Sentinel waits without a valid PING reply before flagging the primary as subjectively down (+sdown) from its own point of view. Shorter values detect a real crash faster but make transient network blips look like outages. For most production networks 5000 ms balances the two.
# a Sentinel marks the primary +sdown after 5s of no valid reply
sentinel down-after-milliseconds mymaster 5000
4. Bound promotion time with failover-timeout and parallel-syncs
Once the quorum is met and a leader Sentinel is elected, failover-timeout caps how long the whole promotion may run before Sentinel considers it failed and lets another attempt start. parallel-syncs limits how many replicas re-synchronize from the new primary at once — keep it at 1 so you never black out every read replica simultaneously during the resync.
sentinel failover-timeout mymaster 180000 # 3 minutes to complete a failover
sentinel parallel-syncs mymaster 1 # resync replicas one at a time
5. Discover the current primary from Python
Application code must never hard-code the primary's address, because that address changes on every failover. Instead, connect to the Sentinels and ask them for the current primary with master_for, which returns a client that transparently re-resolves after a promotion.
import redis.asyncio as redis
from redis.asyncio.sentinel import Sentinel
# List every Sentinel; the client polls them for the live primary address.
sentinel = Sentinel(
[("host-a", 26379), ("host-b", 26379), ("host-c", 26379)],
socket_timeout=0.5,
sentinel_kwargs={"password": None}, # set if Sentinels require auth
)
async def get_primary() -> redis.Redis:
# master_for resolves 'mymaster' to whichever node Sentinel currently
# reports as primary, and refreshes that mapping after a failover.
return sentinel.master_for(
"mymaster",
password="s3cr3t-primary-password",
socket_timeout=0.5,
decode_responses=True,
)
async def write_session(session_id: str, payload: str) -> None:
client = await get_primary()
await client.set(f"session:{session_id}", payload, ex=3600) # 1h TTL
6. Trigger a failover and watch the promotion
Never trust an untested failover. Force one with SENTINEL FAILOVER (or kill the primary process) and follow the Sentinel event stream to confirm the sequence: subjective down, objective down, leader election, and promotion.
# ask a Sentinel to run a failover on demand, then follow its events
redis-cli -p 26379 SENTINEL FAILOVER mymaster
redis-cli -p 26379 PSUBSCRIBE '+switch-master' '+odown' '+elected-leader'
Failure Modes
Flapping failover on a jittery network. A saturated link or a long GC pause makes the primary miss pings, Sentinels declare it down, promote a replica, and then the old primary reappears — repeatedly. Diagnose by counting failover events in the Sentinel log:
redis-cli -p 26379 SENTINEL MASTER mymaster | grep -A1 num-other-sentinels
grep -c '+switch-master' /var/log/redis/sentinel.log # repeated flips = flapping
Fix by raising down-after-milliseconds so a transient blip cannot cross the threshold, and confirm every Sentinel actually sees the others (num-other-sentinels should be one less than your Sentinel count).
Quorum can never be reached. The quorum is set higher than the number of Sentinels that can actually reach each other, so a genuine outage never authorizes a failover and the cache stays dead. Diagnose by inspecting how many Sentinels each one knows about:
redis-cli -p 26379 SENTINEL CKQUORUM mymaster
# reports whether enough Sentinels are reachable to both authorize and elect
Fix by lowering the quorum to a strict majority (2 of 3, 3 of 5) and ensuring Sentinels can route to one another on port 26379.
Clients keep hitting the old primary. After a promotion, application workers still write to the demoted node because they cached its address instead of resolving through Sentinel. Diagnose by comparing what the client thinks is primary against Sentinel's view:
redis-cli -p 26379 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster
Fix by always obtaining the connection via master_for (Step 5) rather than a fixed host, and by keeping Sentinel-aware pooling as described in connection pooling.
Verification
Confirm each Sentinel agrees on the primary address and sees the expected number of peers and replicas:
redis-cli -p 26379 SENTINEL MASTER mymaster | grep -E "quorum|num-slaves|num-other-sentinels"
# quorum matches your config; num-other-sentinels = (total sentinels - 1)
Prove that a promotion actually re-routes writes by killing the primary and re-reading the primary address after the failover completes:
redis-cli -h 10.0.1.10 -p 6379 DEBUG SLEEP 30 # simulate an unresponsive primary
sleep 8
redis-cli -p 26379 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster # should be the ex-replica
Assert from application code that the resolved client points at a writable primary:
async def verify_primary() -> None:
client = await get_primary()
role = await client.execute_command("ROLE")
assert role[0] == "master", f"resolved node is not primary: {role[0]}"
FAQ
Is the quorum the same as the majority needed to elect a leader?
No, and conflating them causes most Sentinel confusion. The quorum only decides how many Sentinels must agree the primary is objectively down to authorize a failover. Actually running the failover requires a separate election in which a strict majority of the total Sentinel set must vote for a leader. You can set a quorum of 2 on a five-Sentinel deployment, but the promotion still needs three votes to elect the leader that performs it.
How many Sentinels should I run?
Run an odd number across independent failure domains — three for most deployments, five when you need to tolerate two simultaneous Sentinel losses. An odd count guarantees a majority can always form, and spreading them across racks or availability zones prevents a single domain failure from taking out both the primary and the Sentinels that would have promoted its replica.
Can Sentinel cause split-brain, and how do I limit it?
Yes: during a network partition the minority side may still hold an old primary that briefly accepts writes before it is demoted. Bound the damage with min-replicas-to-write, which refuses writes on a primary that cannot see enough healthy replicas, so an isolated primary stops accepting data it can never replicate. Combined with a majority quorum this keeps the window small and the losing side's writes minimal.
What does min-replicas-to-write actually protect against?
It stops a partitioned or demoted primary from silently accepting writes that will be lost when the real primary wins the election. Setting min-replicas-to-write 1 and min-replicas-max-lag 10 tells a primary to reject writes unless at least one replica has acknowledged within ten seconds. On the isolated side of a partition that replica is gone, so writes fail fast instead of accumulating as data that a subsequent failover discards.
Up: Redis Sentinel vs Cluster Failover