Aller au contenu

Architecture par échelle

La structure MIC (Model / Interface / Controller, framework-agnostique, DI explicite) reste identique à toutes les échelles. Ce qui change, ce n'est pas le code métier — ce sont le déploiement et les capacités activées. On ne réécrit jamais un controller pour monter en charge : on ajoute des réplicas et on branche une brique.

< 1 000 utilisateurs — monoprocessus

Le palier « démarrage ». L'objectif est la simplicité, pas la résilience.

  • 1 réplica ASGI (uvicorn) + Postgres. Redis optionnel ; SQLite suffit en dev/tests.
  • Pas de cache distribué, pas d'outbox : un seul service, pas de propagation.
  • /health + /ready + /metrics dès le départ — c'est gratuit et ça évite d'ajouter l'observabilité après coup.
  • Repère : quelques dizaines de RPS, p95 < 200 ms sans effort.

< 1 million — réplicas horizontaux + cache + read-models

Le palier « produit en croissance ». On met horizontalement à l'échelle des réplicas stateless.

  • N réplicas stateless derrière un répartiteur de charge. L'état vit dans Postgres / Redis, jamais dans le processus → l'auth est stateless (JWT audience-bound).
  • Redis cache (cache-aside) pour les lectures chaudes ; HTTP response cache pour les GET.
  • Inter-service en push signé, enrobé d'un circuit breaker et rendu sûr par l'idempotence (livraison at-least-once).
  • Outbox transactionnel + EventBus pour la cohérence entre services ; rate limiting par identité en bordure.
  • Repère : centaines à quelques milliers de RPS, p95 < 200 ms / p99 < 500 ms.

> 1 million — sharding, CQRS, fan-out

Le palier « grande échelle ». Les jointures et les chemins synchrones deviennent le goulot ; on pré-calcule et on partitionne.

  • Sharding applicatif Postgres (par tenant / clé de hash) + réplicas lecture.
  • CQRS généralisé : write normalisé (source de vérité) + read-models Redis (Sorted Set / INCR / HLL) alimentés en asynchrone par l'EventBus. La lecture chaude = 1 appel Redis, pas un join.
  • Verrouillage distribué pour les singletons (dispatcher outbox) et workers de drain dédiés.
  • Observabilité : tracing distribué + métriques à cardinalité bornée (status_class), indispensable pour diagnostiquer à ce volume.
  • Repère : 10k+ RPS. La capacité se dimensionne avec marge — pas d'autoscaling magique, la cohérence se gagne par design (idempotence, outbox).

Repères par palier

Palier Réplicas Données Capacités clés RPS indicatif
< 1K 1 Postgres (ou SQLite) health/ready, metrics ~10-50
< 1M N stateless Postgres + Redis cache, response-cache, outbox, eventbus, circuit breaker, idempotence ~100-2 000
> 1M N + workers dédiés Postgres shardé + replicas + Redis read-models/CQRS, sharding, locking, tracing 10 000+

Ce qui ne change jamais

À tous les paliers, la couche M/I/C est la même : controllers purs (fonctions testables sans framework), interfaces fines (HttpRouteSpec), modèles SQLModel sans logique. Un service qui passe de 1 à 22 modules, et de 1K à 1M+ utilisateurs, garde la même structure — voir Structure canonique. C'est la promesse MIC : faire évoluer le déploiement, jamais réécrire le métier.