Aller au contenu
medium

Découvrir PostgreSQL : architecture, vocabulaire et composants

26 min de lecture

Logo PostgreSQL

Vous lancez sudo -u postgres psql, vous tombez sur un prompt postgres=#, et vous tapez des requêtes SQL. Ça fonctionne. Mais qu’est-ce qui tourne en dessous ? Quel processus écoute sur quel port, où sont stockées les données, pourquoi il y a trois bases alors que vous n’en avez créé aucune, et que signifie ce fichier pg_hba.conf qui décide si vous avez le droit de vous connecter ?

PostgreSQL n’est pas une simple base de données — c’est un système complet avec son propre vocabulaire : cluster, instance, schéma, rôle, tablespace, WAL. Beaucoup de ces termes sont trompeurs. Un cluster n’a rien à voir avec la haute disponibilité. Un rôle n’est ni un utilisateur ni un groupe — c’est les deux à la fois. Ce guide démonte la mécanique interne pour que vous compreniez ce que vous administrez avant de toucher à la configuration.

  • Distinguer cluster, instance, base de données et schéma — les quatre niveaux de la hiérarchie PostgreSQL
  • Identifier les processus serveur et comprendre le rôle de chaque background worker
  • Expliquer ce que sont les WAL et pourquoi ils sont critiques pour la fiabilité
  • Différencier une connexion par socket Unix d’une connexion TCP et savoir laquelle est active
  • Lire un pg_hba.conf et comprendre les règles d’authentification

Ce guide est le point de départ avant toute administration PostgreSQL. Vous en avez besoin quand :

  • Vous installez PostgreSQL pour la première fois et voulez comprendre ce qui a été créé automatiquement
  • Vous devez diagnostiquer un problème de connexion (refus d’accès, mauvais socket, port inaccessible)
  • Vous voulez séparer les données de plusieurs applications dans des bases ou schémas distincts
  • Vous préparez une stratégie de sauvegarde et devez comprendre ce que sont les WAL avant de configurer l’archivage
  • Vous lisez la documentation officielle et les termes cluster, PGDATA, backend vous bloquent

Ce guide explique l’architecture — il ne configure rien. Les actions pratiques sont dans les guides dédiés :

Dans le monde PostgreSQL, cluster ne signifie pas « plusieurs serveurs qui travaillent ensemble ». Un cluster PostgreSQL désigne un répertoire de données unique, géré par un serveur PostgreSQL qui l’ouvre et l’exploite. C’est l’équivalent d’un « moteur de base de données avec toutes ses données locales ».

Analogie : pensez à un cluster comme un coffre-fort. Le coffre contient plusieurs tiroirs (les bases de données), chaque tiroir a des compartiments (les schémas), et il y a un gardien unique (le processus serveur) qui contrôle l’accès.

Sur Debian/Ubuntu, l’installation crée automatiquement un cluster nommé main :

Fenêtre de terminal
pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
18 main 5432 online postgres /var/lib/postgresql/18/main /var/log/postgresql/postgresql-18-main.log

La colonne Data directory indique le PGDATA — le répertoire racine du cluster. Tout ce que PostgreSQL stocke (données, configuration interne, WAL) se trouve dans ce répertoire ou est référencé depuis celui-ci.

Voici le contenu réel du PGDATA sur une installation fraîche de PostgreSQL 18 :

Fenêtre de terminal
ls -la /var/lib/postgresql/18/main/
total 92
drwx------ 19 postgres postgres 4096 Apr 13 08:49 .
drwxr-xr-x 3 postgres postgres 4096 Apr 13 08:49 ..
-rw------- 1 postgres postgres 3 Apr 13 08:49 PG_VERSION
drwx------ 5 postgres postgres 4096 Apr 13 08:49 base
drwx------ 2 postgres postgres 4096 Apr 13 08:53 global
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_commit_ts
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_dynshmem
drwx------ 4 postgres postgres 4096 Apr 13 08:54 pg_logical
drwx------ 4 postgres postgres 4096 Apr 13 08:49 pg_multixact
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_notify
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_replslot
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_serial
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_snapshots
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_stat
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_stat_tmp
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_subtrans
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_tblspc
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_twophase
drwx------ 4 postgres postgres 4096 Apr 13 08:49 pg_wal
drwx------ 2 postgres postgres 4096 Apr 13 08:49 pg_xact
-rw------- 1 postgres postgres 88 Apr 13 08:49 postgresql.auto.conf
-rw------- 1 postgres postgres 130 Apr 13 08:49 postmaster.opts
-rw------- 1 postgres postgres 108 Apr 13 08:49 postmaster.pid

Les éléments essentiels à retenir :

ÉlémentRôle
PG_VERSIONIndique la version majeure (ici 18)
base/Contient les données de chaque base, un sous-répertoire par OID
global/Tables partagées entre toutes les bases (rôles, tablespaces)
pg_wal/Les fichiers WAL (Write-Ahead Log) — journal de transactions
pg_tblspc/Liens symboliques vers les tablespaces additionnels
postmaster.pidLe PID du processus principal — preuve que le serveur tourne
postgresql.auto.confParamètres modifiés via ALTER SYSTEM (surcharge le .conf)

Sur Debian/Ubuntu, les fichiers de configuration ne sont pas dans PGDATA mais dans /etc/postgresql/18/main/ :

SELECT name, setting FROM pg_settings
WHERE name IN ('data_directory','config_file','hba_file','ident_file')
ORDER BY name;
name | setting
----------------+-----------------------------------------
config_file | /etc/postgresql/18/main/postgresql.conf
data_directory | /var/lib/postgresql/18/main
hba_file | /etc/postgresql/18/main/pg_hba.conf
ident_file | /etc/postgresql/18/main/pg_ident.conf

Cette séparation est une spécificité Debian — sur Red Hat ou en installation depuis les sources, tout est dans PGDATA.

Bases, schémas, tablespaces : la hiérarchie logique

Section intitulée « Bases, schémas, tablespaces : la hiérarchie logique »

PostgreSQL organise les objets SQL (tables, vues, fonctions) en trois niveaux :

  1. Cluster → contient une ou plusieurs bases de données
  2. Base de données → contient un ou plusieurs schémas
  3. Schéma → contient les objets SQL (tables, vues, fonctions, séquences)

Analogie : une base de données est un immeuble dans une ville (le cluster). Chaque étage de l’immeuble est un schéma. Les appartements sont les tables. Vous ne pouvez pas prendre l’ascenseur entre deux immeubles — une connexion PostgreSQL cible une seule base à la fois.

Une installation fraîche contient trois bases :

\l
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges
-----------+----------+----------+-----------------+---------+---------+--------+-----------+-----------------------
postgres | postgres | UTF8 | libc | C.UTF-8 | C.UTF-8 | | |
template0 | postgres | UTF8 | libc | C.UTF-8 | C.UTF-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | libc | C.UTF-8 | C.UTF-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
BaseRôle
postgresBase par défaut pour l’administration. C’est là où vous atterrissez avec sudo -u postgres psql.
template1Modèle utilisé automatiquement par CREATE DATABASE. Toute modification ici (extensions, schémas) sera héritée par les nouvelles bases.
template0Modèle « propre », jamais modifié. Utilisé pour restaurer une base avec un encoding différent (createdb --template=template0).

Chaque base correspond à un sous-répertoire dans base/, identifié par son OID (Object Identifier) :

SELECT oid, datname FROM pg_database ORDER BY oid;
oid | datname
-----+-----------
1 | template1
4 | template0
5 | postgres

Le répertoire base/5/ contient donc les fichiers de la base postgres.

Le schéma public : risques du search_path et changements depuis PostgreSQL 15

Section intitulée « Le schéma public : risques du search_path et changements depuis PostgreSQL 15 »

Chaque base contient au minimum le schéma public :

\dn+
List of schemas
Name | Owner | Access privileges | Description
--------+-------------------+----------------------------------------+------------------------
public | pg_database_owner | pg_database_owner=UC/pg_database_owner+| standard public schema
| | =U/pg_database_owner |

Quand vous créez une table sans préciser de schéma, PostgreSQL utilise le search_path pour décider où la placer :

SHOW search_path;
search_path
-----------------
"$user", public

PostgreSQL cherche d’abord un schéma portant le nom de l’utilisateur connecté ("$user"), puis le schéma public. Si le schéma personnel n’existe pas, tout tombe dans public.

Bonne pratique : créez un schéma dédié par application (CREATE SCHEMA monapp;) plutôt que de tout mettre dans public. Cela facilite les sauvegardes ciblées, les permissions et la lisibilité.

Tablespaces : séparer données et index (cas d’usage)

Section intitulée « Tablespaces : séparer données et index (cas d’usage) »

Un tablespace est un emplacement physique (un répertoire sur le disque) où PostgreSQL peut stocker des fichiers de données en dehors de PGDATA. Cas d’usage typiques : placer les index sur un SSD rapide, les tables d’archive sur un HDD, ou les données temporaires sur un volume dédié.

En pratique, les tablespaces ne sont utiles qu’en production avec des contraintes de performances I/O ou de capacité disque. Vous pouvez ignorer ce concept au début — le tablespace par défaut suffit largement.

Rôles : ni utilisateurs ni groupes (les deux à la fois)

Section intitulée « Rôles : ni utilisateurs ni groupes (les deux à la fois) »

PostgreSQL n’a pas de notion séparée d’« utilisateur » et de « groupe ». Il n’existe qu’un seul concept : le rôle. Un rôle peut se connecter (comme un utilisateur) ou non (comme un groupe), selon qu’il possède l’attribut LOGIN ou NOLOGIN.

\du
List of roles
Role name | Attributes
-----------+------------------------------------------------------------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS

Sur une installation fraîche, il n’existe qu’un seul rôle : postgres, le superuser. Il cumule tous les privilèges — c’est l’équivalent de root sous Linux.

Analogie : un rôle PostgreSQL est comme un badge d’accès dans un immeuble. Certains badges permettent d’entrer (LOGIN), d’autres sont des profils de groupe qui donnent accès à certains étages mais ne servent pas à passer le tourniquet (NOLOGIN). Un badge peut hériter des droits d’un autre badge.

Vous pouvez créer des rôles « groupe » (NOLOGIN) et y rattacher des rôles « utilisateur » (LOGIN) :

-- Rôle groupe : accès lecture seule
CREATE ROLE app_reader NOLOGIN;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_reader;
-- Rôle utilisateur qui hérite des droits de app_reader
CREATE ROLE bob LOGIN PASSWORD '<change-me>' IN ROLE app_reader;

Le rôle bob peut se connecter et hérite automatiquement des droits de app_reader. C’est le mécanisme standard pour implémenter le moindre privilège dans PostgreSQL.

Le superuser et pourquoi ne pas s’en servir au quotidien

Section intitulée « Le superuser et pourquoi ne pas s’en servir au quotidien »

Le rôle postgres (superuser) contourne toutes les vérifications de permissions. Il peut lire, modifier et supprimer n’importe quelle donnée dans n’importe quelle base. Il peut aussi charger des extensions C arbitraires, modifier la configuration et créer d’autres superusers.

Ne l’utilisez pas pour vos applications. Créez des rôles dédiés avec les permissions minimales nécessaires :

RôlePermissionsUsage
postgresSuperuser — toutAdministration, ALTER SYSTEM, maintenance
app_ownerPropriétaire du schémaMigrations, DDL (CREATE TABLE, ALTER)
app_writerINSERT, UPDATE, DELETEConnexion applicative en écriture
app_readerSELECT uniquementConnexion en lecture, reporting, monitoring

Le guide Sécurisation détaille cette séparation de rôles.

Le processus principal (accepte les connexions, lance les workers)

Section intitulée « Le processus principal (accepte les connexions, lance les workers) »

PostgreSQL fonctionne en multi-processus (pas en multi-thread). Un processus principal (postgres) écoute les connexions et démarre les processus auxiliaires nécessaires au fonctionnement du cluster. Pour chaque client qui se connecte, il crée un processus fils dédié — le backend.

Voici l’arbre des processus sur notre serveur PostgreSQL 18 :

Fenêtre de terminal
ps auxf | grep postgres
postgres 4323 /usr/lib/postgresql/18/bin/postgres -D /var/lib/postgresql/18/main -c config_file=/etc/postgresql/18/main/postgresql.conf
postgres 4324 \_ postgres: 18/main: io worker 0
postgres 4325 \_ postgres: 18/main: io worker 2
postgres 4326 \_ postgres: 18/main: io worker 1
postgres 4327 \_ postgres: 18/main: checkpointer
postgres 4328 \_ postgres: 18/main: background writer
postgres 4330 \_ postgres: 18/main: walwriter
postgres 4331 \_ postgres: 18/main: autovacuum launcher
postgres 4332 \_ postgres: 18/main: logical replication launcher

Le processus principal (PID 4323) lance les background workers au démarrage. Ils restent actifs en permanence.

Lorsqu’un client se connecte (via psql, une application, un outil de monitoring), PostgreSQL crée un backend dédié pour cette session. Ce processus exécute les requêtes SQL du client et disparaît à la déconnexion.

SELECT pid, usename, application_name, client_addr, backend_type, state
FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | application_name | client_addr | backend_type | state
------+----------+------------------+-------------+----------------+--------
4744 | postgres | psql | | client backend | active

Le champ client_addr est vide — la connexion passe par un socket Unix local, pas par TCP. Chaque backend consomme de la mémoire, mais attention : work_mem n’est pas réservé une fois par connexion. C’est une limite par opération interne de tri ou de hachage, qui peut se multiplier sur une requête complexe et sur plusieurs sessions concurrentes. C’est pourquoi le paramètre max_connections existe : limiter le nombre de processus simultanés pour éviter l’épuisement mémoire.

Background workers (autovacuum, WAL writer, checkpointer, archiver)

Section intitulée « Background workers (autovacuum, WAL writer, checkpointer, archiver) »

Les background workers sont des processus permanents qui assurent le bon fonctionnement interne :

ProcessusRôle
checkpointerÉcrit périodiquement les données modifiées (dirty pages) du cache vers le disque. Garantit un point de reprise cohérent.
background writerÉcrit les pages modifiées en avance pour réduire la charge lors des checkpoints.
walwriterÉcrit les enregistrements WAL du cache vers les fichiers pg_wal/.
autovacuum launcherDéclenche le nettoyage automatique des lignes mortes et met à jour les statistiques.
logical replication launcherGère les workers de réplication logique (si configurée).
io worker (PG 18+)Nouveauté PostgreSQL 18 : workers d’I/O asynchrones pour paralléliser les lectures/écritures disque. Améliore les performances sur les systèmes multi-cœurs.

Quand vous exécutez un INSERT INTO clients VALUES (...), voici ce qui se passe :

  1. Le client envoie la requête au backend dédié via le socket Unix ou TCP

  2. Le backend écrit dans le WAL — l’opération est journalisée avant toute modification des données (Write-Ahead Logging)

  3. Le walwriter écrit le WAL sur disque (flush). À ce moment, l’opération est durable même en cas de crash

  4. Le backend modifie les pages en mémoire (shared buffers). Les données sont maintenant visibles par les autres connexions

  5. Le checkpointer écrira ces pages sur disque lors du prochain checkpoint. Entre-temps, les WAL garantissent la récupération

Ce mécanisme explique pourquoi PostgreSQL redémarre dans un état cohérent après un crash : il rejoue les WAL nécessaires pour remettre les fichiers de données en phase avec les transactions durablement enregistrées. En configuration non durable (comme avec synchronous_commit = off), les toutes dernières transactions validées côté client mais pas encore flushées sur disque peuvent toutefois être perdues.

Par défaut, psql se connecte via un socket Unix — un fichier spécial sur le disque qui permet la communication entre processus sans passer par le réseau :

Fenêtre de terminal
ls -la /var/run/postgresql/
srwxrwxrwx 1 postgres postgres 0 Apr 13 08:49 .s.PGSQL.5432
-rw------- 1 postgres postgres 69 Apr 13 08:49 .s.PGSQL.5432.lock
-rw-r--r-- 1 postgres postgres 5 Apr 13 08:49 18-main.pid

Le fichier .s.PGSQL.5432 est le socket. Le numéro correspond au port. Quand vous exécutez sudo -u postgres psql, la connexion passe par ce socket et utilise l’authentification peer : PostgreSQL vérifie que l’utilisateur système (postgres) correspond au rôle demandé.

Avantages du socket Unix :

  • Pas de mot de passe avec l’authentification peer
  • Plus rapide que TCP (pas de couche réseau)
  • Plus sûr — pas d’exposition réseau

Pour les connexions depuis un autre serveur ou une application distante, PostgreSQL écoute sur TCP. Par défaut sur Debian, il n’écoute que sur localhost :

Fenêtre de terminal
# Connexion TCP locale — nécessite un mot de passe
psql -h 127.0.0.1 -U postgres

Cette connexion passe par TCP et pg_hba.conf exige une authentification scram-sha-256 (un mot de passe hashé). Contrairement au socket, l’identité de l’utilisateur système ne suffit pas.

Le fichier pg_hba.conf (Host-Based Authentication) contrôle qui peut se connecter, depuis où, et comment. Voici les lignes actives sur une installation fraîche :

local all postgres peer
local all all peer
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
local replication all peer
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256

Lecture ligne par ligne :

TypeBaseUtilisateurAdresseMéthodeSignification
localallpostgrespeerConnexion socket : le rôle postgres est authentifié par le système
localallallpeerConnexion socket : tout rôle ayant un utilisateur système correspondant
hostallall127.0.0.1/32scram-sha-256Connexion TCP locale : mot de passe hashé requis
hostallall::1/128scram-sha-256Idem en IPv6

Le guide Sécurisation détaille comment écrire un pg_hba.conf restrictif, activer TLS et configurer scram-sha-256.

Écriture séquentielle avant modification des données

Section intitulée « Écriture séquentielle avant modification des données »

Les WAL (Write-Ahead Logs) sont le mécanisme de journalisation de PostgreSQL. Le principe est simple : toute modification est d’abord écrite dans le journal (WAL) avant d’être appliquée aux fichiers de données. C’est une écriture séquentielle, donc performante.

Analogie : imaginez un cahier de brouillon (le WAL) et un classeur (les données). Avant de ranger un document dans le classeur, vous notez l’opération dans le brouillon. Si quelqu’un renverse le classeur (crash), vous pouvez tout reconstituer en relisant le brouillon.

Les fichiers WAL se trouvent dans pg_wal/ :

Fenêtre de terminal
ls /var/lib/postgresql/18/main/pg_wal/
000000010000000000000001
archive_status
summaries

Chaque fichier WAL fait 16 Mo par défaut. Le position courante d’écriture (LSN — Log Sequence Number) indique où PostgreSQL en est :

SELECT pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/17A6148

Pourquoi c’est la base de tout : crash recovery, réplication, PITR

Section intitulée « Pourquoi c’est la base de tout : crash recovery, réplication, PITR »

Les WAL servent à trois fonctions critiques :

FonctionComment ça marche
Crash recoveryAu redémarrage après un crash, PostgreSQL rejoue les WAL depuis le dernier checkpoint pour retrouver un état cohérent. Les transactions dont les WAL ont été flushés sont garanties.
RéplicationUn serveur standby reçoit les WAL du primary et les rejoue en continu. C’est le principe de la streaming replication.
PITR (Point-In-Time Recovery)En archivant les WAL, vous pouvez restaurer une base à n’importe quel instant — “je veux l’état de ma base à 14h32 mardi dernier”.
  • Un cluster PostgreSQL = un répertoire PGDATA + un serveur PostgreSQL. Ce n’est pas de la haute disponibilité.
  • Sur Debian/Ubuntu, les fichiers de configuration (postgresql.conf, pg_hba.conf) sont dans /etc/postgresql/18/main/, pas dans PGDATA.
  • Trois bases existent par défaut : postgres (administration), template1 (modèle pour CREATE DATABASE), template0 (modèle propre).
  • Un schéma est un espace de noms dans une base. Depuis PostgreSQL 15, le schéma public est restreint au propriétaire de la base.
  • Un rôle remplace utilisateurs et groupes. L’attribut LOGIN permet la connexion, NOLOGIN crée un rôle groupe.
  • PostgreSQL fonctionne en multi-processus : un processus principal, des workers permanents, et un backend par client connecté.
  • Les io workers sont une nouveauté PostgreSQL 18 — ils parallélisent les opérations d’I/O disque.
  • Les connexions locales passent par un socket Unix (peer, pas de mot de passe). Les connexions distantes utilisent TCP (scram-sha-256).
  • Les WAL (Write-Ahead Logs) journalisent toute modification avant écriture. Ils permettent le crash recovery, la réplication et le PITR.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn