Concevez une infrastructure web scalable avec load balancer, cache, sessions externalisees, base de donnees robuste, files asynchrones et observabilite orientee production.
Pourquoi penser scalable des le debut
Une infrastructure web scalable ne consiste pas a ajouter des serveurs des que le trafic monte. Le vrai sujet est de construire une plateforme qui continue a repondre correctement quand le nombre de requetes, le volume de donnees et les taches metier augmentent en meme temps.
Dans la pratique, les premiers points de rupture sont rarement le manque de machines seulement. On voit plutot une session stockee en local qui empeche le load balancing, une base de donnees qui traite trop de lectures inutiles, un export lourd execute dans la requete utilisateur, ou un manque de metriques qui empeche d'anticiper le prochain pic.
Penser scalable des le debut permet donc d'eviter deux erreurs couteuses : surdimensionner trop tot une architecture encore simple, ou a l'inverse decouvrir trop tard que l'application depend trop d'un seul serveur.
Rendre l'application stateless pour scaler horizontalement
Le principe le plus rentable pour une application web moderne est le scaling horizontal : lancer plusieurs instances de l'application derriere un load balancer. Cette approche devient vite impossible si chaque serveur conserve des informations critiques localement.
Une application est plus simple a mettre a l'echelle lorsqu'elle reste stateless cote web. Concretement, cela veut dire :
- ne pas stocker les sessions utilisateur sur le disque local du serveur web ;
- ne pas ecrire des fichiers temporaires metier uniquement sur une machine ;
- ne pas dependre d'un cron local unique pour un traitement critique sans reprise possible ;
- ne pas supposer qu'une requete suivante reviendra sur la meme instance.
Exemple concret : un site e-commerce tourne sur deux serveurs PHP derriere Nginx. Si les sessions sont sauvegardees dans /var/lib/php/sessions en local, un client peut ajouter un produit au panier sur le serveur A puis perdre son panier sur le serveur B. La solution propre consiste a externaliser les sessions vers Redis ou une base adaptee.
; Exemple PHP : sessions dans Redis
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?database=2"
Ce choix rend l'application beaucoup plus souple : vous pouvez ajouter une troisieme ou quatrieme instance sans recoder toute la gestion de session.
Repartir la charge avec load balancer, cache et CDN
Une infrastructure scalable repose souvent sur trois niveaux complementaires : un load balancer pour repartir les requetes, un cache reverse proxy pour eviter de recalculer certaines reponses, et un CDN pour servir les assets statiques au plus pres des visiteurs.
| Couche | Objectif principal | Exemple utile |
|---|---|---|
| Load balancer | Distribuer les requetes entre plusieurs instances | Nginx, HAProxy, ALB |
| Cache proxy | Servir plus vite les pages publiques repetitives | Nginx cache, Varnish |
| CDN | Decharger l'origine pour images, JS, CSS | CloudFront, Cloudflare |
Exemple Nginx avec plusieurs serveurs d'application :
upstream app_backend {
least_conn;
server 10.0.1.11:8080 max_fails=3 fail_timeout=10s;
server 10.0.1.12:8080 max_fails=3 fail_timeout=10s;
server 10.0.1.13:8080 max_fails=3 fail_timeout=10s;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Ici, least_conn est souvent plus pertinent qu'une simple rotation si certaines requetes sont plus longues que d'autres. Vous evitez qu'une instance surchargee recoive encore la meme quantite de trafic qu'une instance presque libre.
Exemple concret : sur un media en ligne, les images et les bundles front sont servis par le CDN, les pages articles anonymes peuvent etre mises en cache quelques minutes, et seules les actions connectees atteignent vraiment l'application. Le resultat est une baisse immediate du nombre de requetes backend.
Externaliser sessions, cache et etat applicatif
Le composant qui bloque le plus souvent la mise a l'echelle n'est pas le serveur web lui-meme, mais l'etat partage. Une plateforme scalable doit clairement separer les sessions utilisateur, le cache de donnees reutilisables, les fichiers generes ou uploades, et les verrous ou compteurs distribues.
Pour les sessions et certains caches, Redis est souvent un tres bon choix. Pour les fichiers, un stockage objet ou partage est generalement plus adapte qu'un disque local. Pour les exports, miniatures ou rapports PDF, il faut aussi penser a la reprise sur incident : si une machine tombe, le travail ne doit pas disparaitre silencieusement.
Exemple concret : une application genere des factures PDF. Si les fichiers sont ecrits dans /tmp sur une instance ephemere, le lien de telechargement peut casser apres un redeploiement. Une strategie plus robuste consiste a generer le PDF en tache asynchrone puis a le stocker dans un bucket objet, avec un enregistrement en base.
Faire evoluer la base de donnees sans casser la production
Beaucoup d'architectures web deviennent non scalables parce que la base de donnees reste traitee comme une boite noire. Pourtant, c'est souvent elle qui supporte les lectures, les jointures couteuses, les files d'ecriture et les verifications transactionnelles.
Avant de parler replica ou sharding, il faut d'abord appliquer les fondamentaux :
- indexer les colonnes vraiment utilisees dans les filtres, tris et jointures ;
- supprimer les requetes N+1 cote application ;
- mettre en cache les lectures tres frequentes et peu volatiles ;
- archiver les donnees historiques qui ralentissent inutilement les ecrans courants ;
- analyser les requetes lentes avant de monter en infrastructure.
Ensuite seulement, vous pouvez faire evoluer la base de facon plus structuree. Un schema classique consiste a garder un noeud principal pour les ecritures et une ou plusieurs replicas pour absorber une partie des lectures.
Application
|
|-- ecritures --> DB primaire
|
`-- lectures non critiques --> DB replica
Exemple concret : sur un back-office, le tableau de bord principal peut lire des indicateurs agreges depuis un cache ou une replica, tandis que la validation d'un paiement ou la mise a jour d'un stock doit rester sur la base primaire pour conserver une coherence forte.
Sortir les travaux lents de la requete HTTP
Une plateforme scalable traite rapidement la requete utilisateur et repousse les traitements lourds hors du chemin critique. C'est indispensable pour les emails, exports CSV, generation de PDF, webhooks, redimensionnement d'images, recalculs analytiques ou synchronisations externes.
Le schema a viser est simple : la requete HTTP valide l'action, cree une tache dans une file, repond vite au client, puis un worker execute le traitement en arriere-plan.
# Exemple de flux
Client -> API -> file de messages -> worker -> stockage / notification
Exemple concret : si un export de 200000 lignes est genere directement dans la requete, l'utilisateur risque un timeout et le pool PHP-FPM reste occupe pendant trop longtemps. Si l'export est delegue a un worker, la page peut afficher "generation en cours" puis proposer le fichier des qu'il est pret.
Cette approche ameliore a la fois l'experience utilisateur et la capacite globale de la plateforme, car les workers peuvent etre mis a l'echelle differemment du front web.
Mesurer, observer et preparer la capacite
On ne gere pas une infrastructure scalable seulement avec des intuitions. Il faut des metriques qui permettent de voir ce qui se passe avant, pendant et apres une montee en charge. Sans cela, chaque ajout de serveur ressemble a un pari.
Les indicateurs minimaux a suivre en production sont generalement :
- temps de reponse par route ou groupe de routes ;
- taux d'erreur HTTP et erreurs applicatives ;
- charge CPU, memoire et saturation disque ;
- latence et nombre de connexions de la base de donnees ;
- taux de hit cache ;
- taille et age moyen des jobs en file ;
- nombre d'instances et etat des health checks.
Exemple concret : si votre CPU reste correct mais que les temps de reponse explosent des que la file de jobs grossit, le probleme n'est pas toujours le front web. Vous avez peut-etre un worker sous-dimensionne qui bloque la mise a disposition de ressources, ou une base qui sature en arriere-plan.
Une bonne pratique consiste aussi a definir une baseline : trafic normal, volume de connexions, memoire habituelle, temps de reponse cible. Sans point de comparaison, il est difficile de savoir si la plateforme se degrade vraiment ou si elle suit simplement sa charge habituelle.
Checklist de mise a l'echelle raisonnable
- Application web : plusieurs instances possibles sans dependance a un disque local critique.
- Sessions : stockees hors du serveur web, idealement dans Redis ou un service adapte.
- Assets : servis via cache navigateur et, si necessaire, via CDN.
- Pages publiques : candidates a un cache reverse proxy avec invalidation simple.
- Base de donnees : indexes utiles, requetes lentes connues, plan de separation lectures/ecritures si besoin.
- Taches lourdes : sorties du cycle HTTP et traitees par des workers.
- Observabilite : logs, metriques, alertes et health checks en place.
- Capacite : tests de charge et seuils de saturation documentes.
- Haute disponibilite : composants critiques identifies et points uniques de panne reduits.
Dans beaucoup de projets, cette checklist suffit deja a passer proprement d'une application mono-serveur a une plateforme capable d'absorber plusieurs pics de trafic sans bricolage de derniere minute.
Conclusion
Une infrastructure web scalable repose d'abord sur des choix d'architecture concrets : application stateless, sessions externalisees, cache bien place, base de donnees observee, traitements lents delegues et metriques lisibles. Ce sont ces decisions qui rendent la mise a l'echelle simple, pas l'ajout brutal de serveurs.
Si vous devez prioriser, commencez par trois chantiers : supprimer l'etat local critique, proteger la base avec du cache et des requetes propres, puis sortir les traitements lourds de la requete HTTP. Vous aurez deja une plateforme bien plus robuste pour absorber la croissance.
Pour aller plus loin, reliez cette approche avec Nginx en reverse proxy et l'optimisation des performances serveur. Ensemble, ces briques forment une base solide pour une infrastructure web qui grandit proprement.