Pourquoi Postgres n’est pas optimal en environnement contraint
PostgreSQL est l’un des systèmes de bases de données relationnelles les plus respectés au monde. Fiable, robuste, extensible, il est devenu un choix par défaut pour d’innombrables applications. Mais son architecture interne repose sur des choix profonds — très adaptés aux serveurs modernes — qui le rendent moins efficace dans des environnements contraints ou distribués avec une latence élevée.
Cette note n’est pas une critique. Elle vise à expliquer pourquoi Postgres se comporte ainsi, et pourquoi ces comportements deviennent des limites dans certains contextes.
Architecture B-Tree + VACUUM
Postgres utilise principalement des B-Trees, excellents pour les recherches mais basés sur des mises à jour en place.
Pour garantir l’isolation, Postgres adopte aussi le MVCC, qui conserve les anciennes versions de lignes jusqu’à ce qu’elles soient obsolètes.
Un UPDATE produit donc :
nouvelle version de la ligne
ancienne version conservée
Cette accumulation de versions mortes nécessite un processus de maintenance : VACUUM, chargé de nettoyer les pages.
L’ensemble B-Tree + MVCC + VACUUM fonctionne très bien sur des serveurs puissants, mais crée une forte sensibilité au matériel et à la charge.
Le bloat : le coût caché de MVCC
Le bloat correspond à l’espace occupé par les anciennes versions de lignes.
Chaque mise à jour augmente la quantité de données stockées, même si la table ne “grandit” pas conceptuellement.
Représentation simplifiée :
[Avant UPDATE] [Après plusieurs UPDATE]
+---------+ +------------------------+
| row A | ----> | row A (versions mortes)|
| row B | | row A (version active) |
+---------+ | row B (versions mortes)|
+------------------------------------------------+
Effets directs du bloat :
- plus de pages à lire pour la même requête,
- index plus lourds,
- augmentation automatique du travail de VACUUM,
- explosion de la consommation disque.
Sur un matériel limité, le bloat devient rapidement un problème majeur.
VACUUM : une dépendance structurelle
VACUUM est indispensable au fonctionnement du moteur, mais son coût est important.
Points critiques :
- forte consommation CPU,
- accès disque intensifs,
- contention potentielle avec les requêtes,
- dépendance à la performance du disque,
- risque d’arriéré si la charge est élevée.
Lorsque le rythme de création de tuples morts dépasse celui du VACUUM, les performances du moteur se dégradent rapidement.
Tuples morts → bloat ↑ → VACUUM ↑ → contention ↑ → latence ↑
Dans des environnements contraints, ce cycle peut devenir ingérable.
Scaling vertical obligatoire
Postgres ne supporte pas nativement le scaling horizontal pour les écritures.
Son modèle opérationnel est :
Écritures → 1 nœud principal
Lectures → réplicas (synchro ou asynchro)
Utiliser plusieurs nœuds pour écrire nécessite :
- du sharding manuel,
- des couches externes,
- une orchestration complexe.
Dans les environnements WAN instables, en Afrique ou ailleurs, la réplication de Postgres souffre :
- pertes de paquets,
- délais de propagation,
- déconnexions sporadiques,
- retards de synchronisation.
Le moteur suppose un centre de données unique et stable — ce qui contredit le modèle local-first ou distribué.
Sensibilité à la latence réseau
Le protocole Postgres nécessite plusieurs allers-retours pour traiter une requête simple.
Exemple typique :
Client → Parse
Serveur → ParseComplete
Client → Bind
Serveur → BindComplete
Client → Execute
Serveur → DataRow(s)
Sur un réseau rapide, ces échanges sont invisibles.
Sur un réseau instable, ils deviennent un goulet d’étranglement.
RTT élevée → throughput ↓ → latence ↑
Même si le serveur est performant, la perception côté client est dégradée.
Consommation mémoire et CPU
Postgres repose sur :
- de larges buffer pools,
- des caches internes structurés,
- un planner SQL exigeant en CPU,
- plusieurs workers de fond (checkpointer, background writer, autovacuum…).
Sur des VMs modestes, des Raspberry Pi, des serveurs edge, ou dans des infrastructures avec CPU limité, ces processus se retrouvent en concurrence avec les requêtes applicatives.
Conclusion
Postgres excelle dans les environnements modernes, centralisés et bien équipés.
Mais ses choix architecturaux — MVCC, bloat, VACUUM, protocole verbeux, dépendance à une faible latence — le rendent inadapté lorsque :
- les ressources sont limitées,
- les réseaux sont instables,
- l’architecture est distribuée,
- le stockage est lent,
- le coût d’administration doit rester faible.
Reconnaître ces limites ne remet pas en cause sa qualité : cela permet simplement de comprendre où Postgres brille réellement — et où d’autres architectures log-structured, local-first ou CPU-first deviennent nécessaires.
Références recommandées
- Documentation PostgreSQL — MVCC & Storage
- 2ndQuadrant — The Anatomy of a PostgreSQL Update
- Garcia-Molina — Database Systems
- PostgreSQL Wiki — Autovacuum & Bloat
- Postgres Professional — PostgreSQL in High Latency Networks