Concept #002
DevOps & ProduitLes Feature Flags
- produit
- devops
- architecture
Deploy is not Release
Dans la Silicon Valley, cette phrase est devenue un mantra : Deploy is not Release. Elle résume une idée simple mais puissante que beaucoup de développeurs confondent encore.
Déployer, c'est envoyer du code en production. Le code est sur le serveur.
Releaser, c'est rendre une fonctionnalité accessible aux utilisateurs. Ils peuvent l'utiliser.
Ces deux actions sont souvent collées ensemble par défaut. On pousse du code, les utilisateurs le voient immédiatement. Mais rien ne vous y oblige. Les Feature Flags — aussi appelés Feature Toggles ou Feature Switches — sont précisément le mécanisme qui vous permet de dissocier ces deux étapes.
Un Feature Flag, c'est une condition dans votre code qui décide si une fonctionnalité est visible ou non, pour qui, et à quel moment. Le code est déployé. Le flag décide si vous l'activez.
Les cas d'usage concrets
A/B Testing
Vous hésitez entre deux designs pour votre bouton de conversion ? Activez la version bleue pour 50 % de vos utilisateurs, la rouge pour les autres. Mesurez. Gardez ce qui fonctionne. Pas besoin de deux environnements distincts, pas besoin de rejouer un déploiement : le flag fait le travail.
Canary Release
Avant d'exposer toute votre base utilisateurs à une nouvelle fonctionnalité critique, ouvrez la vanne progressivement. 1 % d'abord. Puis 10 %. Vous surveillez les métriques, les erreurs, le comportement. Si quelque chose cloche, vous coupez le flag. Zéro rollback, zéro stress.
Targeting
Vous voulez que seuls vos Beta Testers voient le nouveau Dashboard avant le grand public ? Un flag ciblé sur le groupe beta-testers suffit. Votre équipe interne peut tester en production réelle, pendant que vos utilisateurs lambda continuent sur l'ancienne version.
L'implémentation en React / TypeScript
Grâce à un simple hook, votre composant s'adapte dynamiquement. Le code du nouveau design et de l'ancien cohabitent dans la même base de code. C'est le flag qui décide quoi afficher au moment du rendu.
// hooks/useFeatureFlag.ts
type FlagName = "new-dashboard" | "blue-button" | "checkout-v2";
interface FeatureFlagConfig {
enabled: boolean;
rolloutPercentage?: number; // 0-100
targetGroups?: string[];
}
const FLAGS: Record<FlagName, FeatureFlagConfig> = {
"new-dashboard": {
enabled: true,
targetGroups: ["beta-testers", "internal"],
},
"blue-button": {
enabled: true,
rolloutPercentage: 50,
},
"checkout-v2": {
enabled: false,
},
};
function isInRollout(percentage: number, userId: string): boolean {
// Hash stable basé sur l'userId pour une expérience cohérente
const hash = userId.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0);
return hash % 100 < percentage;
}
export function useFeatureFlag(flagName: FlagName, user: { id: string; groups: string[] }) {
const config = FLAGS[flagName];
if (!config.enabled) return false;
if (config.targetGroups) {
return config.targetGroups.some((group) => user.groups.includes(group));
}
if (config.rolloutPercentage !== undefined) {
return isInRollout(config.rolloutPercentage, user.id);
}
return true;
}// components/Dashboard.tsx
import { useFeatureFlag } from "@/hooks/useFeatureFlag";
import { useCurrentUser } from "@/hooks/useCurrentUser";
export function Dashboard() {
const user = useCurrentUser();
const hasNewDashboard = useFeatureFlag("new-dashboard", user);
return (
<main>
{hasNewDashboard ? (
<NewDashboardLayout userId={user.id} />
) : (
<LegacyDashboardLayout userId={user.id} />
)}
</main>
);
}Pas besoin de branches git complexes qui divergent pendant des semaines. Tout cohabite sur main. Le flag tranche.
Les avantages produit
Au-delà de la technique, les Feature Flags changent profondément la relation entre le développement et le produit.
Moins de stress au déploiement. Vous pouvez déployer à n'importe quelle heure, n'importe quel jour. La feature n'est pas active. Aucun risque pour l'utilisateur.
Un kill switch instantané. Si un bug critique apparaît sur la nouvelle fonctionnalité, vous coupez le flag. Pas de rollback, pas d'urgence à 3h du matin pour reverter un commit. En quelques secondes, vous revenez à l'état stable.
Des données réelles pour décider. Plutôt que de débattre en réunion de ce que préfèrent vos utilisateurs, vous mesurez. L'A/B test vous donne une réponse empirique, pas une intuition.
Le code reste propre. Toute l'équipe travaille sur une seule branche. Pas de merge hell après deux mois de développement en parallèle sur des branches qui ont trop divergé.
Quand ne pas les utiliser
Les Feature Flags ne sont pas une solution universelle. Quelques garde-fous s'imposent.
Nettoyez vos flags morts. Un flag qui reste dans le code après que la feature est définitivement activée pour tous, c'est de la dette technique. Créez un ticket de nettoyage dès que vous créez un flag. Les bases de code remplies de vieux flags deviennent rapidement illisibles.
Ne les utilisez pas pour du code permanent. Si une fonctionnalité doit toujours être présente, inutile de la mettre derrière un flag. Réservez les flags aux phases de transition, de test, ou de rollout progressif.
Attention à la complexité combinatoire. Trop de flags qui interagissent entre eux créent des états impossibles à tester exhaustivement. Gardez vos flags indépendants et en petit nombre simultanément.
La configuration doit être centralisée. Des flags éparpillés dans le code sans source de vérité unique, c'est le chaos. Utilisez un service dédié (LaunchDarkly, Unleash, Flagsmith) ou a minima un fichier de configuration clair et versionné.
En résumé
Les Feature Flags, c'est l'outil qui vous fait passer du statut de développeur qui subit les décisions produit à celui qui les maîtrise. Vous déployez sereinement. Vous testez en conditions réelles. Vous rolloutez progressivement. Et si ça foire, vous coupez le robinet.
Deploy is not Release. Internalisez cette distinction, et votre rapport au déploiement ne sera plus jamais le même.