Le problème se prépare souvent en silence. La latence médiane reste correcte, les serveurs paraissent disponibles et aucun client ne se plaint encore. Pourtant, l’attente du pool SQL double chaque semaine, les messages les plus anciens vieillissent et un quota partenaire laisse moins de marge à chaque pic.
Le vrai enjeu est de reconnaître la ressource ou la frontière qui borne le débit avant que toute la demande ne s’y aligne. Le goulet n’est pas forcément le composant le plus chargé. Il est l’endroit où une unité de travail attend et où ajouter de la demande augmente davantage la file que le résultat.
Contre-intuitivement, augmenter la capacité d’un étage peut dégrader le parcours. Plus de workers peuvent saturer la base, un cache peut servir une décision ancienne et un timeout plus long peut immobiliser le pool. L’action utile confirme d’abord le mécanisme et le coût déplacé.
Dans une application web métier sur mesure, la capacité se mesure de bout en bout. Ce guide relie débit, attente, files, saturation et cohorte, puis propose des expériences bornées, des seuils locaux et un repli avant toute optimisation.
Définir le goulet comme une contrainte de débit
Distinguer travail, file et service
Un parcours alterne files et étapes de service. Le débit maximal est contraint par l’étape dont la capacité utile est la plus faible dans les conditions actuelles. Cette contrainte peut être CPU, verrou, connexion, quota, opérateur ou écriture séquentielle.
Le goulet change avec la charge, la cohorte et le code. La base peut borner les imports la nuit tandis qu’un partenaire borne les validations le jour. Le diagnostic nomme fenêtre et population au lieu de déclarer « la base est le goulet » pour toujours.
Observer la pente
Une file qui se vide après le pic possède une marge. Une file dont l’âge augmente alors que le trafic se stabilise signale un débit de sortie insuffisant ou un travail bloqué. La pente et le temps de récupération importent autant que le niveau.
Mesurer le parcours avant les ressources
L’équipe choisit un résultat : commande confirmée, facture disponible ou dossier synchronisé. Elle mesure arrivées, résultats, durée, erreurs et travail en cours. Ces valeurs donnent le moment où la promesse dérive et évitent de commencer par cinquante graphes système.
Le parcours est découpé aux frontières observables : acquisition de connexion, requête, publication, attente de file, appel externe et persistance finale. La somme des moyennes n’explique pas une queue ; les distributions et traces montrent où certains dossiers attendent.
Séparer latence de service et temps d’attente
Une requête SQL de 30 ms peut être précédée de 800 ms d’attente de connexion. Optimiser la requête ne rendra pas ces 800 ms. L’instrumentation conserve les deux durées et le nombre d’unités en attente.
Chercher l’attente et la file qui grandit
Les files explicites vivent dans un broker ; les files implicites apparaissent dans pool, thread, mutex, socket, verrou ou liste de tâches humaines. Chaque ressource partagée peut transformer un pic en attente. Le dashboard mesure longueur, âge, temps d’acquisition et abandons.
L’âge du plus ancien révèle la promesse, tandis que la profondeur estime le stock. Un seul dossier bloqué peut avoir un âge élevé sans manque global de capacité ; la cohorte et la cause du blocage évitent d’ajouter des ressources inutilement.
Mesurer le temps de récupération
Après le pic, le système doit absorber le backlog avant la prochaine vague. Si dix minutes de surcharge exigent deux heures de rattrapage, la marge est fragile. Le seuil local tient compte du rythme métier et des fenêtres suivantes.
Examiner utilisation, saturation et erreurs
La méthode USE publiée par Brendan Gregg propose d’examiner, pour chaque ressource, utilisation, saturation et erreurs. Elle structure l’enquête sans affirmer que la première ressource élevée est la cause.
Une utilisation proche de 100 % n’est problématique que si attente ou perte apparaît. Une utilisation moyenne faible peut masquer un cœur saturé, une limite de quota ou un burst court. Les agrégations conservent distribution et fenêtre adaptée.
Inventorier les ressources réelles
CPU, mémoire, disque et réseau ne suffisent pas. Pools SQL/HTTP, workers, descripteurs, connexions, quotas, verrous et threads ont une capacité. L’inventaire relie chaque ressource au parcours qui la consomme.
Lire pools, verrous et plans SQL
Le dashboard sépare temps d’acquisition, durée de requête, transactions, verrous, connexions actives et erreurs. Une multiplication des connexions peut réduire l’attente locale tout en augmentant la contention et la mémoire du serveur.
La documentation PostgreSQL sur EXPLAIN décrit l’analyse des plans. EXPLAIN ANALYZE exécute la requête : il est utilisé avec prudence, surtout pour une écriture. Le plan est comparé sur une donnée et des paramètres représentatifs.
Traquer les verrous avant les CPU
Une transaction longue peut sérialiser le travail sans saturer le processeur. Le diagnostic cherche bloqueur, attente, ordre des verrous et durée. Tuer une session restaure temporairement sans corriger la séquence applicative.
Observer âge, débit et retries des files
Entrées, sorties, âge maximal, durée de traitement, en cours, retries et erreurs définitives donnent la capacité. La profondeur seule ne distingue pas un burst absorbé d’un consommateur arrêté. Les catégories prioritaires restent séparées.
Un retry immédiat amplifie la charge sur la dépendance en panne. Temporisation, jitter, concurrence et budget de retry limitent l’orage. Le statut métier passe à intervention requise lorsque la promesse ne peut plus être tenue.
Contrôler les messages lents
Un petit nombre de jobs longs peut monopoliser les workers. Le dashboard montre distribution par type et cohorte, pas l’identifiant en label. Une file dédiée ou une limite de concurrence peut isoler le travail lourd sans extraire un service.
Intégrer quotas et dépendances externes
Le débit dépend d’un quota par seconde, d’une concurrence, d’une fenêtre ou d’une capacité contractuelle. L’application suit consommation, refus, latence et marge. Elle ne découvre pas le quota uniquement dans les erreurs du client.
Timeouts et pools sont cohérents avec la promesse. Un timeout plus long retient une ressource et peut réduire le débit. Un circuit ouvert ou une limitation du producteur protège le système quand la dépendance ne suit plus.
Distinguer lent et inconnu
Après timeout, l’effet externe peut avoir eu lieu. Le retry exige idempotence ou rapprochement. Le goulet de support créé par les résultats inconnus compte dans le coût, même si les machines restent disponibles.
Refuser le cache qui masque une décision périmée
Un cache réduit la demande sur une ressource, mais ajoute invalidation et staleness. Il convient aux données dont l’âge acceptable est défini. Une décision de droit ou de stock peut devenir fausse avant l’expiration.
Le tableau suit hit ratio, latence, évictions, taille et âge de la valeur, mais le taux de hit n’est pas un objectif seul. Un cache à 99 % qui sert une autorisation révoquée échoue. La clé, la version et la stratégie d’invalidation sont testées.
Comparer le coût déplacé
Le cache peut déplacer le goulet vers mémoire, réseau ou invalidation. L’expérience mesure la ressource d’origine et la nouvelle. Le rollback désactive le cache sans rendre la base incapable d’absorber le retour de trafic.
Tester la charge sans fabriquer un faux verdict
Le scénario reproduit mix d’opérations, tailles, concurrence, données et dépendances. Monter uniquement les lectures d’une route chaude ne prédit pas le batch du lundi. La montée est progressive et garde des paliers pour observer pente et récupération.
L’environnement diffère de la production ; le résultat est qualifié. Les quotas et tailles sont ajustés ou simulés. Le test ne touche pas des services externes sans accord. Le succès vient d’un modèle explicite, pas d’un nombre de requêtes spectaculaire.
Arrêter avant l’effondrement
Un seuil local de latence, erreur, saturation ou backlog stoppe le palier. Le test vérifie dégradation et retour au nominal. Une récupération manuelle non documentée invalide la capacité annoncée.
Définir des signaux faibles actionnables
Le signal précoce est proche du mécanisme : attente de pool, âge, quota restant, verrous ou temps de rattrapage. Il précède la plainte mais doit conduire à une action. Une tendance sans propriétaire devient un graphique ignoré.
Les seuils comparent une baseline locale, une promesse et une marge. Par exemple, si l’âge d’une file dépasse la moitié de la fenêtre métier et continue d’augmenter sur trois mesures, l’équipe réduit le producteur non essentiel avant violation.
Réviser après changement
Un index, une nouvelle cohorte ou un quota modifie la capacité. Les seuils sont recalibrés avec des données représentatives. Une alerte devenue bruyante est corrigée, pas simplement silencée.
Cas concret : plus de workers, moins de débit
Cas concret hypothétique. Une synchronisation ERP accumule 8 000 messages. L’équipe double les workers ; la profondeur augmente plus vite. Le CPU applicatif reste bas, mais l’attente du pool SQL et les verrous sur une table de statut explosent.
Le pilote revient à la concurrence précédente, regroupe une lecture, réduit la transaction et ajoute un index vérifié sur le volume. Il augmente ensuite les workers par paliers. Le débit progresse jusqu’au point où le quota ERP devient la contrainte suivante.
Le go retient une concurrence avec marge, un rate limit et un âge d’alerte local. Le runbook suspend les imports non critiques si le pool attend. La cause est la transaction trop large, pas un manque générique de machines.
Observer la contrainte suivante
L’équipe répète le palier avec une distribution réaliste. Les cas lourds restent isolés dans une file dédiée et le débit utile se stabilise. Elle vérifie qu’un redémarrage restitue les messages sans doubler l’écriture ERP. La mesure relie donc capacité et correction métier, pas seulement messages par seconde.
Un mois plus tard, le quota partenaire devient la première contrainte. Le tableau montre refus et marge avant que la file ne vieillisse. Le produit priorise les mises à jour de stock et diffère les enrichissements. La contrainte, le diagnostic et le seuil changent ensemble.
Pour qui adapter la méthode de capacité
Une application synchrone commence par latence, pools et dépendances. Un système asynchrone ajoute âge et rattrapage. Un traitement humain suit dossiers par étape et capacité d’opérateur. La méthode reste la même, les ressources changent.
Produit qualifie promesse et priorité ; développement instrumente ; plateforme mesure ressources ; exploitation exerce la reprise. Une petite équipe cumule les rôles mais garde les décisions explicites.
Une application saisonnière teste ses pics avant la campagne ; un outil interne stable peut surveiller tendance et récupération pendant les heures ouvrées. Un service soumis à un quota tiers planifie la priorité davantage que l’autoscaling. Le niveau d’effort suit conséquence et délai de correction possibles.
Le test de charge n’est pas toujours nécessaire. Si un pool montre déjà une attente croissante sur un pic réel reproductible, une expérience de concurrence bornée peut suffire. À l’inverse, une nouvelle architecture sans historique demande un modèle explicite et des paliers avant toute promesse de capacité.
Éviter les erreurs fréquentes de capacité
Optimiser la ressource la plus visible
Un CPU haut n’est pas forcément le goulot. L’attente et le débit confirment. Le changement mesure le parcours avant et après, ainsi que la contrainte déplacée.
Confondre profondeur et retard
Une file profonde peut être saine ; une petite file peut contenir un cas bloqué. Âge, distribution et cohorte complètent le stock.
Ajouter du cache sans règle d’âge
Le cache améliore la latence et peut détériorer la décision. L’âge acceptable, l’invalidation, le repli et la charge de retour sont testés.
Arbitrer optimisation, capacité et limitation
Optimiser réduit le travail par unité ; ajouter de la capacité augmente le plafond ; limiter protège une dépendance. L’équipe compare délai, coût, risque et réversibilité. Une solution temporaire garde une date et un signal de sortie.
Si la contention vient d’une transaction, alors ajouter des replicas applicatifs est refusé. Si le quota externe est fixe, le produit arbitre priorité et délai. Si la demande croît durablement, capacité et architecture sont planifiées avec le coût complet.
Choisir une option et son signal de sortie
L’arbitrage explicite aussi le coût caché. Augmenter une base peut acheter du temps mais prolonger la transaction problématique ; limiter le trafic protège le run mais retarde une cohorte. Chaque option possède durée, population, signal de sortie et personne qui peut revenir au réglage précédent.
Le choix entre ces options dépend de la fenêtre disponible. Une optimisation structurelle convient si le mécanisme est compris et testable ; une capacité temporaire achète du temps si elle ne renforce pas la contention ; une limitation protège lorsque le résultat devient inconnu. Ce compromis est revu dès que le signal de sortie est atteint.
Par exemple, avant une campagne de trois jours, l’équipe peut augmenter une ressource après avoir borné les pools, tout en planifiant la réduction de transaction. Elle refuse cette option si le test montre des verrous plus longs. La décision conserve hypothèse, coût, seuil d’arrêt et repli, plutôt qu’une promesse générale de montée en charge.
Si la preuve localise la base, alors l’équipe agit sur transaction, index ou concurrence. En revanche, si le quota partenaire borne le débit, elle priorise et lisse la demande plutôt que de multiplier les workers. Dans ce cas, augmenter la base ne ferait qu’acheter une capacité inutilisée et déplacerait le coût sans améliorer la promesse.
- D’abord, localiser l’attente sur un parcours et une cohorte.
- Ensuite, confirmer le mécanisme avec saturation, erreurs et trace.
- Puis, changer une variable et mesurer la contrainte déplacée.
- Enfin, retenir marge, seuil, repli et plan de capacité.
Fermer le contrat de détection
Les entrées sont trafic, cohorte, version et dépendances. Les sorties sont débit, attente, saturation et promesse. Les responsabilités séparent définition, instrumentation et action. La journalisation relie les cas ; le monitoring suit les distributions.
Les seuils, quotas, pools et ressources sont documentés. Le retry et la concurrence sont bornés. Le rollback restaure le réglage précédent et vérifie le retour de charge. Le runbook couvre limitation, drainage et rapprochement.
Le test crée un backlog, ralentit une dépendance et sature le pool. Une personne non auteure doit localiser le goulot, appliquer le repli et confirmer la récupération sans ajouter arbitrairement des workers.
Plan d’action sur six semaines
Semaines 1 et 2 : cartographier
L’équipe choisit trois parcours, décrit files, étapes, ressources, quotas et promesses. Elle mesure arrivées, sorties, attente et récupération sur les pics réels. Les trous d’instrumentation et cardinalités dangereuses sont corrigés.
Semaines 3 et 4 : provoquer
Des paliers représentatifs sollicitent API, base, file et partenaire simulé. Le pilote injecte verrou, quota, job long et cache froid. Chaque palier garde seuil d’arrêt, version et repli. L’équipe valide que le signal précoce apparaît avant l’impact.
Semaines 5 et 6 : corriger et exercer
Une optimisation et une limitation sont testées séparément. La contrainte suivante est documentée. L’exploitation draine une file et restaure un réglage. Le produit valide la marge sur sa fenêtre. La revue choisit extension ou capacité supplémentaire.
Le plan retire les alertes sans action et les panneaux de simple curiosité. Il attribue pools et quotas. Une nouvelle cohorte n’entre que si le tableau et le runbook savent expliquer son attente et sa récupération.
Clore par une reprise indépendante
La cinquième semaine compare le changement sur les mêmes paliers et données. Elle mesure débit utile, attente, erreurs, coût et temps de récupération. Une amélioration qui augmente les résultats inconnus ou la charge support est refusée même si le nombre brut d’opérations progresse.
La revue finale confie le scénario à une personne non auteure. Elle doit repérer la ressource bornante, expliquer les hypothèses concurrentes, appliquer la limitation et restaurer le réglage. Si elle choisit d’ajouter de la capacité sans regarder l’attente, l’instrumentation ou le runbook reste insuffisant.
Le bilan compare aussi la capacité annoncée au mix réellement testé. Il note tailles, concurrence, données et dépendances simulées. Une évolution du mix déclenche une nouvelle qualification ; le chiffre précédent ne survit pas automatiquement à un nouveau type de job ou à une autre région.
Relier capacité, workflow et monitoring
L’observabilité des workflows métier fournit états et âges ; les tests d’exceptions provoquent retries et résultats inconnus.
Le guide performance et monitoring complète la mesure des ressources. Une migration Symfony compatible évite de confondre changement de schéma et capacité.
- Mesurer débit, attente, saturation et récupération.
- Qualifier cohorte, quota et contrainte déplacée.
- Exercer limitation, drainage et retour au réglage précédent.
Conclusion : prouver le goulot avant d’agir
Un goulet se reconnaît à l’attente et au débit qu’il borne, pas à la ressource la plus impressionnante du dashboard. Il varie avec le parcours, la charge et la cohorte.
Files implicites, pools, verrous et quotas fournissent des signaux avant la plainte. Leur valeur dépend d’un seuil local, d’une action et d’un test de récupération.
L’optimisation responsable mesure le coût déplacé. Plus de capacité, cache ou workers ne devient un progrès que si la promesse s’améliore sans transférer le risque.
Dawap peut instrumenter ces contraintes et éprouver les scénarios de charge dans une mission de développement web et de performance, avec un accompagnement expert jusqu’à un diagnostic et un repli utilisables par l’équipe.