Héberger PostgreSQL sur un VPS : dimensionner mémoire et disque

Une base PostgreSQL rapide est une base dont les données consultées souvent tiennent en mémoire. Tout le dimensionnement part de là : le volume de la base, la part qui travaille vraiment, le nombre de connexions, puis le disque et sa marge. Ce guide donne la méthode, les réglages de départ pour 4, 8 et 16 Go de mémoire, et les requêtes qui mesurent une base existante.

Publié le 29 octobre 2026 Par Lecture : 10 minutes

Tous les guides

L'essentiel

  1. Mesurez le volume de la base et de ses index, puis la part consultée souvent : c’est elle qui doit tenir en mémoire.
  2. Point de départ : shared_buffers à 25 % de la mémoire, effective_cache_size à 75 %, random_page_cost = 1.1 sur SSD NVMe.
  3. Chaque connexion est un processus : au-delà de quelques dizaines de connexions actives, placez PgBouncer devant la base.
  4. Disque : données et index à un an, plus 30 % de marge au moins. Un disque plein arrête PostgreSQL.
  5. Le taux de lecture en cache doit rester au-dessus de 99 % : en dessous, la base manque de mémoire.
  6. Sauvegardez chaque jour par pg_dump, hors du serveur, et restaurez régulièrement pour le vérifier.

Partir du volume utile

La mémoire d'un serveur de base de données sert d'abord de cache : une page lue en mémoire se sert bien plus vite qu'une page lue sur disque, même NVMe. La question n'est donc pas seulement « combien pèse la base ? », mais « quelle part est lue souvent ? ». Une base de 50 Go dont seuls les douze derniers mois sont consultés travaille peut-être sur 8 Go.

Sur une base existante, deux requêtes donnent le volume total et les plus grosses tables, index compris :

SQL (psql)
SELECT pg_size_pretty(pg_database_size(current_database()));

SELECT relname AS nom,
       pg_size_pretty(pg_total_relation_size(relid)) AS taille_avec_index
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;

Pour une base à venir, estimez table par table : nombre de lignes attendues à un an × taille moyenne d'une ligne, puis ajoutez les index, qui pèsent couramment de 30 à 100 % des données. Exemple : 2 millions de lignes par mois, de 500 octets chacune, font 12 Go de données à un an, et 18 à 24 Go avec les index.

La mémoire : les réglages de départ

PostgreSQL garde les pages lues à deux niveaux : son propre cache (shared_buffers) et le cache de fichiers du système. Sa documentation recommande de partir de 25 % de la mémoire pour shared_buffers sur un serveur dédié, et observe qu'au-delà de 40 % le gain devient rare : le reste profite au cache du système et aux tris.

Paramètre4 Go8 Go16 GoRôle
shared_buffers1 Go2 Go4 GoLe cache propre de PostgreSQL
effective_cache_size3 Go6 Go12 GoLe cache total estimé, qui oriente le choix des plans de requête
work_mem8 Mo16 Mo32 MoLa mémoire de chaque tri ou hachage, par connexion : à multiplier par les requêtes simultanées
maintenance_work_mem256 Mo512 Mo1 GoLa création des index et le VACUUM
random_page_cost1.11.11.1Le coût estimé d’une lecture aléatoire : 4 par défaut, bien au-dessus du coût réel sur SSD NVMe

Ces valeurs supposent une base seule sur le serveur. Si l'application tourne à côté, retirez d'abord sa mémoire (processus, cache, compilation) et appliquez les pourcentages au reste : un serveur de 8 Go qui fait tourner une application de 3 Go se règle comme une base de 5 Go.

postgresql.conf, pour un serveur de 8 Go dédié à la base
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 16MB
maintenance_work_mem = 512MB
random_page_cost = 1.1

shared_buffers ne prend effet qu'au redémarrage de PostgreSQL ; les autres paramètres se rechargent sans interruption, par SELECT pg_reload_conf();.

Pour savoir si la mémoire suffit, lisez le taux de lecture en cache. Sur une application de gestion ou un site, il dépasse 99 % :

SQL (psql)
SELECT round(100.0 * blks_hit / nullif(blks_hit + blks_read, 0), 2) AS taux_cache
FROM pg_stat_database
WHERE datname = current_database();

Les connexions : un processus chacune

PostgreSQL ouvre un processus par connexion, et en accepte 100 par défaut (max_connections). Chaque processus occupe quelques mégaoctets au repos, davantage quand il trie ou hache des données (work_mem, parfois plusieurs fois dans une même requête). Relever max_connections à 500 pour suivre une application bavarde, c'est exposer le serveur à manquer de mémoire au premier pic.

La bonne réponse est un regroupeur de connexions : PgBouncer, en mode transaction, fait partager quelques dizaines de connexions réelles à des centaines de connexions de l'application. Les frameworks ont aussi leur propre pool (SQLAlchemy, Prisma, HikariCP) : réglez sa taille sur le nombre de vCPU du serveur de base plutôt que sur le nombre d'utilisateurs.

Le disque : volume, marge et journal

Le disque d'un serveur PostgreSQL porte plus que les tables :

La règle : le volume à un an, plus 30 % de marge au moins. Ce n'est pas du confort : quand le disque qui porte le journal de transactions se remplit, PostgreSQL s'arrête pour protéger ses données. Surveillez l'occupation, et agrandissez avant 80 %.

Côté performance, chaque validation de transaction attend l'écriture du journal sur disque : la latence du stockage fixe le débit d'écriture. C'est là qu'un SSD NVMe fait la différence, bien plus que sur les lectures, que la mémoire sert déjà.

Le processeur : une requête, un cœur

Une requête PostgreSQL s'exécute sur un seul cœur, sauf les grosses lectures que le moteur parallélise. Le nombre de vCPU fixe donc le nombre de requêtes lourdes traitées en même temps : 2 vCPU suffisent à une application de gestion au lancement, 4 à 8 conviennent aux bases très sollicitées et aux rapports lourds.

Avant d'ajouter des vCPU, cherchez les requêtes qui les consomment. L'extension pg_stat_statements les classe par temps total :

postgresql.conf, puis redémarrage
shared_preload_libraries = 'pg_stat_statements'
SQL (psql)
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

SELECT calls, round(total_exec_time) AS ms_total,
       round(mean_exec_time::numeric, 1) AS ms_moyen, query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

Même serveur que l'application, ou serveur séparé ?

Au lancement, la base sur le même serveur que l'application est le bon choix : aucune latence réseau entre les deux, une connexion par socket Unix, un seul serveur à sauvegarder et à surveiller. On sépare quand les deux se disputent les ressources : une compilation ou un pic de trafic qui vide le cache de la base, une base qui a besoin de toute la mémoire pour ses données, ou des exigences de sauvegarde différentes.

Sécurité et sauvegardes

Terminal : export compressé, puis restauration dans une base de test
pg_dump -Fc -d ma_base -f ma_base-$(date +%F).dump
createdb ma_base_test
pg_restore -d ma_base_test ma_base-2026-10-29.dump

Une base PostgreSQL rapide, sur le bon serveur

Le VPS Pro tourne sur processeurs Intel Xeon, mémoire ECC qui corrige les erreurs à la volée et SSD NVMe en miroir, chaque bloc de données vérifié par somme de contrôle et une sauvegarde chiffrée chaque nuit, hors de la machine. L'Assistance intégrale est comprise : quand votre base ralentit, nous analysons les requêtes lentes et les index, puis nous vous indiquons les réglages qui rendent sa vitesse à votre application.

Découvrir le VPS Pro

Questions fréquentes

Combien de RAM pour PostgreSQL ?

Assez pour que les données consultées souvent tiennent en mémoire. Pour une application de gestion au lancement, 4 Go suffisent, base et application comprises. Ensuite, mesurez le taux de lecture en cache : tant qu'il reste au-dessus de 99 %, la mémoire suffit.

Quelle valeur pour shared_buffers ?

25 % de la mémoire sur un serveur dédié à la base, comme le recommande la documentation de PostgreSQL : 1 Go sur 4 Go, 2 Go sur 8 Go, 4 Go sur 16 Go. Au-delà de 40 %, le gain devient rare, le cache du système faisant le reste.

Combien de connexions PostgreSQL peut accepter un VPS ?

PostgreSQL en accepte 100 par défaut, et chaque connexion est un processus qui consomme de la mémoire. Plutôt que de relever ce plafond, placez un regroupeur comme PgBouncer devant la base : quelques dizaines de connexions réelles servent alors des centaines de connexions de l'application.

Faut-il séparer la base de données et l'application ?

Pas au lancement : sur le même serveur, la base répond sans latence réseau et l'ensemble se sauvegarde d'un bloc. On sépare quand l'une gêne l'autre, par exemple quand une compilation ou un pic de trafic vide le cache de la base.

Contactez-nous