C'est quoi un feature flag ? Explication pour développeurs
Résumé
Un feature flag est une condition logique qui toggle du comportement sans redéploiement. Découvrez comment fonctionnent les quatre types de flags (release, experiment, ops, permission), pourquoi ils deviennent de la dette technique quand on ne les nettoie pas, et comment mettre en place un processus de suppression qui marche vraiment.
C'est quoi un feature flag ? C'est une condition dans votre code qui décide au moment de l'exécution si une fonctionnalité est active ou inactive, sans avoir besoin de redéployer. C'est le concept fondamental. En pratique, c'est une instruction if dont la réponse vient d'une config, d'une ligne en base de données, ou d'un service de flags: pas d'une valeur codée en dur.
L'idée est simple. Vivre avec 200 flags dans un repo, c'est autre chose. Et c'est justement ce dont ce guide parle.
C'est quoi concrètement un feature flag dans le code ?
Voici la version minimale qui marche vraiment :
if (flags.isEnabled("new-checkout", { userId })) {
return renderNewCheckout();
}
return renderOldCheckout();Les deux chemins du code sont compilés dans la même build. La valeur du flag vit quelque part où vous pouvez la changer sans redéployer : une variable d'environnement, un fichier JSON, une table, ou un service hébergé. Changez la valeur, et le comportement change à la prochaine évaluation.
C'est cette séparation qui compte. Le déploiement = mettre du code sur les serveurs. La release = laisser les utilisateurs le voir. Les flags scindent ces deux moments, donc fusionner sur main ne signifie plus « tout le monde l'a maintenant ».

Pourquoi les équipes utilisent-elles des feature flags ?
Trois raisons reviennent constamment dans les vraies équipes de 5 à 50 développeurs.
Fusionner du travail inachevé sans risque. Vous committez la moitié de la nouvelle fonction derrière un flag éteint, et votre branche n'existe jamais trois semaines. C'est ce qui rend le trunk-based development viable.
Déployer progressivement. Allumez une fonction pour les utilisateurs internes d'abord, ensuite 5 % du trafic, puis tout le monde. Si les erreurs explosent, vous l'éteignez en quelques secondes.
Arrêter quelque chose en urgence. Quand un prestataire de paiement déconne à 2 h du matin, un flag permet au support d'éteindre une seule fonction au lieu de rollback une release entière.
Aucune de ces trois raisons n'exige un vendor. Un flag peut être un booléen dans une table de config. Sautez la plateforme jusqu'à ce que vous ayez vraiment besoin de rollouts en pourcentage, d'audit trails, ou que des non-ingénieurs allument les flags.
Quels sont les quatre types de feature flags ?
L'article très cité de Pete Hodgson sur les feature toggles chez Martin Fowler classe les flags selon leur durée de vie et la fréquence des changements. Les catégories restent le modèle mental le plus clair.
Release : existe quelques jours à quelques semaines, allumé par des ingénieurs. Exemple : masquer une refonte de checkout inachevée.
Experiment : existe quelques semaines, allumé par le product et les data. Exemple : un A/B test de deux pages de prix.
Ops : existe quelques heures à jamais, allumé par l'on-call. Exemple : kill switch d'un service de recommendations lent.
Permission : existe des mois à des années, allumé par le product et le support. Exemple : accès beta ou fonctions premium-only.
La colonne « durée de vie » compte le plus. Un flag release qui outlive sa release est un bug qu'on n'a pas trouvé. Un flag permission qu'on supprime dans un sprint de cleanup est une panne qu'on n'a pas eue.
Nommez et catégorisez le type quand vous créez le flag. Six mois plus tard, personne ne se souvient de la catégorie « new-nav-v2 ».

Comment déployer un flag sans faire de dégâts ?
La séquence ennuyeuse marche le mieux.
Déployez le code avec le flag éteint. Vérifiez que rien n'a changé.
Allumez-le pour votre équipe en production. Utilisez-le une journée.
Allumez pour 1 % à 5 % des utilisateurs, sticky par user ID pour que personne ne bascule d'une version à l'autre pendant une session.
Regardez le taux d'erreur, la latence, et une métrique métier. Décidez le seuil avant de commencer, pas pendant qu'on regarde le dashboard.
Montez à 100 %, attendez une période définie, puis supprimez le flag.
L'étape 5 est celle que les équipes sautent. On y revient: ça coûte plus cher qu'on le pense.
Une note pratique : faites en sorte que les flag reads soient bon marché et robustes en cas d'erreur. Si le service de flags est down, votre code a besoin d'une valeur par défaut. Choisissez la default par flag, exprès. Un kill switch doit échouer à « off », tandis qu'une nouvelle fonction doit échouer à « off » aussi.
Pourquoi les feature flags deviennent-ils une dette technique ?
Chaque flag est une fourche dans votre code. Deux flags font 4 chemins possibles, dix flags en font 1024, et vous en avez probablement testé une poignée. Le guide engineering de GrowthBook sur la dette flags cite une recherche : environ 75 % des composants toggle restaient dans les repos jusqu'à 49 semaines après leur introduction, même si la plupart des devs disaient qu'ils avaient prévu de les enlever.
Hodgson le dit bien dans le même article Fowler : les bonnes équipes traitent les toggles comme un inventaire avec un coût de possession, et bossent pour garder cet inventaire bas.
L'histoire d'horreur classique : Knight Capital en 2012. Le flag d'une fonction retirée a été réutilisé pour un nouveau comportement tandis que l'ancien code attendait encore sur un serveur. Ce décalage a contribué à environ 460 millions de pertes en moins d'une heure. Votre vieux flag ne fera probablement pas ça. Il fera quelque chose de plus discret : une refactor qui casse une branche que personne ne savait exister, ou un nouveau dev qui passe un après-midi à deviner quel chemin checkout est vraiment utilisé.

Comment trouver tous les flags dans un repo existant ?
C'est la question que la doc des vendors saute, et c'est où la plupart des équipes se bloquent. Le dashboard du flag dit ce qui est configuré. Il ne dit pas où chaque flag est lu dans le code, ni si le chemin derrière un flag « off » est encore accessible.
Commencez par la méthode économe :
# chaque clé de flag lue via votre wrapper
rg -n 'isEnabled\("' src/ | sort
# flags définis mais jamais référencés
comm -23 <(jq -r 'keys[]' flags.json | sort) \
<(rg -o 'isEnabled\("([^"]+)"' -r '$1' src/ | sort -u)Ça part en fumée vite. Les clés de flags construites avec concatenation de strings ne remontent pas dans grep. Les flags passés via des fonctions helper cachent leurs call sites. Les monorepos et les multi-repo multiplient le problème, parce que la même clé peut être lue par trois services.
C'est là que lire le code avec des outils qui le comprennent aide. Les outils de recherche de code qui comprennent votre repo peuvent répondre « où new-checkout est-il évalué, et qu'est-ce qui dépend du résultat ? » en une requête au lieu d'un après-midi de grep. Cursor et GitHub Copilot gèrent ça raisonnablement dans un repo. Sur plusieurs repos, vous avez besoin d'un index qui les couvre tous: c'est pour ça qu'on a builté codebasechat.
C'est quoi un bon processus de cleanup des flags ?
Traitez la suppression comme faisant partie du travail, pas une corvée pour plus tard.
Créez le ticket de suppression avec le flag. Référez-le dans la description du flag. Si le ticket n'existe pas, le flag ne ship pas.
Assignez un propriétaire et une date d'expiration à chaque flag non-permanent. Environ 90 jours sans changement est un déclencheur raisonnable pour une révision.
Supprimez en deux pull requests. D'abord supprimez la condition et gardez le chemin gagnant. Ensuite supprimez la branche morte et ses tests. Des petites diffs se relisent mieux.
Ajoutez un test time bomb. Un test qui échoue quand un flag release dépasse sa date d'expiration transforme une bonne intention en un build rouge.
Mettez un cap. Si vous avez 40 flags actifs et le limite est 40, ajouter un flag signifie en supprimer un.
L'analyse statique aide ici aussi. Un outil comme CodeScene peut montrer quels fichiers portent la logique conditionnelle la plus compliquée, c'est généralement là que les vieux flags se concentrent. SonarQube flag le code unreachable et dead après que vous supprimiez une condition.
Comment tester du code derrière un flag ?
Les tests c'est la part qu'on ne budgète pas. Avec deux chemins par flag, votre suite de tests doit les couvrir tous, au moins pour les flags qui gardent du comportement risqué.
Gardez ça simple. Testez les états on et off de chaque flag release en unit tests, en injectant la valeur plutôt que de lire un service live. Lancez une suite end-to-end contre la config prod par défaut, parce que c'est ce que les users voient aujourd'hui. Puis lancez une deuxième passe avec le flag on pour la feature qu'on va bientôt release.
N'essayez pas de tester chaque combinaison. Avec dix flags vous ne pouvez pas. À la place, gardez les flags indépendants : un flag qui change de comportement seulement quand un autre flag est aussi on est un design smell, et c'est la première chose à untangle.
Que font de travers les nouveaux développeurs avec les flags ?
Les juniors font les mêmes trois erreurs, et chacune est facile à prévenir en review.
Emboîter les flags. Un flag dans un autre crée un chemin qui existe seulement quand les deux sont on. Demandez un seul flag avec un nom clair.
Mettre la logique dans le nom du flag. Une clé comme « show-new-nav-to-premium-users-in-eu » encode une règle de targeting qui doit vivre dans le service de flags, pas dans une string.
Oublier la valeur par défaut. Si la recherche du flag échoue, que se passe-t-il ? Faites que l'auteur écrive la réponse dans la description de la PR.
Les deux premières semaines d'un nouveau dev sont exactement quand ils tombent sur des vieux flags sans propriétaire. Un court registre de flags, avec un type, un propriétaire, et une date de suppression pour chaque entrée, économise plusieurs heures d'asking around.
Quand faut-il ignorer les feature flags ?
Les flags ne sont pas gratuits, alors ignorez-les quand :
La modification est mineure, réversible, et à un redéploiement d'une rollback. Un flag ajoute un chemin de code sans gain.
La modification touche un schéma de base de données d'une manière qu'un flag ne peut pas cacher. Utilisez plutôt des expand-and-contract migrations.
Votre équipe n'a pas de processus pour supprimer les flags. Arrangez ça d'abord, sinon vous vous endettez contre la lisibilité future.
Et utilisez-les sans hésiter quand une modification est risquée, user-facing, et difficile à réverser avec un redéploiement. Les flux de paiement, les changements d'auth, tout avec une migration de données derrière: ça rentre là.
Ce qu'on ferait vraiment sur une équipe de dix
Commencez avec un booléen dans la config et une seule fonction wrapper, pour que chaque flag read passe par un seul endroit. Ce choke point unique rend la liste des flags greppable, auditable, et facile de migrer vers un service hébergé plus tard.
Étiquez chaque flag par type, assignez-lui un propriétaire, et créez le ticket de suppression le jour 1. Relisez la liste une fois par mois pendant dix minutes. Supprimez les flags qui sont à 100 % depuis deux semaines.
Un feature flag est un prêt. Empruntez-le quand c'est un release risqué, et remboursez-le avant que l'intérêt ne vous fasse du refactor.