Trois leviers pour des releases plus sûres : trafic, cohortes et feature flags
Vous avez une nouvelle version de votre application prête. Les tests passent en staging. L'équipe est confiante. Mais vous hésitez encore avant d'appuyer sur le bouton de déploiement en production. Cette hésitation est saine. Chaque déploiement comporte des risques, et le moyen le plus sûr de les réduire est de ne pas envoyer le changement à tout le monde en même temps.
L'idée est simple : publier progressivement. Mais "progressif" signifie différentes choses selon ce que vous contrôlez. Lorsque vous décidez de ne pas livrer un changement à tous les utilisateurs simultanément, vous avez trois leviers indépendants à actionner. Chacun contrôle un aspect différent de la release. Comprendre quand utiliser chacun d'eux, et comment ils se combinent, est ce qui distingue un déploiement maîtrisé d'un pari.
Trafic : contrôler la charge qui atteint la nouvelle version
La manière la plus directe de publier progressivement est de contrôler la proportion de requêtes qui atteignent la nouvelle version. Au lieu de router tout le trafic vers l'application mise à jour, vous n'en envoyez qu'une fraction. Cinq pour cent de toutes les requêtes vont vers la nouvelle version. Les quatre-vingt-quinze pour cent restantes continuent de frapper l'ancienne version.
Cette approche s'appelle le fractionnement du trafic (traffic splitting). Vous le configurez au niveau de l'infrastructure : votre répartiteur de charge, votre service mesh ou votre passerelle API. La configuration est simple. Vous spécifiez un pourcentage, et l'infrastructure distribue les requêtes en conséquence. Aucune identité utilisateur n'est impliquée. Aucune logique de ciblage. Juste une proportion brute de trafic réseau.
Le fractionnement du trafic est idéal pour la toute première phase de validation. Vous voulez savoir si la nouvelle version plante au démarrage, génère des erreurs sous charge réelle, ou consomme plus de mémoire que prévu. Comme l'échantillon est aléatoire, vous obtenez un signal rapide sur la santé de base. Si les taux d'erreur grimpent, vous arrêtez le déploiement avant que la plupart des utilisateurs ne soient affectés.
Voici un exemple réaliste utilisant VirtualService d'Istio pour fractionner le trafic à 5% vers la nouvelle version et 95% vers l'ancienne :
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp.example.com
http:
- match:
- uri:
prefix: /
route:
- destination:
host: myapp
subset: v2
weight: 5
- destination:
host: myapp
subset: v1
weight: 95
La limitation est évidente : vous ne pouvez pas contrôler qui reçoit la nouvelle version. Le même utilisateur pourrait frapper la nouvelle version sur une requête et l'ancienne sur la suivante. Cette incohérence est acceptable pour la validation de l'infrastructure, mais elle devient un problème lorsque vous devez observer le comportement dans le temps ou recueillir les retours d'utilisateurs spécifiques.
Cohortes : contrôler qui reçoit la nouvelle version
Lorsque vous devez cibler des utilisateurs spécifiques, le fractionnement du trafic ne suffit pas. Vous voulez que les testeurs internes voient la nouvelle version en premier. Ou les utilisateurs bêta. Ou les utilisateurs d'une région spécifique. Ou les comptes avec un niveau d'abonnement particulier. C'est là que les cohortes entrent en jeu.
Une cohorte est un groupe d'utilisateurs défini par un critère : plage d'ID utilisateur, localisation géographique, type de compte, segment métier, ou tout attribut que votre système connaît. Au lieu de router un pourcentage aléatoire de trafic, vous acheminez tout le trafic d'une cohorte spécifique vers la nouvelle version. C'est ce qu'on appelle un déploiement par étapes (staged rollout).
L'avantage par rapport au fractionnement du trafic est la traçabilité. Lorsque vous publiez vers une cohorte d'utilisateurs internes, vous savez exactement qui voit la nouvelle version. S'ils signalent des problèmes, vous pouvez corréler le problème avec le changement spécifique. Si la cohorte est petite et contrôlée, le rayon d'impact est contenu. Vous pouvez observer les schémas d'utilisation réels, pas seulement les taux d'erreur.
Les cohortes permettent également une expansion progressive. Vous commencez par les utilisateurs internes, puis vous élargissez aux utilisateurs bêta, puis à cinq pour cent des utilisateurs de production dans une région spécifique, puis à vingt-cinq pour cent, et ainsi de suite. À chaque étape, vous avez un groupe d'utilisateurs connu qui fournit un signal. Le déploiement devient une série d'expansions délibérées plutôt qu'une seule décision binaire.
La contrepartie est la complexité. Vous avez besoin de l'infrastructure pour identifier et router les utilisateurs en fonction d'attributs. Votre répartiteur de charge ou votre passerelle doit comprendre l'identité de l'utilisateur, pas seulement les chemins de requête. Cela nécessite souvent une intégration avec des systèmes d'authentification, des bases de données utilisateurs ou une gestion de session. C'est plus de travail à mettre en place que le fractionnement du trafic, mais cela vous donne un contrôle bien plus riche.
Fonctionnalités : contrôler les fonctionnalités actives
Le trafic et les cohortes contrôlent quelle version de l'application un utilisateur exécute. Mais parfois, vous voulez déployer la nouvelle version partout et activer sélectivement des fonctionnalités spécifiques à l'intérieur. Peut-être que la nouvelle version est déjà en cours d'exécution sur tous les serveurs, mais qu'une fonctionnalité particulière ne doit pas encore être visible pour tout le monde. Ou vous voulez activer une fonctionnalité pour un sous-ensemble d'utilisateurs sans redéployer.
C'est là que les feature flags entrent en jeu. Un feature flag est un interrupteur conditionnel dans votre code qui détermine si une fonctionnalité est active pour un utilisateur donné. Le flag peut être activé ou désactivé à l'exécution, sans nouveau déploiement. Vous pouvez activer la fonctionnalité pour dix pour cent des utilisateurs, pour les comptes internes, pour les utilisateurs avec des ID pairs, ou sur la base de toute logique que vous définissez.
Les feature flags découplent le déploiement de l'activation. Vous pouvez déployer le code qui contient une nouvelle fonctionnalité des jours ou des semaines avant que la fonctionnalité ne soit réellement activée. Cela réduit le risque du déploiement lui-même, car vous ne modifiez pas le comportement en même temps que vous modifiez le code. Si quelque chose ne va pas avec la fonctionnalité, vous désactivez le flag. Pas besoin de rollback. Pas de redéploiement. Juste un changement de configuration.
La puissance des feature flags réside dans leur granularité. Vous pouvez cibler des utilisateurs individuels, exécuter des tests A/B, augmenter progressivement l'exposition, ou tuer instantanément une fonctionnalité qui cause des problèmes. Mais cette puissance a un prix. Les feature flags ajoutent de la logique conditionnelle à votre code. Trop de flags, ou des flags qui ne sont jamais nettoyés, créent de la dette technique. Chaque flag qui reste dans le code après le déploiement complet de sa fonctionnalité devient un poids mort.
Combiner les trois leviers
Ces trois composants ne sont pas mutuellement exclusifs. En pratique, une stratégie de déploiement progressif mature les utilise tous ensemble.
Le diagramme ci-dessous montre comment les trois leviers fonctionnent ensemble dans une séquence typique de déploiement progressif.
Une séquence typique pourrait ressembler à ceci :
- Déployez la nouvelle version sur un petit pourcentage du trafic en utilisant le fractionnement du trafic. Validez que l'application ne plante pas et ne fuit pas de mémoire.
- Étendez à une cohorte d'utilisateurs internes en utilisant un déploiement par étapes. Recueillez des retours et observez les schémas de comportement.
- Une fois confiant, déployez la nouvelle version sur tous les serveurs mais gardez une nouvelle fonctionnalité derrière un feature flag. Activez le flag pour dix pour cent des utilisateurs.
- Augmentez progressivement le pourcentage du feature flag tout en surveillant les métriques. Si quelque chose ne va pas, désactivez le flag instantanément.
Chaque levier vous donne un type de contrôle différent. Le trafic contrôle l'ampleur de la diffusion de la nouvelle version. Les cohortes contrôlent qui est affecté. Les fonctionnalités contrôlent ce qui est actif. Lorsque vous comprenez les trois, vous pouvez concevoir une stratégie de release qui correspond à votre tolérance au risque et à vos besoins de validation.
Une checklist pratique
Avant votre prochaine release, posez-vous ces questions :
- Ai-je besoin de valider d'abord la santé de base de l'infrastructure ? Utilisez le fractionnement du trafic.
- Ai-je besoin de retours d'utilisateurs spécifiques ? Utilisez les cohortes et le déploiement par étapes.
- Ai-je envie de déployer le code maintenant mais d'activer les fonctionnalités plus tard ? Utilisez les feature flags.
- Ai-je un moyen de mesurer si la nouvelle version ou fonctionnalité est sûre ? Si non, ne commencez pas encore le déploiement.
L'essentiel à retenir
La publication progressive n'est pas une seule technique. Ce sont trois contrôles indépendants qui résolvent différents problèmes. Le fractionnement du trafic valide l'infrastructure. Les cohortes valident l'expérience utilisateur. Les feature flags séparent le déploiement de l'activation. Les équipes qui publient en toute sécurité sont celles qui savent quel levier actionner, et quand.