11 oct. 2025·8 min de lecture

Bloat Postgres et réglage d'autovacuum pour de meilleures performances

Bloat Postgres et réglage d'autovacuum : apprenez à repérer le bloat des tables et index, ajuster l'autovacuum en sécurité et planifier la maintenance pour retrouver des performances.

Bloat Postgres et réglage d'autovacuum pour de meilleures performances

Ce qu'est le bloat Postgres et pourquoi l'autovacuum compte

Le bloat est l'espace supplémentaire et gaspillé à l'intérieur des tables et des index Postgres qui s'accumule avec le temps. Il suit généralement un régime constant d'UPDATEs et de DELETEs. Postgres n'écrase pas les lignes en place : il écrit une nouvelle version de la ligne et laisse l'ancienne jusqu'à ce qu'un nettoyage intervienne.

Cet espace gaspillé nuit aux performances de plusieurs manières prévisibles. Les requêtes doivent lire plus de pages depuis le disque et la mémoire pour trouver la même quantité de données utiles. Les index deviennent plus grands, donc les recherches et les jointures demandent plus de travail. Les écritures peuvent aussi ralentir parce que Postgres doit maintenir des index plus volumineux et toucher plus de pages. Les sauvegardes et restaurations prennent aussi plus de temps parce qu'il y a simplement plus de choses à copier.

L'autovacuum est le travailleur en arrière-plan qui limite cela. Il fait principalement deux choses :

  • Nettoyer les anciennes versions de lignes pour que leur espace puisse être réutilisé (VACUUM)
  • Mettre à jour les statistiques du planificateur pour que Postgres choisisse de bons plans de requête (ANALYZE)

Un détail important : l'autovacuum ne réduit généralement pas la taille physique du fichier sur le disque. Il rend l'espace réutilisable à l'intérieur de la table, mais l'utilisation disque peut ne pas diminuer. Pour rendre l'espace au système d'exploitation, il faut généralement une maintenance plus lourde (comme VACUUM FULL ou une reconstruction de table), et ces options ont de vrais compromis.

Un exemple simple : un panneau d'administration généré par IA qui « met à jour » les enregistrements utilisateurs à chaque chargement de page peut créer un flux constant de lignes mortes. L'autovacuum peut suivre un temps. Puis un pic de trafic arrive, il prend du retard, et soudain les requêtes courantes paraissent lentes même si la taille du jeu de données n'a pas beaucoup changé.

Le réglage de l'autovacuum n'est pas un interrupteur à activer une fois. Les bons paramètres dépendent de votre taux d'écriture, de la taille des tables et de votre sensibilité au travail en arrière-plan. L'approche la plus sûre est itérative : mesurer, faire de petits changements, observer l'impact, puis ajuster.

Signes courants que votre base souffre de bloat

Le bloat se manifeste souvent par un « rien n'a changé, mais tout est plus lent ». Les données métier peuvent sembler stables, pourtant Postgres doit lire et scanner plus de pages pour répondre aux mêmes requêtes. Ce travail supplémentaire se traduit par plus d'IO, plus de CPU et plus d'attente.

Les signaux qui pointent souvent vers le bloat incluent :

  • Des requêtes qui allaient bien la semaine dernière et qui traînent maintenant, en particulier celles qui faisaient des index scans rapides.
  • L'utilisation disque continue d'augmenter alors que les données métier réelles ne croissent pas au même rythme.
  • Une latence de lecture plus élevée et davantage de cache misses (plus de lectures sur disque plutôt que depuis la mémoire).
  • L'autovacuum tourne souvent, mais vous ne constatez pas la récupération habituelle ensuite.
  • Les sauvegardes et restaurations prennent plus longtemps, et un décalage de réplication apparaît pendant les périodes chargées.

Un indice subtil : le plan de requête est toujours « correct » (il utilise encore l'index attendu), mais les temps sont beaucoup plus mauvais. Cela peut arriver quand l'index est gonflé et plus volumineux que nécessaire, donc Postgres doit lire plus de pages pour le parcourir.

Un autre motif courant : les scans de table deviennent plus lents même si les comptes de lignes restent similaires. Les updates et deletes laissent des tuples morts derrière eux, et quand le nettoyage prend du retard, la table grossit en pages. Postgres a alors plus de pages à parcourir et plus de vérifications de visibilité à effectuer.

Un exemple concret : une petite appli SaaS ajoute un "update last_seen" à chaque requête. Les lectures commencent à timeout pendant les heures de pointe, l'utilisation disque bondit, et l'autovacuum semble occupé toute la journée. Le problème de fond n'est pas une mauvaise requête isolée, mais la base qui fait du travail supplémentaire parce que des lignes mortes et des index surdimensionnés se sont accumulés.

Si vous observez deux signes ou plus en même temps, mesurez le bloat avant de changer les paramètres. Les ajustements d'autovacuum aident surtout quand vous pouvez confirmer quelles tables et quels index grossissent réellement.

Checklist rapide : confirmer le bloat avant d'ajuster

Avant de toucher quoi que ce soit, confirmez que vous avez vraiment affaire au bloat et non à un plan de requête lent, de mauvais index, ou une transaction qui bloque le nettoyage. Le réglage fonctionne mieux quand vous pouvez pointer quelques tables et index spécifiques.

Commencez par obtenir des chiffres simples et comparables semaine après semaine. Concentrez-vous sur :

  • Les plus grandes tables et si elles subissent vraiment des écritures lourdes (les tables froides expliquent rarement le bloat).
  • L'historique d'autovacuum par table : quand il a tourné pour la dernière fois, à quelle fréquence, et s'il prend de plus en plus de temps.
  • Des comptes élevés de tuples morts, surtout sur les tables mises à jour fréquemment.
  • De gros index sur des colonnes à fort churn (les index peuvent brouter même si la table semble correcte).
  • Des transactions de longue durée, car elles peuvent empêcher le vacuum de supprimer les tuples morts.

Si vous voulez un premier passage rapide, ces requêtes donnent généralement assez de signal pour décider quoi investiguer ensuite :

-- Biggest tables
SELECT relname, pg_total_relation_size(relid) AS bytes
FROM pg_catalog.pg_statio_user_tables
ORDER BY bytes DESC
LIMIT 5;

-- Dead tuples and last vacuum/autovacuum
SELECT relname, n_live_tup, n_dead_tup, last_vacuum, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

-- Biggest indexes
SELECT indexrelname, pg_relation_size(indexrelid) AS bytes
FROM pg_stat_user_indexes
ORDER BY bytes DESC
LIMIT 10;

-- Long-running transactions (can block cleanup)
SELECT pid, now() - xact_start AS xact_age, state
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_age DESC
LIMIT 10;

Une façon pratique de lire les résultats : si une table de type events est énorme, a un nombre de tuples morts en hausse et que l'autovacuum court mais ne rattrape jamais, cette table est une candidate au réglage. Si les tuples morts sont élevés sur de nombreuses tables et que vous voyez aussi une transaction qui tourne depuis des heures, corrigez d'abord la transaction longue. L'autovacuum ne peut pas travailler mieux qu'une transaction qui ne finit jamais.

Comment mesurer le bloat des tables et des index (méthodes pratiques)

Commencez par ce que Postgres suit déjà. Le bloat corrèle souvent avec beaucoup de tuples morts et un fort churn (updates et deletes) sur les mêmes tables.

1) Utiliser les statistiques intégrées pour trouver des tuples morts et le churn

Ces vues sont un premier passage rapide et à faible risque. Recherchez les tables où n_dead_tup est élevé, et où n_tup_upd et n_tup_del continuent d'augmenter.

-- Tables with lots of dead tuples
SELECT
  schemaname,
  relname,
  n_live_tup,
  n_dead_tup,
  last_autovacuum,
  last_vacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;

-- Churn (writes) that tends to create bloat
SELECT
  schemaname,
  relname,
  n_tup_ins,
  n_tup_upd,
  n_tup_del,
  n_tup_hot_upd
FROM pg_stat_user_tables
ORDER BY (n_tup_upd + n_tup_del) DESC
LIMIT 20;

Une règle simple : si les tuples morts représentent une large part des tuples vivants et que l'autovacuum ne tourne pas souvent (ou prend longtemps), vous avez probablement du bloat et devriez investiguer les paramètres d'autovacuum et les bloqueurs.

2) Estimer le bloat sans math lourde

Restez pragmatique. Comparez la taille de la relation sur disque au nombre de lignes vivantes qu'elle contient. Si une table est énorme mais que le nombre de lignes vivantes est faible, l'écart est souvent du bloat ou des lignes très larges. Vous pouvez confirmer plus tard avec des outils plus approfondis.

Vérifiez aussi si la table a crû rapidement et n'a jamais diminué. Postgres ne rend pas automatiquement l'espace au système d'exploitation après des deletes/updates normaux, ce qui explique pourquoi on parle souvent de bloat et d'autovacuum ensemble.

3) Vérifier la taille des index vs leur utilité

Les index peuvent aussi brouter, et les index inutilisés sont un coût caché. Comparez la taille à la fréquence d'utilisation de l'index par Postgres.

SELECT
  s.schemaname,
  s.relname AS table_name,
  s.indexrelname AS index_name,
  pg_relation_size(s.indexrelid) AS index_bytes,
  s.idx_scan
FROM pg_stat_user_indexes s
ORDER BY pg_relation_size(s.indexrelid) DESC;

Si un index est volumineux et que idx_scan reste proche de zéro sous une charge réelle, c'est un candidat à suppression ou à refonte. Confirmez qu'il n'est pas requis pour des contraintes, l'unicité, ou une requête rare mais critique avant de le toucher.

4) Quand utiliser des outils d'inspection plus profonds

Si vous avez besoin de chiffres réels sur le bloat, utilisez pgstattuple (ou pgstattuple_approx pour les grosses tables). Il peut rapporter l'espace mort et la densité de tuples, mais il est plus lourd que les vues de stats, donc exécutez-le en période de faible trafic.

5) Prendre une base de référence

Avant de changer quoi que ce soit, enregistrez un instantané : top tables par n_dead_tup, top index par taille, et quelques timings de requête clés. Après le tuning et la maintenance, vous saurez ce qui s'est réellement amélioré.

Pourquoi l'autovacuum prend du retard dans des applications réelles

Trouver le vrai coupable du bloat
Nous examinerons votre code généré par IA et identifierons les schémas d'écriture qui causent le bloat et les requêtes lentes.

L'autovacuum est l'équipe de nettoyage en arrière-plan de Postgres. Il supprime les lignes mortes laissées par les updates et deletes, et garde les statistiques à jour pour que les plans restent pertinents. Il décide quand agir en utilisant des seuils en partie fixes et en partie proportionnels à la taille de la table.

Pour chaque table, Postgres attend que le nombre de lignes modifiées franchisse un déclencheur comme :

  • un nombre de base (autovacuum_vacuum_threshold)
  • plus un pourcentage de la table (autovacuum_vacuum_scale_factor)

Cela marche bien pour de nombreuses tables. Mais les tables à mises à jour fréquentes (sessions, events, queues) peuvent générer des tuples morts plus vite que ces déclencheurs ne se déclenchent, surtout si le scale factor est trop élevé. La table grossit, le déclencheur croît avec elle, et le vacuum arrive en retard.

Bloqueurs réels qui empêchent le nettoyage

La raison la plus fréquente qui empêche le vacuum de supprimer des tuples morts est une transaction longue. Si une transaction reste ouverte, Postgres doit conserver les anciennes versions de lignes, même si tout le monde a fini avec elles. Cela peut être causé par des sessions « idle-in-transaction » (un onglet laissé ouvert), un worker bloqué, ou un job de lot qui englobe trop de travail dans une seule transaction.

Même quand le vacuum peut tourner, il peut être trop timide. L'autovacuum a des limites de coût (combien d'IO il peut utiliser avant de dormir). Sur les systèmes chargés, ces limites sont souvent conservatrices, donc le vacuum progresse lentement pendant que votre appli continue de générer des tuples morts.

Causes cachées qui empirent la situation

Quelques modèles poussent régulièrement l'autovacuum en retard : de grosses mises à jour/suppressions en lot qui touchent la plupart des lignes, des tables chaudes avec des UPDATEs fréquents (même petits), des connexions idle-in-transaction qui gardent des snapshots, des rapports longuement exécutés qui gardent une transaction ouverte, et un trafic en rafales où le vacuum ne rattrape pas les pics entre deux.

Quand vous dépannez le bloat, commencez par trouver deux choses : la table qui churne le plus et la transaction la plus longue qui ne semble jamais finir. Résolvez celles-là en premier, puis ajustez les paramètres.

Étapes pas-à-pas : régler l'autovacuum en sécurité (commencer petit)

La façon la plus sûre de régler l'autovacuum est de changer une chose, sur une table, et de l'observer pendant une journée complète. La plupart des douleurs avec l'autovacuum proviennent de quelques tables à fort churn (sessions, events, logs, tables de queue), pas de toute la base.

Choisissez une table qui reçoit beaucoup d'updates ou de deletes et qui montre des ralentissements. Un bon candidat a généralement un nombre de tuples morts en forte hausse et des écritures fréquentes pendant le trafic normal.

Une séquence contrôlée et modeste qui marche bien :

  1. Choisissez une table à fort churn et prenez une base : nombre de lignes, tuples morts, et fréquence d'autovacuum.
  2. Baissez les scale factors et seuils au niveau par-table pour que la maintenance arrive plus tôt (avant que la table ne devienne énorme). Gardez le changement modeste.
  3. Si le vacuum est trop lent, ajustez la capacité prudemment : augmentez un peu autovacuum_max_workers, ou relevez autovacuum_vacuum_cost_limit pour que les vacuums progressent sans écraser l'appli.
  4. Confirmez qu'ANALYZE maintient des plans précis en surveillant moins de changements surprises de plan et des temps de requête plus stables.
  5. Surveillez pendant une journée complète de trafic réel et comparez : tuples morts, fréquence de vacuum, latence des requêtes, et CPU/IO.

Un réglage pratique par-table ressemble souvent à ceci :

ALTER TABLE public.events SET (
  autovacuum_vacuum_scale_factor = 0.02,
  autovacuum_analyze_scale_factor = 0.01,
  autovacuum_vacuum_threshold = 1000,
  autovacuum_analyze_threshold = 1000
);

Puis validez avec les stats que vous avez déjà :

SELECT relname, n_live_tup, n_dead_tup, last_autovacuum, last_autoanalyze
FROM pg_stat_all_tables
WHERE schemaname = 'public'
ORDER BY n_dead_tup DESC
LIMIT 10;

Exemple : une appli écrit 5 millions de lignes d'événements par jour et supprime les anciennes toutes les heures. Avec les réglages par défaut, le vacuum démarre trop tard et les tuples morts s'accumulent. En baissant les scale factors pour events, l'autovacuum tourne plus souvent, le temps de réponse des requêtes reste plus stable, et vous évitez une maintenance lourde et risquée pendant les heures de pointe.

Si vous avez hérité d'une appli générée par IA où les patterns d'écriture sont désordonnés (boucles de retry, inserts dupliqués, tempêtes d'updates), il vaut la peine de corriger la cause racine. Sinon vous vous retrouvez à régler l'autovacuum pour compenser un comportement défectueux.

Étapes pas-à-pas : récupérer de l'espace et de la vitesse sans casser la disponibilité

Commencez par les outils les moins perturbateurs. La plupart du temps, vous pouvez obtenir des gains notables sans bloquer les écritures ni arrêter l'appli.

1) Lancer un VACUUM normal (souvent suffisant)

Un VACUUM standard supprime les versions de lignes mortes pour que Postgres puisse réutiliser cet espace à l'intérieur de la table. Il met aussi à jour les informations de visibilité pour que les index scans et scans séquentiels s'accélèrent. Il ne réduit pas la taille du fichier disque, mais il arrête souvent l'hémorragie et améliore les temps de requête.

Si possible, faites-le en petits lots (une grosse table à la fois) pendant un trafic faible. Exemple :

VACUUM (ANALYZE) public.big_table;

2) Reconstruire les index bloatés (quand les requêtes restent lentes)

Si le VACUUM sur la table n'aide que peu, les index peuvent être le principal problème. Des index bloatés ralentissent les lectures et augmentent l'IO aléatoire. En production, préférez une reconstruction concurrente pour que les lectures et écritures continuent :

REINDEX INDEX CONCURRENTLY public.big_table_some_idx;

Attendez-vous à ce que cela prenne du temps et utilise de l'espace disque temporaire pendant la construction du nouvel index.

3) Utiliser VACUUM FULL seulement si vous acceptez une interruption

VACUUM FULL réécrit toute la table et peut rendre l'espace disque au système d'exploitation. C'est disruptif car il prend un verrou exclusif sur la table. Cela signifie que les inserts, updates, et souvent les lectures seront bloqués.

Ne l'utilisez que si vous avez une fenêtre de maintenance claire et que l'espace disque est vraiment critique.

4) Options plus sûres pour les très grosses tables

Si une table est énorme et que vous avez besoin d'espace sans blocage prolongé, planifiez une fenêtre de maintenance et utilisez l'une de ces approches : reconstruire d'abord les pires index avec REINDEX CONCURRENTLY, envisager le partitionnement ou l'archivage des données anciennes et la suppression des partitions obsolètes, ou réécrire la table (copier dans une nouvelle table et basculer) quand vous pouvez contrôler le cutover.

5) Vérifier que vous avez vraiment amélioré les choses

Ne vous fiez pas aux impressions. Comparez avant/après avec des vérifications simples :

SELECT relname, n_dead_tup, last_vacuum, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

Vérifiez aussi les tailles et les temps de requête. Si le bloat revient rapidement, la cause racine est souvent le comportement applicatif (gros updates, index manquants, transactions longues).

Un planning de maintenance pour éviter que le bloat revienne

Relier latence et chemins de code
Apportez vos endpoints lents et nous les tracerons jusqu'aux tables qui churnent et à la logique applicative cassée.

Un bon plan de maintenance est volontairement ennuyeux. Il fait du bloat une corvée routinière plutôt qu'une panne surprise. L'objectif n'est pas une amélioration ponctuelle, mais un rythme stable qui correspond au mode d'écriture de votre appli.

Commencez par choisir des fenêtres de maintenance en fonction du trafic réel. Regardez vos 30 à 60 minutes les plus chargées chaque jour et évitez-les. Si vous n'avez pas de graphiques, utilisez des indices simples : heures de caisse, jobs quotidiens, envois marketing, et pics de tickets support.

Un rythme hebdomadaire simple qui fonctionne pour beaucoup d'équipes :

  • Examiner les 5 plus grandes tables et index. Vérifier les tuples morts et les heures de vacuum récentes.
  • Lancer manuellement VACUUM (ANALYZE) sur les quelques tables les plus chaudes si l'autovacuum est régulièrement en retard.
  • Chercher les transactions longues qui bloquent le vacuum.

Une fois par mois, ajoutez une passe plus lourde quand le trafic est au plus bas. L'autovacuum doit gérer le churn normal. Le travail manuel sert aux exceptions : tables en rafale, grosses suppressions, et changements de schéma.

Pour la checklist mensuelle, restez bref et mesurable :

  • Comparer la croissance des tables et index au mois précédent.
  • Vérifier si la durée des vacuums augmente.
  • Décider si une table nécessite des réglages d'autovacuum personnalisés (seuils, scale factors, limites de coût).
  • Planifier un REINDEX ciblé (ou une reconstruction contrôlée) seulement quand vous pouvez tolérer la charge supplémentaire.

Suivez quelques métriques dans le temps : tuples morts (n_dead_tup), taille de la table vs total incluant toast, tailles d'index, et timestamps de vacuum/analyze. Quand vous livrez de nouvelles fonctionnalités, anticipez : toute nouvelle table à fort débit devrait débuter avec des paramètres autovacuum raisonnables et une place dans votre revue hebdomadaire.

Erreurs courantes qui aggravent le bloat et les performances

La plupart des problèmes de bloat empirent parce que la « solution » est appliquée trop largement, trop vite. Vous obtiendrez de meilleurs résultats si vous changez une chose, mesurez, puis changez la suivante.

1) Sur-régler l'autovacuum et provoquer des pics d'IO

Monter les paramètres d'autovacuum sur toute la base peut déclencher des lectures/écritures disque massives. Cela peut ralentir les requêtes utilisateur, augmenter la latence, et ne pas résoudre le pire du bloat si le vrai problème se situe sur quelques tables chaudes.

Une approche plus sûre est de régler au niveau des tables concernées pour la poignée de tables qui churnent le plus (sessions, logs d'événements, queues), puis surveiller l'impact.

2) Utiliser VACUUM FULL sur une table active sans plan

VACUUM FULL peut récupérer de l'espace, mais il réécrit la table et bloque l'accès normal pendant son exécution. Sur une table en production très utilisée, cela peut ressembler à une panne.

Si vous avez besoin d'une grosse récupération d'espace, planifiez une fenêtre de maintenance, envisagez des approches alternatives et confirmez que vous avez assez d'espace libre pour la réécriture.

3) Ignorer les transactions longues et blâmer l'autovacuum

L'autovacuum ne peut pas supprimer les tuples morts si une transaction longue garde des snapshots ouverts. Vous verrez les tuples morts s'accumuler même si l'autovacuum tourne constamment.

Les causes fréquentes sont des sessions admin oubliées, des jobs en arrière-plan qui ne commitent jamais, ou du code applicatif qui ouvre une transaction puis fait un travail lent.

4) Ne changer que les réglages globaux au lieu de corriger les points chauds

Les paramètres globaux d'autovacuum sont des outils grossiers. Le bloat se concentre généralement dans des tables et index spécifiques, et ceux-ci demandent souvent leurs propres seuils et limites de coût.

Si vous réglez globalement, vous risquez de perdre des ressources à vacuumer des tables froides pendant que la table problématique continue de grossir.

5) Mesurer une fois, changer cinq choses et perdre la base

Si vous ajustez plusieurs paramètres en même temps, vous ne saurez pas ce qui a aidé. Gardez une base simple (tailles de table, tuples morts, temps de vacuum/analyze, latence des requêtes) et changez une variable à la fois.

Exemple : de requêtes lentes à des performances stables en une semaine

Sauver une build générée par IA
Hérité d'une app Bolt, v0, Cursor ou Replit ? Nous corrigeons rapidement les parties en désordre.

Une startup lance un fil d'activité : likes, commentaires et marqueurs "vu". Du jour au lendemain, les écritures passent de quelques dizaines par seconde à quelques milliers. L'appli marche encore, mais les pages qui se chargeaient en 200 ms prennent maintenant 2 à 5 secondes.

En deux jours, deux choses sautent aux yeux : les index grossissent vite, l'utilisation disque continue d'augmenter même après suppression d'anciennes lignes, et l'on reçoit des alertes de disque faible. La latence des requêtes devient aussi instable : tout va bien pendant 10 minutes, puis soudainement lent.

Ce que nous avons trouvé

Le point chaud est une table qui change constamment, par exemple activity_events. Elle subit des updates fréquents (flags de statut) et des deletes (nettoyages de rétention). L'autovacuum tourne, mais il est toujours en retard parce que la table atteint rapidement son seuil et continue de changer pendant que le vacuum essaie de rattraper. Les tuples morts s'accumulent, les index bloatent, et des requêtes simples finissent par lire bien plus de pages que nécessaire.

Ce que nous avons changé (sans maintenance risquée « big bang")

Nous avons résolu le problème avec des étapes petites et ciblées :

  • Définir des seuils d'autovacuum par table pour que cette table à fort churn soit vacuumée plus tôt et plus souvent.
  • Augmenter légèrement le travail d'autovacuum pour cette table (limite de coût ou ouvriers) afin qu'il finisse avant le prochain pic.
  • Lancer une reindexation ciblée des pires index bloatés pendant une fenêtre de faible trafic.
  • Programmer une fenêtre de maintenance hebdomadaire pour les quelques tables qui churnent le plus.
  • Modifier les jobs de rétention pour supprimer par petits lots afin que le vacuum puisse suivre.

À la fin de la semaine, la croissance du disque s'est stabilisée et est devenue prévisible. La latence des requêtes a cessé d'être oscillante, et le fil d'activité est redevenu fluide.

Prochaines étapes : stabiliser et traiter la cause racine

Une fois le bloat sous contrôle, l'objectif change : l'empêcher de revenir. La manière la plus sûre est de faire un changement à la fois et d'observer. Cela vous évite d'échanger un problème contre un autre.

Commencez par le pire coupable (une table ou une table de queue qui subit beaucoup d'updates) et appliquez un changement clair. Par exemple : abaisser les seuils et scale factors pour cette table, augmenter la limite de coût pour que le vacuum finisse, réduire le churn applicatif en évitant les réécritures inutiles, ou ajouter des alertes pour les tuples morts, le retard d'autovacuum et les transactions longues.

Après chaque changement, suivez quelques chiffres pendant une semaine : croissance de la table, tuples morts, fréquence d'autovacuum, et p95 du temps de réponse des endpoints qui touchent cette table. Si vous ne voyez pas d'amélioration, revenez en arrière et essayez l'idée suivante.

Rédigez un petit runbook que votre équipe peut répéter :

  • Quelle métrique déclenche une action (ex. : tuples morts > X% ou retard de vacuum > Y heures)
  • Ce que vous changez en premier (réglages par table avant réglages globaux)
  • Comment vérifier le succès (deux métriques et un contrôle côté utilisateur)
  • Ce qu'il faut éviter (VACUUM manuel en période de pointe, transactions longues)
  • Qui prend la décision et quand escalader

Si votre appli a été générée par IA, cherchez des patterns qui créent du churn constant : écritures verbeuses (mise à jour d'une ligne à chaque requête), index manquants sur les clés étrangères, et mauvaise gestion des sessions qui laissent des transactions ouvertes. Un exemple fréquent est un prototype qui écrit last_seen à chaque chargement de page.

Quand vous continuez à ajuster mais que la performance dérive encore, c'est généralement un problème de comportement produit, pas un problème de vacuum. Si vous vous battez contre une base de code générée par IA qui martèle Postgres de manières étranges (flows d'auth cassés, boucles de retry, jobs qui ne s'arrêtent jamais), FixMyMess at fixmymess.ai peut aider à diagnostiquer et réparer ces chemins de code pour que la base cesse de se battre contre un problème insoluble.