Failover PostgreSQL multi-région sans interruption
Cette configuration utilise une réplication en streaming inter-région pour un failover rapide et ajoute un contrôle de restauration nocturne pour détecter les problèmes que la réplication ne protège pas, comme une mauvaise migration, une table corrompue ou un DELETE accidentel sans clause WHERE.
Architecture cible
La région standby fait tourner une couche applicative active (réduite, mais pas à zéro) afin que le failover soit un événement de bascule de trafic et de promotion, pas un démarrage à froid.
Réplication : synchrone vs. asynchrone, et ce que ça vous coûte
La réplication synchrone vous donne un RPO de zéro (aucune transaction validée n'est jamais perdue), mais chaque écriture attend un aller-retour vers le standby. Entre régions avec 40-80 ms de latence, c'est inenvisageable. La réplication fait donc deux métiers différents selon la distance :
- Réplication synchrone vers une réplique de la même région/même AZ pour un failover local instantané, sans perte de données.
- Réplication en streaming asynchrone vers le standby inter-région pour un failover de niveau sinistre, en acceptant un RPO faible (de l'ordre de la seconde) en échange d'une latence d'écriture acceptable.
# postgresql.conf sur le primaire
wal_level = replica
max_wal_senders = 6
wal_keep_size = 2GB
archive_mode = on
archive_command = 'wal-g wal-push %p'
# synchronous_standby_names ne cible que la réplique LOCALE,
# le standby inter-région reste asynchrone pour que les écritures
# ne soient pas bloquées par la latence WAN.
synchronous_standby_names = 'local_replica'# postgresql.conf sur le standby inter-région
primary_conninfo = 'host=primary.internal port=5432 user=replicator application_name=region_b_standby'
restore_command = 'wal-g wal-fetch %f %p'
recovery_target_timeline = 'latest'Des outils comme Patroni (adossé à etcd/Consul pour l'élection du leader) peuvent automatiser cette promotion à la place d'un humain. Mais un failover automatisé entre régions est une décision à prendre délibérément, pas un choix par défaut. Un faux positif de failover sur une liaison WAN est un incident à part entière.
Validation des sauvegardes : l'étape que presque tout le monde saute
Ce contrôle tourne chaque nuit contre la dernière sauvegarde complète archivée + WAL, sur une instance jetable, entièrement automatisé :
#!/usr/bin/env bash
set -euo pipefail
RESTORE_TARGET="/var/lib/postgresql/restore-verify"
EXPECTED_MIN_ROWS=1000000
echo "[1/4] Récupération de la dernière sauvegarde complète via wal-g..."
wal-g backup-fetch "$RESTORE_TARGET" LATEST
echo "[2/4] Démarrage de PostgreSQL en mode recovery sur les données restaurées..."
pg_ctl -D "$RESTORE_TARGET" -o "-p 5433" start -w
echo "[3/4] Exécution des contrôles d'intégrité..."
ROW_COUNT=$(psql -p 5433 -Atc "SELECT count(*) FROM orders;")
CHECKSUM=$(psql -p 5433 -Atc "SELECT md5(string_agg(id::text, ',' ORDER BY id)) FROM orders LIMIT 100000;")
if [ "$ROW_COUNT" -lt "$EXPECTED_MIN_ROWS" ]; then
echo "ÉCHEC : nombre de lignes restaurées ($ROW_COUNT) sous le seuil attendu ($EXPECTED_MIN_ROWS)" >&2
exit 1
fi
echo "[4/4] Restauration vérifiée, $ROW_COUNT lignes, checksum $CHECKSUM"
pg_ctl -D "$RESTORE_TARGET" stopBranchez le code de sortie sur votre alerting (une restauration nocturne échouée est un page, pas un ticket). De tous les contrôles de ce playbook, ce test de restauration nocturne est celui qui rapporte le plus vite : il transforme « on pense que nos sauvegardes fonctionnent » en « on l'a prouvé il y a 20 minutes ».
Failover au niveau DNS
resource "aws_route53_health_check" "primary_region" {
fqdn = "app-primary.example.com"
port = 443
type = "HTTPS"
resource_path = "/healthz"
failure_threshold = 3
request_interval = 10
}
resource "aws_route53_record" "app_failover_primary" {
zone_id = var.zone_id
name = "app.example.com"
type = "A"
failover_routing_policy {
type = "PRIMARY"
}
set_identifier = "primary"
health_check_id = aws_route53_health_check.primary_region.id
alias {
name = aws_lb.region_a.dns_name
zone_id = aws_lb.region_a.zone_id
evaluate_target_health = true
}
}L'enregistrement de failover SECONDARY correspondant du standby prend le relais automatiquement dès que les health checks échouent ; aucun changement DNS manuel n'est nécessaire pendant un véritable incident.
Objectifs RTO/RPO visés
| Scénario | RPO | RTO | |---|---|---| | Panne d'une seule AZ (réplique synchrone locale) | 0 (aucune perte de données) | < 60 s (automatisé) | | Panne de région complète (promotion du standby asynchrone) | < 30 s d'écritures | < 5 min (automatisé) | | Données corrompues / mauvaise migration (restauration depuis sauvegarde) | Jusqu'au dernier segment WAL (~5 min) | 15-30 min (manuel, délibéré) |
Remarquez que la ligne « données corrompues » a un RTO plus long, par conception. Une récupération rapide et automatique d'un problème de données auto-infligé ne ferait que réappliquer la même mauvaise migration.
Le résultat
La réplication en streaming et les enregistrements de failover Route53 sont des briques mûres et bien comprises. Ce qui décide de l'issue pendant un véritable incident, c'est si le chemin de failover a réellement été testé, et si « la sauvegarde fonctionne » est un fait vérifié plutôt qu'une supposition.
Si votre plan de reprise n'a jamais eu de véritable test de restauration exécuté contre lui, c'est exactement l'écart qu'une mission de Revue d'architecture est conçue pour combler, avant qu'un incident ne le découvre à votre place.
Envie de faire tourner ça en production ?
Ce tutoriel couvre les concepts et l'architecture. Si vous voulez l'implémenter dans votre propre infrastructure, ou monter en compétence pour posséder ce sujet durablement, je propose du mentorat individuel construit autour de votre environnement réel, pas une formation générique.
Ce tutoriel
- Concepts clés et architecture principale
- Extraits de code illustratifs
- Le raisonnement derrière chaque décision
Mentorat individuel
- Des sessions de travail sur votre propre environnement
- Des réponses directes aux cas particuliers que vous rencontrez
- Un retour sur votre implémentation réelle
- Un accompagnement continu pendant que vous la construisez
Tutoriels similaires
Montée de version PostgreSQL sans interruption
Basculer une base PostgreSQL de production vers une nouvelle version majeure via logical replication, sans la fenêtre de maintenance habituelle.
Le guide 2026 d'optimisation des coûts Cloud
Un cadre éprouvé pour réduire les dépenses cloud sans sacrifier la fiabilité : dimensionnement, remises d'engagement, et ce qui fait durer les économies.