C'est quoi un feature flag ? Guide simple pour dev solo

Résumé

Un feature flag est une condition dans votre code dont la valeur se contrôle depuis l'extérieur, dans un fichier de configuration, une base ou un service. Vous activez ou coupez une fonctionnalité sans redéployer. Cela sépare le déploiement de la mise en production : vous fusionnez chaque jour du travail inachevé, déployez à 1 % des utilisateurs et coupez instantanément. Le piège : chaque flag ajoute un chemin de code et doit être supprimé après le déploiement.

Ordinateur portable avec éditeur de code à côté d'un petit panneau d'interrupteurs métalliques sur un bureau sombre

C'est quoi un feature flag ? C'est un if dont la réponse vit en dehors de votre code. Vous déployez la nouvelle branche désactivée, puis vous l'activez plus tard en changeant une valeur dans un fichier de configuration, une ligne de base de données ou un service de flags, sans redéployer. Ce mécanisme sépare le déploiement de la mise en production d'une fonctionnalité, et c'est pour cela que le flag est le rollback le moins cher que vous posséderez jamais.

J'ai appris la deuxième moitié de cette phrase à mes dépens. Mon premier flag était un booléen dans une variable d'environnement, activé un vendredi soir, et je l'ai oublié pendant onze mois. Rien n'a cassé. C'est précisément le problème, on y vient.

Ce qu'un feature flag ressemble vraiment dans le code

Bien plus petit que ce que suggèrent les pages d'accueil des outils. Une fois les tableaux de bord écartés, un flag se résume à une lecture et à un embranchement :

const flags = { newCheckout: false };

if (flags.newCheckout) {
  return renderNewCheckout(user);
}
return renderOldCheckout(user);

Le reste, c'est une question de provenance : d'où vient flags, et qui peut le modifier ? Une constante dans le fichier est un flag qu'il faut changer en déployant, ce qui annule l'intérêt. Une variable d'environnement ne se met à jour qu'au redémarrage. Une ligne en base change en quelques secondes. Un service hébergé change en quelques secondes également, et ajoute un ciblage par utilisateur, une interface et un journal d'audit.

Le piège concret n'est pas le code, qui est trivial, mais le cycle de vie. Deux branches en production, ce sont deux comportements à tester, deux chemins à déboguer à 2 h du matin, et l'un des deux est voué à pourrir.

Interrupteur industriel à bouton rouge sur un panneau de commande en acier, un kill switch

Quels sont les quatre types de feature flags, et lequel vous faut-il en premier ?

La taxonomie de Martin Fowler sur les feature toggles reste la façon la plus claire de les classer, et l'axe utile est la durée de vie attendue de chaque type.

Les flags de release masquent un travail inachevé ou risqué. Ils sont transitoires : une semaine ou deux, puis suppression. C'est celui dont vous avez besoin en premier.

Les flags ops sont des kill switches. Vous enveloppez une fonctionnalité lourde ou fragile (un widget de recommandations, un appel à un tiers) pour la couper sous charge sans déployer. La plupart sont courts, quelques-uns restent indéfiniment, et c'est très bien.

Les flags d'expérimentation répartissent les utilisateurs en cohortes pour des tests A/B. Ils vivent le temps d'atteindre un résultat statistiquement exploitable, donc de quelques heures à quelques semaines, et n'ont de sens qu'avec un vrai trafic.

Les flags de permission conditionnent une fonctionnalité au plan ou au compte : l'offre Pro, le groupe bêta. Ceux-là peuvent durer des années, et à ce stade ce ne sont plus vraiment des flags. Ce sont des droits d'accès, et ils méritent un vrai modèle de données.

Si vous êtes développeur solo avec 40 utilisateurs, il vous faut des flags de release et peut-être un kill switch. Des flags d'expérimentation sur 40 personnes produisent du bruit, pas des données. Attendez de pouvoir nommer la métrique et la taille de l'échantillon.

Quel problème les flags résolvent que les branches et les déploiements ne résolvent pas ?

Trois choses, et seulement trois méritent qu'on s'y intéresse.

Livrer du travail inachevé sans risque. Les branches longue durée font mal, parce que les fusionner est une petite guerre. Un flag vous permet de fusionner sur main chaque jour avec le nouveau code désactivé. C'est le moteur du trunk-based development, où tout le monde committe sur une seule branche et où les flags portent les parties inachevées.

Le déploiement progressif. Vous activez la fonctionnalité pour vous, puis pour 1 % des utilisateurs, puis 10 %, puis tout le monde. Fowler décrit une cohorte canari d'environ 1 % obtenue en prenant l'identifiant utilisateur modulo 100. Si quelque chose cloche, le rayon d'impact se limite à une poignée de personnes au lieu de toute votre base.

Le retour arrière rapide. Revenir en arrière sur un déploiement, c'est un build, un pipeline et un peu de sang-froid. Basculer un flag, c'est une seule modification. Une mauvaise journée, la différence se mesure en minutes contre une heure.

Rien de tout cela n'exige un prestataire dès le premier jour. Tout cela exige de la discipline.

Faut-il LaunchDarkly, ou un fichier JSON suffit-il ?

Un fichier JSON ou une table en base suffit, jusqu'à ce que l'une de ces conditions soit vraie : une personne non développeuse doit pouvoir basculer les flags, vous avez besoin de déploiements en pourcentage ou de ciblage par utilisateur, vous voulez savoir qui a changé quoi, ou plusieurs services lisent les mêmes flags.

Voici l'échelle que je grimperais, dans l'ordre :

  1. Constantes et variables d'environnement. Coût nul. Suffisant pour le premier flag de release d'un projet perso.

  2. Une table flags ou un fichier JSON lu à l'exécution. Dix lignes de code, bascules instantanées, pas de prestataire. Cela porte un projet solo étonnamment loin.

  3. Un service de flags open source ou hébergé. Quand vous voulez des règles de ciblage, des déploiements progressifs et une interface que quelqu'un d'autre peut utiliser.

  4. Une plateforme entreprise. Quand la conformité, les validations et des dizaines d'ingénieurs entrent dans l'équation.

Les outils hébergés couvrent les étapes 3 et 4. LaunchDarkly est la référence historique, avec les fonctions de ciblage et de gouvernance les plus poussées, et un prix qui le reflète.

Statsig regroupe les flags avec l'expérimentation et l'analyse produit. C'est pertinent si vous comptez mesurer ce que le flag a fait, et pas seulement le basculer.

Passez les deux si votre équipe, c'est vous. Un tableau à trois colonnes vaut mieux qu'un tableau de bord que vous ouvrez deux fois par trimestre. Ne prenez un service que lorsque la version manuelle vous a coûté quelque chose de précis, comme une modification nocturne de la configuration de production que vous avez regrettée.

Une assurance à connaître : OpenFeature est un projet incubé à la CNCF qui définit une API neutre pour évaluer les flags, avec des SDK pour Node.js, Python, Go, Java, .NET et les clients web, entre autres. Vous codez contre l'interface standard et vous changez de fournisseur en dessous. Si vous pensez que votre première installation va devenir trop petite, passer par OpenFeature transforme cette migration en simple changement de configuration.

Carnet avec des cases dessinées à la main et des flèches sur un bureau de développeur, la nuit

Comment ajouter votre premier flag sans faire un désordre ?

Commencez par un seul flag de release et quelques règles de base. C'est la version que j'aurais aimé suivre.

Nommez-le d'après la fonctionnalité, pas d'après le mécanisme. nouveau-tunnel-paiement vous dit ce qui casse si ça dérape. flag_47 ne vous dit rien dans six mois.

Par défaut, il est désactivé, et désactivé veut dire ancien comportement. La convention « désactivé égale legacy, activé égale nouveau » est ce qui vous permet de raisonner sur le système sous pression. Si vous la cassez, chaque flag devient une énigme.

Évaluez-le à un seul endroit. Fowler appelle le remède l'inversion de toggle : au lieu de semer des if (flags.x) dans vingt fichiers, vous décidez une fois, près de la périphérie du système, et vous passez le résultat à l'intérieur. Un seul point de décision, c'est un seul endroit à modifier et un seul endroit à tester.

Écrivez le ticket de suppression au moment où vous créez le flag. Mettez-le dans le backlog avec une date. Fowler suggère aussi des dates d'expiration pour les toggles courts, et même des tests qui échouent une fois la date dépassée. Un flag sans ticket de suppression, c'est un emprunt sans échéancier de remboursement.

Journalisez chaque évaluation qui compte. Quand un utilisateur signale un bug, vous voulez savoir de quel côté du flag il se trouvait. Si vous ne pouvez pas répondre à cette question, le flag est un passif.

C'est sur les tests qu'on sur-ingénie le plus. Inutile de tester chaque combinaison de flags, parce que la plupart n'interagissent pas entre eux. Testez la configuration attendue en production, testez le repli avec le nouveau flag désactivé, et lancez éventuellement une passe avec tout activé pour détecter les dérives.

Quel est le coût réel des feature flags dont personne ne parle ?

Chaque flag double un chemin de code. Dix flags indépendants donnent, en théorie, 1 024 combinaisons. Vous ne les testerez jamais toutes, mais l'une d'elles peut quand même apparaître en production sans que personne l'ait anticipée.

Le coût le plus douloureux, ce sont les flags morts. Le déploiement se termine, tout le monde a le nouveau comportement, le flag reste à 100 %, et l'ancienne branche dort dans le dépôt comme du code que personne n'ose supprimer. Six mois plus tard, plus personne ne sait si la désactiver est sans risque.

La version célèbre de ce problème, c'est Knight Capital en août 2012. Un ancien flag, qui avait autrefois activé une fonction de trading retirée, a été réutilisé pour du nouveau code. Un serveur sur huit a manqué le déploiement et a continué à exécuter l'ancien code. En 45 minutes, la société a perdu environ 440 millions de $ selon son propre rapport trimestriel, un chiffre que des articles ultérieurs situent plutôt autour de 460 millions de $. C'est une entreprise de trading avec de vrais capitaux et de vrais ingénieurs, donc je ne vais pas prétendre que votre projet perso est plus sûr. La leçon se transpose très bien : ne réutilisez jamais un nom de flag, et supprimez les flags morts avant qu'ils ne deviennent de l'archéologie.

Rangée de clés en laiton accrochées à des crochets, certaines rouillées et d'autres brillantes, comme d'anciens flags oubliés dans le code

La formulation de Fowler est celle que je garde en tête : traitez les flags comme un inventaire qui a un coût de possession. Certaines équipes plafonnent le nombre de flags actifs et imposent d'en supprimer un avant d'en ajouter un autre. Pour un développeur solo, un plafond de cinq suffit largement.

Quand faut-il carrément s'en passer ?

Plus souvent que ce que les éditeurs d'outils admettent.

Passez sans flag quand la fonctionnalité est petite, que le changement se révoque facilement avec git et que votre déploiement prend deux minutes. Un flag ajoute une branche, une source de configuration et une chose à oublier. Si un revert est plus rapide qu'une bascule de flag, le flag n'est que du théâtre.

Passez aussi sans flag quand vous n'avez pas encore d'utilisateurs. Un déploiement progressif vers zéro personne ne sert à rien, c'est juste un délai. Livrez, regardez les logs, corrigez.

Passez sans flag pour les migrations de base de données qu'un toggle ne peut pas annuler. Un flag peut masquer une nouvelle colonne dans l'interface, mais il ne peut pas restaurer une table supprimée. Les changements de schéma demandent leur propre plan d'expansion puis de contraction, avec flags ou sans.

Un flag vaut le coup quand le changement touche aux paiements ou à l'authentification, quand vous voulez fusionner chaque jour du travail inachevé, ou quand une dépendance tierce peut tomber et que vous voulez un kill switch.

Que surveiller une fois le flag en production ?

Un flag contrôle l'exposition, et l'exposition n'aide que si vous voyez ce qui se passe ensuite. Activer une fonctionnalité pour 10 % des utilisateurs sans surveiller le taux d'erreur ni la latence, c'est jouer à pile ou face avec des étapes en plus.

Avant le premier déploiement progressif, vérifiez que vous pouvez répondre en moins d'une minute à trois questions : les erreurs ont-elles augmenté dans la cohorte concernée, la latence s'est-elle dégradée, et quelque chose a-t-il changé en aval ? Le monitoring de disponibilité et la recherche dans les logs couvrent l'essentiel pour un petit produit. Un outil comme Better Stack regroupe monitors, pages de statut et logs, avec un palier gratuit.

La règle que je suis désormais : un flag ne vaut que par l'alerte qui lui est attachée. Sans alerte, vous activez des choses dans le noir.

Et concrètement, cette semaine ? Choisissez un chantier inachevé que vous n'osez pas fusionner. Mettez-le derrière un booléen lu depuis une table ou un fichier JSON, désactivé par défaut, et fusionnez-le sur main aujourd'hui. Écrivez le ticket de suppression avant de fermer votre éditeur, avec une date dans deux semaines.

Ensuite, activez-le seulement pour vous et utilisez-le pendant une journée. S'il tient, élargissez-le. Sinon, désactivez-le : vous n'aurez perdu qu'une minute.

Quel flag de votre code est à 100 % depuis plus d'un mois ? Ce sera votre première suppression.

Questions fréquentes

Qu'est-ce qu'un feature flag, en termes simples ?
Un feature flag est une condition dans votre code dont la valeur est stockée hors du code, dans un fichier de configuration, une base de données ou un service de flags. Vous pouvez la modifier à l'exécution, donc une fonctionnalité peut être livrée désactivée puis activée plus tard, sans nouveau déploiement.
Feature flag et feature toggle, est-ce la même chose ?
Oui. Feature flag, feature toggle, feature switch et release toggle désignent la même technique. Les équipes choisissent un terme par habitude, et les outils les utilisent indifféremment.
Quels sont les principaux types de feature flags ?
Quatre types sont courants : les flags de release pour masquer un travail inachevé, les flags ops (kill switches) pour couper une fonctionnalité risquée, les flags d'expérimentation pour les tests A/B, et les flags de permission pour conditionner une fonctionnalité au plan ou au compte.
Faut-il un outil payant de feature flags pour un projet perso ?
En général non. Une constante, une variable d'environnement, un fichier JSON ou une table en base suffisent pour un projet solo. Passez à un service hébergé quand des non-développeurs doivent basculer les flags, ou quand vous avez besoin de déploiements en pourcentage, de ciblage et d'un journal d'audit.
Combien de temps un feature flag doit-il vivre ?
Un flag de release doit vivre une ou deux semaines, puis être supprimé avec l'ancien chemin de code. Les kill switches ops peuvent rester plus longtemps. Les flags de permission peuvent durer des années, mais ce sont en réalité des droits d'accès qui méritent un vrai modèle de données.
Quel est le principal risque des feature flags ?
Les flags obsolètes. Chaque flag ajoute un chemin de code à tester, et un flag resté à 100 % laisse du code mort que personne n'ose retirer. La perte de Knight Capital en 2012, d'environ 440 millions de $, a impliqué un ancien flag réutilisé. Rédigez le ticket de suppression au moment où vous créez le flag.