Qu'est-ce que les feature flags ? Guide SRE pratique
Résumé
Les feature flags sont des conditions dans votre code applicatif qui contrôlent quelles fonctionnalités sont visibles pour quels utilisateurs, sans redéployer. Ils découplent déploiement et release, activent les rollouts progressifs par pourcentage, les kill switches instantanés et le ciblage de cohortes d'expérimentation. Pour les équipes plateforme qui livrent en production plusieurs fois par jour, c'est le mécanisme qui rend le continuous deployment fiable plutôt que hasardeux.
Qu'est-ce que les feature flags ? Guide opérationnel pour les équipes plateforme
Les feature flags sont des conditions dans votre code applicatif qui contrôlent quels chemins s'exécutent pour un utilisateur, une session ou un environnement donné, sans déployer un nouveau build. Un flag new_checkout_flow positionné à false pour 99 % de votre base d'utilisateurs signifie que vous avez déployé ce code il y a deux semaines. Vous ne l'avez simplement pas encore activé. Le contrat qu'ils établissent est précis : déploiement et release deviennent deux événements distincts. Pour toute équipe qui pratique le continuous deployment à l'échelle, ce contrat est structurant.
Déploiement et release ne sont pas le même événement
La plupart des équipes font cette distinction après un rollout raté. Une feature passe en production un mardi après-midi, quelque chose dans la request trace commence à se comporter différemment le mercredi matin, et quand quelqu'un ouvre une investigation le diff couvre quatre commits et deux frontières de service. Attribuer la causalité dans ce scénario est genuinement difficile.
Les feature flags imposent la précision. Quand le code derrière un flag est mergé et déployé, il reste inerte en production. Vous confirmez que le déploiement a réussi, vous observez les métriques de base pendant quelques heures ou quelques jours, et vous vérifiez que rien n'a dégradé. Ensuite, vous positionnez le flag pour 1 % du trafic. Vous avez maintenant une seule variable attribuable. Si le taux d'erreur monte sur le chemin flaggé, vous ne déboguez pas un code diff. Vous togglez une valeur de configuration.
Cette séparation n'est pas d'abord un argument de vélocité. C'est un argument de blast radius. Un release qui touche 1 % des sessions et qui tourne mal est récupérable en quelques minutes. Un release qui touche 100 % des sessions et qui tourne mal est un incident majeur.
Le mécanisme lui-même est direct. En TypeScript, une évaluation de flag ressemble à ceci :
const showNewCheckoutFlow = flagClient.variation(
'new_checkout_flow',
{ userKey: session.userId, custom: { plan: user.plan } },
false // valeur par défaut si le service de flags est injoignable
);
if (showNewCheckoutFlow) {
return renderNewFlow(cart);
}
return renderLegacyFlow(cart);La valeur par défaut false n'est pas une formalité. C'est le comportement que vos utilisateurs obtiennent si le service d'évaluation des flags subit une partition réseau. Définissez-la délibérément, pas par accident.
Les quatre types de flags qui comptent vraiment en production
Tous les feature flags ne servent pas le même objectif opérationnel. Les traiter de façon identique dans votre codebase et vos outils de gestion est un chemin fiable vers la confusion lors des incidents et l'accumulation de flag debt.
Les release flags bloquent les nouvelles features pendant le développement et le rollout. Ils sont temporaires par nature : créés quand le travail commence sur une feature branch, supprimés une fois que la feature atteint 100 % des utilisateurs et que l'équipe a confirmé la stabilité. Les release flags sans date de suppression et sans owner désigné deviennent des éléments permanents de votre codebase.
Les experiment flags alimentent les A/B tests et les expériences multivariées. Ils sont liés aux identifiants de cohorte analytics et leur cycle de vie est borné par l'expérience. Quand l'expérience se termine, le flag part avec elle. L'erreur classique : garder la variante gagnante derrière le flag indéfiniment, en arguant que la suppression n'est "pas urgente". Deux ans plus tard, le flag d'expérience fait partie du chemin critique et personne ne se souvient quelle variante est active.
Les ops flags sont des kill switches et des circuit breakers. Contrairement aux release flags, ils sont conçus pour être une infrastructure permanente. Un flag disable_ml_recommendations qui vous permet de contourner une couche d'inférence ML lente quand son SLO se dégrade est quelque chose que vous voulez avoir disponible à 3h du matin sans avoir à lire de la documentation. Ces flags doivent s'évaluer localement, avoir un fallback bien documenté, et être testés régulièrement en fonctionnement normal -- pas découverts sous pression.
Les permission flags contrôlent l'accès par tier utilisateur, plan de compte ou cohorte bêta. Ils sont longs à vivre par conception. Le risque de confusion : les permission flags ressemblent souvent à des release flags pour un lecteur qui ne connaît pas l'historique. Une convention de nommage claire importe plus ici qu'ailleurs.

Un rollout par pourcentage sans SLO gate n'est qu'un déploiement lent
C'est là que la plupart des implémentations de feature flags s'arrêtent trop tôt. L'équipe plateforme câble un calendrier de rollout : 1 % le lundi, 5 % le mardi, 25 % le mercredi, 100 % le vendredi. Elle le documente, le partage avec les parties prenantes, et appelle ça de la progressive delivery.
Mais "progressif" sans condition de validation à chaque étape, c'est du risque différé, pas du risque réduit. Le curseur de pourcentage contrôle l'exposition. Il ne valide pas la sécurité.
Ce qui rend un rollout progressif opérationnellement significatif, c'est la SLO gate entre chaque étape. Avant de passer de 5 % à 25 %, quelque chose doit répondre à ces questions : le taux d'erreur sur le chemin flaggé est-il dans le budget SLO ? La latence p99 tient-elle dans la même bande que le groupe de contrôle ? Le budget d'erreur brûle-t-il plus vite que la baseline ?
Si aucune de ces questions n'est instrumentée, le calendrier de rollout est une timeline, pas une boucle de validation.
Une configuration qui tient en production : définissez deux fenêtres d'évaluation SLO. Une fenêtre courte (15 minutes) attrape les échecs rapides -- une requête SQL mal formée, un mismatch de schéma, une régression sur un chemin critique. Une fenêtre longue (24 heures ou un cycle de trafic complet) attrape la dégradation progressive -- fuites mémoire, pression sur le cache, edge cases dans les segments de trafic peu fréquents. Exigez que les deux fenêtres soient au vert avant tout avancement. Si l'une est violée, arrêtez le rollout et pagez l'on-call.
Le pourcentage est un curseur. La fenêtre SLO est la gate. Les deux sont requis.
Ingénierie des kill switches : concevez-les avant d'en avoir besoin
Le kill switch n'est pas un mécanisme de dernier recours. C'est une décision de conception de première classe qui doit exister avant que la première ligne de code feature soit écrite.
Un kill switch conçu sous pression est un kill switch avec des hypothèses non examinées. Vous le testez pour la première fois au cours d'un incident actif, dans une session terminal ouverte depuis une notification PagerDuty, avec cinq personnes qui regardent un thread Slack. C'est le pire moment possible pour découvrir que votre ops flag cible les utilisateurs par session ID et que votre service de session est actuellement dégradé.

Trois propriétés non négociables pour tout kill switch destiné à la production :
Evaluation locale sous 50ms : le check du flag ne peut pas être un appel réseau vers un service d'évaluation distant. Si l'évaluation dépend d'un service qui pourrait lui-même être dégradé, vous avez une dépendance circulaire dans votre chemin de réponse aux incidents.
Valeur de fallback explicite : que retourne le flag quand le service de flags est injoignable ? Cela doit être documenté, défini dans le code, et testé. "Quelle que soit la valeur par défaut du SDK" n'est pas une réponse.
Testé en cas de défaillance des dépendances : les kill switches doivent faire partie de votre rotation de chaos engineering. Validez-les contre des scénarios où l'auth est dégradée, où le service de flags lui-même est down, et où la latence réseau vers l'endpoint d'évaluation dépasse 2 secondes.
Les équipes qui gèrent les incidents proprement sont celles qui ont répété. Le kill switch fait partie du runbook. Rendez-le ennuyeux.
Flag debt : la dette technique que personne n'inscrit sur la roadmap
Les équipes qui adoptent agressivement les feature flags accumulent souvent ce qu'on appelle du flag debt : des flags qui ont rempli leur objectif mais n'ont jamais été supprimés. La feature a été livrée, l'expérience a conclu, la bêta s'est terminée. Le flag est resté.
À 50 flags, c'est une nuisance mineure. À 500 flags dans un système distribué, c'est un risque opérationnel actif. Chaque flag est une branche de code qui nécessite de la maintenance, des tests, et de la compréhension lors des investigations d'incidents. Un développeur qui essaie de comprendre une défaillance à 2h du matin ne veut pas tracer à travers 40 branches conditionnelles pour trouver celle qui est pertinente.
Un pattern observé dans plusieurs équipes plateforme : le middleware d'évaluation des flags apparaissant dans les cinq premières frames de pile pour la latence p99. La cause dans la plupart des cas est des flags périmés avec des règles de ciblage complexes qui évaluent des dizaines de conditions par requête, portant le poids de décisions prises il y a deux ans que personne ne s'est senti à l'aise de supprimer.
La contre-mesure est organisationnelle plutôt que technique. Chaque flag créé doit avoir trois attributs : un owner, un type (release, experiment, ops, permission), et une date de suppression prévue. Les release flags doivent être supprimés dans les deux sprints suivant le rollout complet. Les experiment flags doivent être supprimés quand l'expérience conclut, pas "quand quelqu'un trouvera le temps". L'inventaire des flags doit être auditable à la demande et visible dans les dashboards de santé engineering.
Granularité du ciblage : la dimension qui se révèle à l'échelle enterprise
La plupart des plateformes de feature flags supportent les rollouts par pourcentage et le ciblage par attributs utilisateur basiques. La lacune qui apparaît à l'échelle enterprise est la granularité du ciblage : la capacité à exprimer des règles de rollout suffisamment précises pour être utiles sans devenir trop complexes pour être maintenables.
Une hiérarchie de ciblage utile pour les rollouts en production au niveau d'une équipe plateforme :
Niveau environnement : production, staging, preview. La première gate, pas la seule.
Segment infrastructure : datacenter, zone de disponibilité, ou cluster Kubernetes. Utile pour isoler le blast radius géographique.
Compte ou tenant : pour les plateformes B2B SaaS, déployer par compte est souvent plus sûr que par pourcentage d'utilisateurs, parce que vous pouvez observer le pattern de trafic complet d'un compte plutôt qu'un échantillon statistique.
Cohorte utilisateur : utilisateurs bêta, utilisateurs internes, power users par tier d'activité.
Attribut de session : utile pour les experiment flags, dangereux pour les ops flags.
Les plateformes qui implémentent bien cela (LaunchDarkly et Statsig sont les plus citées par les équipes SRE qui opèrent à cette échelle) permettent une composition de règles complexes sans nécessiter du temps engineering pour modifier la logique de ciblage pendant un rollout actif. Cette capacité de self-service est la différence entre une pause de rollout de 30 secondes et un ticket à l'équipe plateforme.
Les plateformes qui implémentent mal cela vous forcent à choisir entre granularité du ciblage et simplicité opérationnelle. Ce compromis surgira à 3h du matin.
Ce que le post-mortem continue de trouver
Chaque post-mortem d'un incident de production lié à une feature pose le même ensemble de questions. La feature était-elle derrière un flag ? Le rollout était-il progressif ? Y avait-il une condition de validation entre les étapes ? Le kill switch avait-il été testé avant l'incident ?
Si les quatre réponses sont oui, l'incident est un problème de calibration : seuils définis trop lâchement, règles de ciblage avec un edge case, comportement d'évaluation du SDK en cas de partition réseau qui n'avait pas été pris en compte. Ce sont des problèmes solubles avec des changements de configuration et des mises à jour de runbook.
Si l'une des réponses est non, l'incident est un problème d'architecture. Les feature flags ne sont pas un outil de debugging pratique. Ce sont une décision d'architecture de déploiement. Cette décision existe soit avant que la feature soit livrée, soit elle n'existe pas du tout.
La question à vous poser avant le prochain release : que dirait le post-mortem sur ce rollout si quelque chose tourne mal ce soir ?