Étude de cas · SaaS B2B confidentiel, Amérique du Nord

Réduire la latence p95 d’une API SaaS B2B par 8 grâce à une couche de cache Redis en production

Comment nous avons repensé l’architecture d’une API Python/FastAPI très sollicitée avec une couche de cache Redis à plusieurs niveaux pour faire passer la latence p95 de 1,8 s à 220 ms tout en réduisant de 70 % la charge de PostgreSQL pour un SaaS B2B nord-américain.

  • SecteurSaaS
  • Année2024
  • PaysÉtats-Unis
  • Durée4 mois
Cutting B2B SaaS API p95 Latency 8x with a Production Redis Caching Layer hero screenshot

Résultats en un coup d'œil

  • 8xBaisse de la latence p95 sur les points d'accès les plus sollicités (1,8 s → 220 ms)
  • 70%Réduction de la charge de lecture PostgreSQL
  • 3,4 K$/moisMise à niveau RDS évitée — mission rentabilisée en 90 jours
  • 99.97%Disponibilité de la couche de cache sur les 6 premiers mois

Le défi

Un SaaS B2B en forte croissance se heurtait à un mur. Son API Python/FastAPI alimentait des tableaux de bord pour des milliers de comptes à licences, et le chemin de lecture était devenu un enchevêtrement de requêtes ORM N+1, de vérifications de permissions répétées et de consultations de feature flags à chaque requête. La latence p95 des points de terminaison les plus sollicités était passée de 380 ms au lancement à 1,8 s, le CPU RDS était saturé à 80 % pendant les heures de bureau, et l’équipe d’ingénierie chiffrait déjà une montée en gamme verticale de RDS qui aurait ajouté environ 3 400 $/mois à la facture.

Pire, la lenteur était invisible pour la moitié de la clientèle car le tableau de bord s’affiche progressivement — le temps que les clients se plaignent, l’équipe avait déjà perdu un renouvellement d’entreprise à cause de « le tableau de bord semble cassé ». L’équipe avait besoin d’une solution en quelques semaines, pas d’une replateformisation de six mois.

Notre solution

Nous avons placé une couche de cache Redis rigoureuse à trois niveaux devant les chemins de lecture les plus sollicités et remodelé le modèle de données pour qu’il puisse être mis en cache en toute sécurité. L’investissement a porté sur la conception des clés de cache, les contrats d’invalidation et l’observabilité — et non sur l’ajout aveugle de mémoire.

Niveau 1 : mémoïsation par requête dans le conteneur de dépendances FastAPI, éliminant les consultations en double au sein d’une même requête. Niveau 2 : un cluster Redis 7 partagé (mode cluster, AWS ElastiCache) contenant les lectures chaudes — ensembles de permissions, feature flags, métadonnées de compte, agrégats de tableau de bord — avec des TTL explicites et une enveloppe Pydantic typée pour que les charges mises en cache soient versionnées et évolutives en toute sécurité. Niveau 3 : un worker Celery hors bande qui préchauffe les agrégats les plus demandés immédiatement après les écritures, de sorte que la requête suivante de l’utilisateur soit déjà un succès de cache.

Chaque clé de cache est préfixée par tenant + entité + version, chaque lecture enregistre un succès/échec dans Datadog, et chaque écriture passe par un module d’invalidation unique afin qu’un futur ingénieur ne puisse pas le contourner silencieusement.

  • Cache à trois niveaux : mémoïsation en processus, cluster Redis et workers Celery de préchauffage
  • Enveloppes de cache Pydantic typées avec champ de version explicite pour une évolution de schéma sûre
  • Clés préfixées (tenant + entité + version) pour que les déploiements ne servent jamais des données de formes mixtes
  • Module d’invalidation unique — tous les chemins d’écriture y passent ; aucun contournement silencieux
  • Déploiement en lecture miroir avec comparaison cache/BDD sur 10 % du trafic réel avant la bascule
  • Tableaux de bord Datadog pour le taux de succès, la p95, le taux d’éviction et la marge de mémoire Redis
  • Alertes PagerDuty sur la baisse du taux de succès, les pics d’éviction et le basculement du primaire Redis
  • Tests de charge k6 reproduisant 3 fois le trafic de pointe, avec un modèle de capacité écrit

Comment nous l'avons construit

  1. 01

    Audit des points chauds et carte de mise en cache

    Nous avons commencé par instrumenter l’API existante avec Datadog APM et un profileur SQL sur mesure, puis classé chaque endpoint selon son coût p95 et son volume d’appels. Les 14 endpoints principaux représentaient 91 % du temps total de base de données. Pour chacun, nous avons établi une carte de mise en cache : ce qui peut être mis en cache sans risque, ce qui est propre à un tenant, ce qui est propre à un utilisateur, quelle durée de vie (TTL) et quels événements doivent l’invalider.

  2. 02

    Contrat de cache et conception des clés

    Avant d’écrire la moindre ligne de code Redis, nous avons rédigé un contrat de cache d’une page : enveloppes typées, une fonction unique de construction des clés, des TTL obligatoires, un versionnage par espace de noms pour que les déploiements ne servent jamais des structures périmées, et une règle d’interdiction de contournement appliquée par un petit décorateur vérifié par mypy. Ce fut l’étape la plus importante : elle a évité la pourriture habituelle du cache qui tue ces projets en deuxième année.

  3. 03

    Implémentation par tranches courtes

    Nous avons livré une famille d'endpoints par semaine derrière un feature flag, avec un mode de lecture miroir comparant les résultats du cache et de la base sur 10 % du trafic pendant 48 heures avant la bascule. Les déploiements se faisaient par tenant, de sorte que toute anomalie restait circonscrite, et chaque tranche était accompagnée d'un runbook pour l'ingénieur d'astreinte.

  4. 04

    Observabilité, test de charge, transfert

    Nous avons ajouté des tableaux de bord Datadog pour le taux de succès, le taux d’éviction, le p95 par endpoint et la marge mémoire Redis, puis réalisé un test de charge k6 de 2 heures à 3x le trafic de pointe pour confirmer le nouveau plafond. L’équipe du client a reçu un runbook écrit, des seuils d’alerte et un contrat de suivi de 4 semaines après le lancement pour l’ajustement.

Stack technique

  • Python
  • FastAPI
  • Redis 7
  • PostgreSQL
  • Celery
  • Docker
  • AWS ECS
  • Datadog
  • Ingénierie de la performance backend
  • Python et FastAPI
  • Solutions cloud
  • DevOps et observabilité
“Nous sommes passés de la refonte de notre base de données à la livraison du prochain lot de fonctionnalités clients au cours du même trimestre. UnlockLive a traité l’invalidation du cache comme une véritable discipline d’ingénierie, et non comme un bricolage.”
VP Ingénierie · Client SaaS B2B (nom confidentiel)

Questions fréquentes

Comment décidez-vous de ce qui peut être mis en cache dans Redis pour un SaaS multi-locataire ?

Nous commençons par un audit de mise en cache de chaque endpoint : frontière du tenant, tolérance à la fraîcheur et événements qui invalident le résultat. Les agrégats par tenant avec des chemins d’écriture clairs sont des gains faciles ; les jointures entre tenants ne le sont presque jamais. Chaque valeur en cache reçoit une enveloppe typée et une clé versionnée pour que les futurs changements de schéma n’empoisonnent pas le cache.

Comment éviter les données périmées et le classique problème d'invalidation du cache Redis ?

Deux règles : chaque chemin d’écriture passe par un module d’invalidation unique (imposé par un décorateur typé pour qu’il ne puisse pas être contourné), et chaque clé de cache inclut une version de schéma. Nous exécutons aussi en production un mode de lecture fantôme qui compare les résultats du cache et de la base sur une partie du trafic avant de promouvoir un nouvel endpoint mis en cache.

Quand la mise en cache Redis permet-elle réellement d’économiser sur AWS, et quand n’est-elle que de la complexité ?

Cela s'amortit lorsque vous pouvez démontrer une économie mesurable sur RDS ou sur le calcul, typiquement quand vos lectures fréquentes représentent 60 % ou plus du temps total de la base et que la charge présente une localité naturelle. Pour nous, le seuil de rentabilité correspond généralement à 3 à 6 semaines de travail d'ingénierie, remboursées par un report de la montée en gamme de RDS. Nous modélisons cela avant de chiffrer le projet.

Utilisez-vous Redis Cluster ou un Redis à nœud unique pour les charges SaaS ?

Nous utilisons par défaut le mode cluster de Redis managé (AWS ElastiCache ou équivalent) pour les SaaS en production : il offre le sharding, le basculement à chaud et une montée en charge prévisible. Un Redis à nœud unique convient pour des files d'attente ou des caches de session, mais pas pour le cache du chemin de lecture qui maintient votre tableau de bord en vie.

Combien de temps dure un projet de cache Redis comme celui-ci ?

Généralement 8 à 16 semaines pour une API FastAPI ou Django de taille moyenne : 2 semaines d'audit et de conception des contrats, 6 à 12 semaines de déploiement tranche par tranche sous feature flags, et une fenêtre de stabilisation de 2 à 4 semaines avec couverture d'astreinte.

Envie d'un résultat comme celui-ci ?

Parlez à l'équipe qui a construit Réduire la latence p95 d’une API SaaS B2B par 8 grâce à une couche de cache Redis en production. Nous définirons le périmètre de votre projet, vous remettrons une proposition à prix fixe et vous présenterons l'exemple le plus proche de notre portfolio.

Réserver un appel stratégique