Pourquoi la mise à l’échelle verticale échoue — et une architecture de mise à l’échelle horizontale desservant 100 000 utilisateurs simultanés sur du matériel conventionnel.

Je n’oublierai jamais le moment où notre API est morte.

C’était mercredi à 14h34. Nous venons d’être présentés sur Product Hunt. Le trafic augmentait. 1200 utilisateurs en ligne… 2400… 4800…

Puis mon Slack a explosé.

“API Timed Out” “Impossible de créer un compte” “Tout est en panne”

J’ai ouvert le panneau de contrôle. Le temps de réponse est passé de 120 ms à 11 secondes. Puis 27 secondes. Ensuite, les demandes… ont simplement cessé d’être traitées.

Notre API s’est heurtée à un mur autour de 8 000 utilisateurs simultanés. Et je ne pouvais rien y faire.

Parce que j’ai commis l’erreur classique que tout ingénieur backend commet au moins une fois : je pensais qu’ajouter plus de CPU au problème résoudrait tout.

Le piège « Actualisez simplement le serveur ».

Deux semaines avant cette catastrophe, notre CTO m’a posé une question simple :

« Pouvons-nous servir 10 000 utilisateurs simultanés ? »

J’ai regardé notre configuration actuelle. Digital Ocean drop, 4 cœurs de processeur, 8 Go de RAM. Nous étions assis à 40 % d’utilisation du processeur avec 1 000 utilisateurs.

Mathématiques de base, non ? Une utilisation de 40 % pour 1 000 utilisateurs signifie que nous pouvons gérer 2,5 000 utilisateurs avant d’atteindre 100 % d’utilisation du processeur.

J’ai donc fait ce qui semblait évident : je suis passé au niveau supérieur. 8 cœurs, 16 Go de RAM.

“Ouais, nous sommes facilement bons pour 10 000 utilisateurs”, lui ai-je dit.

J’avais complètement tort.

Et je n’ai pas réalisé à quel point c’était faux jusqu’à ce que Product Hunt nous envoie 10 000 utilisateurs en 45 minutes.

Ce qui s’est réellement passé (la partie qu’ils ne vous enseignent pas)

Voici ce qui nous a tué, et cela n’a rien à voir avec le processeur :

Notre API Node.js fonctionnait sur une seule instance. Un processus. Un cycle d’événements.

Peu importe que vous ayez 8 ou 80 cœurs tant que l’ensemble de votre application est monothread et bloque les E/S.

Mais le vrai tueur ? Connexion à la base de données.

Nous avons utilisé PostgreSQL avec un pool de connexions de 10. C’est la valeur par défaut dans la plupart des ORM et personne ne la modifie car… cela fonctionne très bien à petite échelle.

Avec 1 000 utilisateurs simultanés, peut-être 50 à 100 requêtes par seconde atteignent la base de données. Un pool de 10 connexions a fait l’affaire. Parfois, il y avait une petite file d’attente, mais rien de notable.

À 10 000 utilisateurs simultanés ? Nous essayions de traiter plus de 1 200 requêtes par seconde sur les mêmes 10 connexions à la base de données.

Le calcul ne fonctionne pas. Je ne peux pas travailler. Cela ne fonctionnera jamais.

Les demandes ont commencé à s’accumuler. 50 ms se sont transformés en 500 ms, qui se sont transformés en 5 secondes, qui se sont transformées en délais d’attente. Un serveur plus gros n’a pas aidé car le goulot d’étranglement n’était pas le serveur.

C’était de l’architecture.

Réveil : mise à l’échelle verticale ou horizontale

J’ai passé toute la nuit à lire tout ce que je pouvais trouver sur le détartrage. Et je n’arrêtais pas de voir les deux mêmes termes : mise à l’échelle verticale contre mise à l’échelle horizontale.

La mise à l’échelle verticale est ce que je faisais. Super serveur. Plus de RAM. Plus de processeur. C’est facile. C’est cher. Et il a un plafond dur.

Vous ne pouvez pas simplement acheter un serveur avec 1 000 cœurs de processeur. Eh bien, vous le pouvez, mais à un moment donné, vous dépassez les limites physiques. Et bien avant cela, vous avez dépassé la limite budgétaire.

La mise à l’échelle horizontale est différente. Au lieu d’un seul gros serveur, vous exécutez plusieurs petits serveurs. Au lieu de mettre à jour, vous multipliez.

Mais voici ce que personne ne vous dit lorsque vous débutez : la mise à l’échelle horizontale ne consiste pas seulement à « exécuter deux serveurs au lieu d’un ».

C’est une façon complètement différente de penser votre architecture.

Reconstruire (qui fonctionne réellement)

Je ne vais pas l’édulcorer – il m’a fallu trois semaines pour le réparer. Mais cela a fonctionné, et nous exploitons désormais plus de 100 000 utilisateurs simultanés sur des serveurs qui coûtent moins cher que ce puissant blob Digital Ocean.

Voici ce que j’ai modifié :

Niveau d’application : 1 instance à N instances

La première chose que j’ai faite a été d’arrêter l’exécution d’un processus Node.js. J’ai commencé à exécuter 8 instances derrière Nginx agissant en tant qu’équilibreur de charge. Même serveur, mais maintenant j’utilise les 8 cœurs.

Le temps de réponse a été instantanément réduit. Non pas parce que le code est devenu plus rapide, mais parce que les requêtes n’étaient plus mises en file d’attente pour la boucle d’événement unique.

Mais 8 exemplaires ne suffisaient pas pour 10 000 utilisateurs. J’ai donc ajouté plus de serveurs. Commencé avec 3 serveurs, 8 instances chacun = 24 processus au total traitant les demandes.

L’équilibreur de charge répartit les requêtes entrantes sur chacun d’entre eux. Quand un serveur meurt ? Les deux autres continuent de courir. Quand le trafic augmentera-t-il ? Ajouter un autre serveur, cela peut prendre 5 minutes.

Niveau base de données : un pool de connexions qui ne craint pas

C’est pénible à comprendre.

J’ai augmenté le pool de connexions de 10 à… 100 ? Cela n’a fait qu’aggraver le problème. Postgres a commencé à s’étouffer avec 100 connexions simultanées. Le processeur a sauté. Les demandes ont été faites plus lentement, pas plus rapidement.

Voici ce qui a réellement fonctionné : PgBouncer.

Il s’agit du pool de connexions qui se situe entre votre application et Postgres. Votre programme pense avoir 100 connexions. Postgres suppose qu’il y en a 20. PgBouncer gère les files d’attente entre eux.

20 connexions Postgres réelles peuvent gérer un débit bien supérieur à 100 car il n’y a pas de surcharge de connexion, pas de changement de contexte, pas de conflit pour les ressources.

Couche de mise en cache : arrêtez de faire référence à la base de données pour tout

Celui-ci est gênant. Nous avons recherché dans la base de données des éléments qui ne changent littéralement jamais.

Photo de profil de l’utilisateur ? Cette URL ne change pas sauf si l’utilisateur télécharge une nouvelle image. Mais nous l’avons demandé pour chaque demande d’API nécessitant des données utilisateur.

Ajout de Redis. Un simple cache clé-valeur. Des données utilisateur qui ne changent pas souvent ? 5 minutes en cache. Des listes de produits ? Mis en cache pendant 1 minute.

Réduisez les requêtes de base de données de 70 %. Aucune exagération. Soixante-dix pour cent du trafic de notre base de données était totalement inutile.

Stockage de session : supprimez-le de votre base de données

Nous avons stocké les sessions dans Postgres. Chaque demande individuelle a vérifié la base de données pour vérifier la session.

Sessions déplacées vers Redis. Recherche de mémoire au lieu de lecture de disque. La validation de session est passée de 15 ms à moins de 1 ms.

Petit changement, grand impact quand vous le faites des milliers de fois par seconde.

Les résultats (et combien ça vaut vraiment)

Après reconstruction :

  • 10 000 utilisateurs simultanés : Les temps de réponse de l’API sont restés inférieurs à 200 ms
  • 50 000 utilisateurs simultanés : Toujours inférieur à 300 ms (vérifié avec des tests de charge)
  • Plus de 100 000 utilisateurs simultanés : Reste stable pendant environ 450 ms

Le coût des infrastructures ? 380 $ par mois en tout.

Comparez cela aux 640 $ par mois que je dépensais pour ce serveur puissant qui ne pouvait même pas gérer 10 000 utilisateurs.

Maintenant, l’architecture ressemble à ceci :

  • 4 serveurs d’applications (4 cœurs, 8 Go de RAM chacun) – 120 $/mois
  • 1 serveur Postgres (8 cœurs, 16 Go de RAM) – 160 $/mois
  • 1 serveur Redis (2 cœurs, 4 Go de RAM) – 40 $ par mois
  • 1 instance de PgBouncer (fonctionnant sur un serveur Postgres)
  • Équilibreur de charge Nginx (exécuté sur l’un des serveurs d’applications)

Total : 320 $/mois pour les serveurs + 60 $/mois pour la bande passante = 380 $/mois

Et c’est évolutif. Besoin de servir 200 000 utilisateurs ? Ajoutez deux serveurs d’applications supplémentaires pour 60 $ par mois. C’est tout.

Ce que j’ai appris (à la dure)

Écoutez, je ne vais pas prétendre avoir compris cela à partir des premiers principes. J’ai lu beaucoup d’articles de blog. J’ai copié des architectures d’entreprises qui savent vraiment ce qu’elles font. J’ai commis de nombreuses erreurs en cours de route.

Mais voici la principale leçon que j’aurais aimé que quelqu’un me dise à l’avance :

La mise à l’échelle verticale est une solution temporaire. Le zoom horizontal est le seul moyen de zoomer réellement.

Vous ne pouvez pas acheter une mauvaise architecture. Un serveur plus gros ne fait que retarder l’inévitable.

Dès que vous concevez une évolution (instances multiples, applications sans état, mise en cache externe, regroupement de connexions), vous débloquez une évolutivité pratiquement infinie. Parce que vous pouvez toujours ajouter des cases supplémentaires.

Et voici ce qui m’a surpris : c’est effectivement le cas Plus facile travaillez une fois que vous avez dépassé la courbe d’apprentissage initiale.

Un serveur tombe en panne ? Peu importe, les trois autres travaillent toujours.

Besoin de déployer une mise à jour ? Déploiement incrémentiel : mettez à niveau un serveur à la fois pendant que les autres gèrent le trafic.

Pic de trafic ? Ajoutez un serveur. Le trafic baisse ? Supprimez le serveur.

Vous arrêtez de vous soucier de « ce serveur va-t-il le gérer » et commencez à penser en termes de « de combien de serveurs ai-je besoin ».

The Framework (gratuit – découvrez-le vous-même)

Je n’écrirai pas ici un tutoriel complet, mais voici le modèle de base :

Niveau 1 : équilibreur de charge

  • Nginx ou HAProxy
  • Distribue le trafic sur N serveurs d’applications
  • Bilans de santé pour le routage des serveurs morts

Niveau 2 : serveurs d’applications (N instances)

  • Uniquement les applications apatrides
  • Pas de stockage sur disque local
  • Aucune session en mémoire
  • Chaque exemplaire est identique et interchangeable

Niveau 3 : niveau de mise en cache

  • Redis pour les sessions et les données fréquemment consultées
  • Stratégies d’expiration du cache
  • Réchauffer le cache pour les données importantes

Couche 4 : pool de connexions à la base de données

  • PgBouncer ou similaire
  • Limite les connexions réelles à la base de données
  • Mettre les demandes en file d’attente intelligemment

Niveau 5 : Base de données

  • Lisez les signaux si nécessaire
  • Indexation correcte (c’est quand même important)
  • Optimisation des requêtes (également important)

C’est une telle régularité. Ce sont les détails qui deviennent compliqués, mais ce sont les bases.

Ou tout simplement apprendre de personnes qui l’ont déjà fait

Écoute, tu peux passer trois semaines à comprendre ça comme je l’ai fait. Lire des articles de blog, tester différentes configurations, planter la production encore quelques fois.

Vous pouvez également tirer des enseignements de modèles de conception de systèmes qui fonctionnent réellement à grande échelle.

J’ai compilé tout ce que j’ai appris sur la mise à l’échelle (pas seulement dans ce cas, mais aussi depuis la conception de systèmes qui gèrent le trafic réel) dans un guide structuré.

Vous faites face à des problèmes de mise à l’échelle ? Obtenez un kit de survie gratuit qui vous montre comment réfléchir à la conception de systèmes : → Kit d’entretien de conception de systèmes

Vous souhaitez un cadre de conception de système complet ? → Bible d’entretien sur la conception de systèmes —

La Bible des entretiens sur la conception de systèmes – Plus de 15 cas et modèles complets d’évolutivité

Il couvre plus de 15 études de cas complètes (Instagram, Uber, systèmes de niveau Netflix), des modèles de mise à l’échelle, des formules d’estimation de puissance et des cadres de compromis. En gros, tout ce que je voulais avoir avant d’essayer d’augmenter le nombre d’utilisateurs à 10 000 sur un serveur.

Plus de catastrophes et de solutions pour augmenter la production ? Abonnez-vous à ma newsletter Substack où je décompose les systèmes réels et comment ils évoluent réellement.

Des post-mortems avec l’IA en 2 minutes ? Découvrez ProdRescue AI – crée une analyse des causes profondes basée sur des faits afin que vous ne passiez pas 4 heures à rédiger des rapports d’incident.

Deurim Ozkai est un ingénieur back-end qui a appris qu’on ne peut pas acheter sa solution pour évoluer avec un serveur plus gros. Il écrit sur les systèmes qui fonctionnent réellement en production, et pas seulement sur les manuels scolaires.


Notre API a bien fonctionné pour 1000 utilisateurs. Il est totalement mort à 10 000 ans. a été initialement publié sur Stackademic sur Medium, où les gens poursuivent la conversation en soulignant et en répondant à cette histoire.

PakarPBN

A Private Blog Network (PBN) is a collection of websites that are controlled by a single individual or organization and used primarily to build backlinks to a “money site” in order to influence its ranking in search engines such as Google. The core idea behind a PBN is based on the importance of backlinks in Google’s ranking algorithm. Since Google views backlinks as signals of authority and trust, some website owners attempt to artificially create these signals through a controlled network of sites.

In a typical PBN setup, the owner acquires expired or aged domains that already have existing authority, backlinks, and history. These domains are rebuilt with new content and hosted separately, often using different IP addresses, hosting providers, themes, and ownership details to make them appear unrelated. Within the content published on these sites, links are strategically placed that point to the main website the owner wants to rank higher. By doing this, the owner attempts to pass link equity (also known as “link juice”) from the PBN sites to the target website.

The purpose of a PBN is to give the impression that the target website is naturally earning links from multiple independent sources. If done effectively, this can temporarily improve keyword rankings, increase organic visibility, and drive more traffic from search results.

Jasa Backlink

Download Anime Batch

Leave a Reply

Your email address will not be published. Required fields are marked *