<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luccin Masirika</title>
    <description>The latest articles on DEV Community by Luccin Masirika (@luccinmasirika).</description>
    <link>https://dev.to/luccinmasirika</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F403685%2F5bda6507-bbbe-49e5-b89f-3b02b41b5603.png</url>
      <title>DEV Community: Luccin Masirika</title>
      <link>https://dev.to/luccinmasirika</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luccinmasirika"/>
    <language>en</language>
    <item>
      <title>Déployer n'est pas livrer</title>
      <dc:creator>Luccin Masirika</dc:creator>
      <pubDate>Thu, 27 Aug 2026 06:00:00 +0000</pubDate>
      <link>https://dev.to/luccinmasirika/deployer-nest-pas-livrer-1db2</link>
      <guid>https://dev.to/luccinmasirika/deployer-nest-pas-livrer-1db2</guid>
      <description>&lt;p&gt;&lt;em&gt;Pourquoi vos branches d'environnement vous ralentissent, comment les équipes les plus rapides du monde s'en sont débarrassées, et ce que ça change concrètement dans votre code. L'article progresse en trois parties, de plus en plus profondes : les experts sont servis à la fin.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Il est 18 h 47, un jeudi
&lt;/h2&gt;

&lt;p&gt;La feature est prête depuis neuf jours. Testée, validée, approuvée. Mais elle ne partira pas en production ce soir, ni demain : elle est coincée sur la branche &lt;code&gt;staging&lt;/code&gt;, mélangée à deux autres features qui, elles, ne sont pas prêtes. Impossible de livrer l'une sans embarquer les autres. Alors on attend. Ou pire : on tente un cherry-pick chirurgical vers &lt;code&gt;master&lt;/code&gt;, en croisant les doigts pour que les commits ne se marchent pas dessus.&lt;/p&gt;

&lt;p&gt;Si cette scène vous parle, votre équipe utilise des branches d'environnement : une branche &lt;code&gt;dev&lt;/code&gt; ou &lt;code&gt;staging&lt;/code&gt; qui accumule les features en test, une branche &lt;code&gt;master&lt;/code&gt; qui représente la production, et des merges rituels entre les deux. C'est le modèle le plus répandu du monde. C'est aussi celui que Google, Meta, Netflix et toutes les équipes mesurées comme les plus performantes ont abandonné il y a quinze ans.&lt;/p&gt;

&lt;p&gt;Le problème n'est pas votre équipe. Le problème est qu'une branche Git est un très mauvais outil pour répondre à la question « qu'est-ce qui est activé, pour qui, en ce moment ? »&lt;/p&gt;

&lt;h3&gt;
  
  
  L'anatomie du mal
&lt;/h3&gt;

&lt;p&gt;Le modèle à branches d'environnement repose sur une équivalence séduisante, &lt;em&gt;une branche = un environnement = un état du produit&lt;/em&gt;, qui se dégrade pour trois raisons mécaniques.&lt;/p&gt;

&lt;p&gt;D'abord, la branche d'intégration dérive. Chaque feature mergée dans &lt;code&gt;staging&lt;/code&gt; mais pas encore en prod creuse l'écart avec &lt;code&gt;master&lt;/code&gt; : features abandonnées, correctifs en double, conflits résolus différemment de chaque côté. Ce qu'on teste n'est plus ce qu'on livrera.&lt;/p&gt;

&lt;p&gt;Ensuite, livrer devient un problème de soustraction. Sortir la feature A sans la B exige de l'extraire de la masse : cherry-picks, merges sélectifs, et un code en prod qui n'est jamais exactement celui qui a été validé.&lt;/p&gt;

&lt;p&gt;Enfin, déployer et livrer sont le même geste. Activer une feature exige de pousser du code ; la désactiver aussi. Chaque mise en prod devient un événement qu'on espace, donc qui grossit, donc qui fait peur, donc qu'on espace encore. Le cercle est vicieux et bien documenté.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ce que disent les chiffres
&lt;/h3&gt;

&lt;p&gt;Le programme de recherche &lt;a href="https://dora.dev" rel="noopener noreferrer"&gt;DORA&lt;/a&gt; (Google Cloud) mesure depuis 2014 la performance de milliers d'équipes, et son résultat le plus contre-intuitif est solide : les équipes qui déploient le plus souvent sont aussi celles qui ont le moins d'incidents. La sécurité ne vient pas de la prudence des gros déploiements espacés ; elle vient de la petitesse de chaque changement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les solutions, dans l'ordre où on les découvre
&lt;/h2&gt;

&lt;p&gt;Il n'y a pas un modèle à adopter d'un bloc, et c'est le point que la plupart des articles ratent. Le chemin passe par des solutions intermédiaires, et chacune est un état stable où une équipe peut s'installer durablement. Ce qui pousse à la suivante n'est pas la mode ; c'est un échec précis, qu'on va raconter à chaque fois.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Branches d'environnement       dev, staging, master, et des merges rituels
     │  la branche d'intégration dérive, livrer devient une soustraction
     ▼
Une branche + des tags         branches courtes, validation avant merge
     │  la validation bloque le merge, les features font la queue
     ▼
Artefact unique + review apps  un build par commit, une scène par feature
     │  déployer reste le seul interrupteur, tout ou rien
     ▼
Trunk + feature flags          on merge tôt, éteint ; livrer = allumer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Une seule branche de vérité
&lt;/h3&gt;

&lt;p&gt;La première réponse à la dérive des branches d'environnement ne demande aucun outillage nouveau, seulement trois règles. La branche principale est protégée : push direct interdit, merge request obligatoire, pipeline vert requis. Les branches de feature sont courtes : quelques jours au plus, une feature = une branche = une MR. Et les environnements se déploient depuis des tags, jamais depuis des branches dédiées : staging redevient un &lt;em&gt;endroit&lt;/em&gt; où l'on déploie un commit précis de &lt;code&gt;main&lt;/code&gt;, pas une branche qui accumule.&lt;/p&gt;

&lt;p&gt;La règle de livraison est alors simple : on ne merge que ce qu'on est prêt à livrer. La validation se fait avant le merge, sur la branche de feature. C'est le « GitHub Flow » classique, et il résout déjà le cœur du problème : plus de dérive, ce qu'on teste est ce qu'on livre.&lt;/p&gt;

&lt;p&gt;Vous pouvez vous arrêter ici si vous livrez une feature à la fois et que la validation est rapide. Beaucoup de petites équipes vivent très bien avec ce modèle, et n'ont besoin de rien de plus.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trois mois plus tard, mardi, 9 h 05.&lt;/strong&gt; Le tableau des merge requests affiche quatre features « en attente de validation ». La QA n'a pas fini la première. La quatrième a déjà deux conflits avec la branche principale ; son auteur passera la matinée à rebaser du code validé la semaine dernière. En rétrospective, quelqu'un propose : « et si on avait une branche commune où on merge tout ce qui est à tester ? » Silence gêné. C'est la branche &lt;code&gt;staging&lt;/code&gt; qui frappe à la porte, sous un faux nom.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;L'échec est instructif : le problème n'est pas de savoir &lt;em&gt;où&lt;/em&gt; poser le code à tester, c'est que la validation &lt;em&gt;bloque le merge&lt;/em&gt;. Tant qu'une seule scène de test existe, les features font la queue devant, ou s'y mélangent. La réponse n'est pas une branche commune ; c'est de donner à chaque feature sa propre scène.&lt;/p&gt;

&lt;h3&gt;
  
  
  Le même artefact, des scènes jetables
&lt;/h3&gt;

&lt;p&gt;Deux mécanismes s'ajoutent, toujours sans toucher au code applicatif. Le premier : build once, promote everywhere. Un artefact unique par commit de &lt;code&gt;main&lt;/code&gt; ; dev, staging et prod reçoivent ce même binaire, promu par tag, jamais reconstruit. Ce qui a été validé est, bit à bit, ce qui part en prod. Le second : des environnements éphémères par MR, les « review apps ». Chaque branche de feature est déployée sur une URL jetable, détruite au merge. La QA valide chaque feature isolément, avant le merge, sans qu'une branche d'intégration mélange tout.&lt;/p&gt;

&lt;p&gt;Concrètement, en GitLab CI (l'équivalent existe chez GitHub Actions et les autres), l'essentiel tient en trois jobs :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Un seul build, adressé par commit : c'est lui qui voyagera partout&lt;/span&gt;
&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Une review app par merge request, détruite à sa fermeture&lt;/span&gt;
&lt;span class="na"&gt;review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy --image "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;review/$CI_COMMIT_REF_SLUG&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://$CI_COMMIT_REF_SLUG.review.example.com&lt;/span&gt;
    &lt;span class="na"&gt;on_stop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stop_review&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_MERGE_REQUEST_IID&lt;/span&gt;

&lt;span class="c1"&gt;# 3. La prod reçoit l'image déjà validée : un retag, jamais un rebuild&lt;/span&gt;
&lt;span class="na"&gt;promote_prod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;crane tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" prod&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_COMMIT_TAG =~ /^prod-/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C'est la réponse « sans flags » au besoin qui pousse les équipes vers les branches d'environnement : tester plusieurs features en parallèle. Chacune a son environnement, aucune ne bloque les autres.&lt;/p&gt;

&lt;p&gt;Vous pouvez vous arrêter ici si déployer et livrer peuvent rester le même geste chez vous : pas besoin d'activer une feature client par client, ni de l'éteindre en urgence sans redéployer. C'est le régime de croisière de très nombreuses équipes produit, et il est déjà excellent.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Six mois plus tard, vendredi, 16 h 40.&lt;/strong&gt; La release de mardi contenait quatre features, validées une à une sur leurs environnements éphémères, irréprochables. Mais l'une d'elles touche au même cache que le module de facturation, et sous le trafic réel du vendredi, ça casse. Le seul levier disponible est brutal : redéployer l'image précédente, en emportant les trois features innocentes. Pendant l'incident, un commercial passe une tête : « on peut activer la nouveauté seulement pour le client pilote qui l'a demandée ? » Non. On ne peut pas. Le déploiement est le seul interrupteur de la maison, et il éteint tout en même temps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Deuxième échec instructif : la validation isolée ne prouve pas le comportement en conditions réelles, et le déploiement est un interrupteur trop gros, qui allume et éteint tout d'un bloc. Il manque un levier plus fin que le déploiement. C'est exactement ce qu'est un feature flag.&lt;/p&gt;

&lt;h3&gt;
  
  
  L'interrupteur : découpler livrer de déployer
&lt;/h3&gt;

&lt;p&gt;La dernière marche renverse la logique : on merge &lt;em&gt;avant&lt;/em&gt; que la feature soit finie, masquée par un interrupteur, et c'est l'interrupteur qui livre. Déployer et livrer deviennent deux gestes distincts. Déployer, c'est pousser du code en production, éteint ; c'est le geste technique, fréquent, automatisé, sans enjeu produit, qui peut arriver dix fois par jour. Livrer, c'est allumer : le geste produit, une feature, un client, un instant choisi, réversible en secondes, sans redéploiement.&lt;/p&gt;

&lt;p&gt;Au fond, un flag est trivial : une condition qui lit une configuration au moment de l'exécution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new_checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;renderNewCheckout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;renderLegacyCheckout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Toute la valeur tient dans une question : d'où vient la valeur du flag ? Trois réponses, du plus simple au plus puissant, chacune légitime à son échelle :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Niveau&lt;/th&gt;
&lt;th&gt;Source des valeurs&lt;/th&gt;
&lt;th&gt;Un « flip » c'est…&lt;/th&gt;
&lt;th&gt;Granularité&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Config runtime&lt;/td&gt;
&lt;td&gt;Un fichier de config chargé au démarrage&lt;/td&gt;
&lt;td&gt;Changer une variable du déploiement, redémarrer le pod&lt;/td&gt;
&lt;td&gt;Par environnement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Backend&lt;/td&gt;
&lt;td&gt;Un objet &lt;code&gt;feature_flags&lt;/code&gt; servi par votre API&lt;/td&gt;
&lt;td&gt;Un appel d'API ou un champ en base&lt;/td&gt;
&lt;td&gt;Par client, par compte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Service dédié&lt;/td&gt;
&lt;td&gt;Unleash, LaunchDarkly, Flagsmith…&lt;/td&gt;
&lt;td&gt;Un clic dans une UI, effectif en secondes&lt;/td&gt;
&lt;td&gt;Par utilisateur, par pourcentage, par règle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Un piège spécifique au frontend mérite d'être nommé : dans une SPA, &lt;code&gt;process.env.MA_VARIABLE&lt;/code&gt; n'est pas une variable d'environnement. Elle est substituée au moment du build et cuite dans le bundle. Un flag lu ainsi exige un build par environnement, ce qui casse « même artefact partout ». La solution standard : un fichier &lt;code&gt;config.js&lt;/code&gt; non bundlé, généré au démarrage du conteneur et chargé par &lt;code&gt;index.html&lt;/code&gt; avant l'application. Le bundle reste identique partout ; seule cette config diffère.&lt;/p&gt;

&lt;p&gt;Reste le cycle de vie. Un flag de release n'est pas une décoration permanente : c'est un échafaudage, avec une date de démontage prévue dès sa pose. Il naît éteint partout, le jour où la feature démarre, ce qui permet de merger le premier commit dans le trunk le jour même. Il s'allume en dev, où toutes les features en cours cohabitent. Puis en staging, seul : on isole ce qu'on évalue. Puis en prod, progressivement si l'enjeu le mérite : équipe interne, client pilote, pourcentage, tout le monde. Et quelques semaines après la généralisation, le flag et l'ancien chemin de code sont supprimés. Cette dernière étape n'est pas optionnelle ; on y revient dans la partie qui suit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Le chemin est le plan de migration
&lt;/h3&gt;

&lt;p&gt;Le plan de transition est déjà écrit : c'est le chemin qu'on vient de parcourir, dans le même ordre, en ne décommissionnant l'ancien mécanisme que quand plus rien ne le lit ; une branche morte gardée « au cas où » redeviendra un entrepôt. Pour une équipe de 5 à 20 personnes, comptez un à deux trimestres. L'étape difficile n'est jamais technique : c'est le raccourcissement des branches, qui oblige à découper le travail autrement.&lt;/p&gt;

&lt;p&gt;Deux disciplines font tenir le système. Merger petit et souvent : le trunk ne fonctionne que si l'intégration est quotidienne, et une grosse MR est un problème à découper, pas à relire plus fort. Et tout nouveau développement naît derrière un flag : le flag remplace la branche comme unité de livraison ; si une feature n'a pas de flag, elle doit être livrable le jour de son merge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les objections que vous allez entendre
&lt;/h3&gt;

&lt;p&gt;Cette migration se gagne en réunion d'équipe avant de se gagner dans Git. Trois phrases reviennent dans toutes les équipes ; autant arriver avec les réponses.&lt;/p&gt;

&lt;p&gt;« On va merger du code pas fini dans master ?! » On merge du code fini au sens du pipeline : compilé, testé, revu. Ce qui n'est pas fini, c'est la feature, et elle est éteinte. Le vrai danger est ailleurs : une branche de trois semaines, c'est du code que personne n'exécute contre le reste du système ; le code éteint en production, lui, est intégré et compilé avec tout le monde, chaque jour.&lt;/p&gt;

&lt;p&gt;« La QA doit valider avant la prod. » Elle valide toujours, et mieux qu'avant : l'objet change. Au lieu de valider une release, un paquet de features enchevêtrées, elle valide une feature, seule, sur sa review app ou derrière son flag en staging. Le contrôle ne disparaît pas ; il se déplace du paquet vers l'unité.&lt;/p&gt;

&lt;p&gt;« Des &lt;code&gt;if&lt;/code&gt; partout dans le code, c'est sale. » Un flag de release bien posé, c'est &lt;em&gt;un&lt;/em&gt; point de divergence, à la frontière du module, avec une date de mort. Une branche longue est aussi un &lt;code&gt;if&lt;/code&gt; : simplement il est invisible, il n'est jamais exécuté en continu, et il se paie d'un coup au merge final. La dette de flags se gère, on y vient ; la dette de merge se subit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ce qui se passe à grande échelle
&lt;/h2&gt;

&lt;p&gt;Tout ce qui précède fonctionne tel quel pour une équipe. Voici ce qui casse quand on grossit, et les mécanismes que les grandes organisations ont construits en réponse.&lt;/p&gt;

&lt;h3&gt;
  
  
  La dette de flags est une dette exponentielle
&lt;/h3&gt;

&lt;p&gt;Chaque flag vivant double le nombre de chemins d'exécution possibles : dix flags actifs, c'est en théorie 1024 combinaisons d'états, dont votre suite de tests n'en couvre qu'une poignée. Les incidents de flags sont un genre à part entière ; le plus célèbre reste Knight Capital en 2012, où du code mort réactivé par un flag recyclé a coûté 460 millions de dollars en 45 minutes.&lt;/p&gt;

&lt;p&gt;Les défenses standard : une date d'expiration par flag, posée à la création, avec un rapport automatique des flags périmés (certaines équipes font échouer le build) ; un registre central avec nom, owner, ticket et type (la taxonomie de &lt;a href="https://martinfowler.com/articles/feature-toggles.html" rel="noopener noreferrer"&gt;Hodgson&lt;/a&gt; fait référence), car un flag sans owner est un flag mort qu'on n'ose pas supprimer ; ne jamais recycler un nom de flag, jamais ; et tester les deux états des flags proches de la prod, plus l'état par défaut de tous les autres. On ne teste pas les 1024 combinaisons, on teste les frontières qui bougent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rollout progressif : le bucketing, pas la loterie
&lt;/h3&gt;

&lt;p&gt;« Allumer pour 10 % des utilisateurs » ne peut pas être un &lt;code&gt;Math.random()&lt;/code&gt; par requête : un même utilisateur verrait la feature apparaître et disparaître entre deux pages. Les SDK de flags font du bucketing déterministe : &lt;code&gt;hash(user_id + flag_name) % 100&lt;/code&gt;, comparé au pourcentage cible. Le résultat est stable par utilisateur, indépendant entre flags grâce au nom dans le hash, et passer de 10 à 30 % conserve les 10 % déjà exposés. C'est aussi la brique de base de l'A/B testing : le flag renvoie une variante au lieu d'un booléen, et l'analyse compare les cohortes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Le schéma de base de données ne connaît pas les flags
&lt;/h3&gt;

&lt;p&gt;Le code a deux chemins (flag on, flag off), mais les deux parlent à la même base. Une migration destructive, renommer une colonne, changer un type, casse le chemin éteint. La réponse standard est le pattern expand-contract : on ajoute la nouvelle colonne sans toucher à l'ancienne, le code écrit dans les deux et lit l'ancienne (expand) ; on bascule la lecture derrière le flag et on backfille l'historique (migrate) ; et quand le flag est généralisé puis supprimé, on supprime l'ancienne colonne dans une release ultérieure (contract). Corollaire : chaque version du schéma doit supporter la version courante et la précédente du code, exigence de toute façon imposée par les déploiements progressifs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Garder le trunk vert quand cinquante personnes mergent
&lt;/h3&gt;

&lt;p&gt;À petite échelle, « pipeline vert avant merge » suffit. À grande échelle, deux MR vertes individuellement peuvent casser le trunk une fois combinées : le merge skew. D'où les merge queues (GitHub Merge Queue, GitLab Merge Trains) : chaque MR candidate est testée contre le résultat des merges qui la précèdent dans la file. Avec la sélection de tests par analyse d'impact, c'est ce qui permet à un trunk de tenir des milliers de commits par jour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observer les flips comme des déploiements
&lt;/h3&gt;

&lt;p&gt;Quand livrer = allumer un flag, le flip devient l'événement à risque, et il mérite les honneurs d'un déploiement : un marqueur dans les dashboards, la liste des flags actifs comme dimension dans les erreurs et les traces, et idéalement des gardes-fous automatiques qui ramènent le flag à zéro si le taux d'erreur de la cohorte exposée dévie. Le rollback n'est plus un geste d'urgence, c'est une politique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les anti-patterns qui reviennent toujours
&lt;/h3&gt;

&lt;p&gt;La branche &lt;code&gt;dev&lt;/code&gt; réinventée : « on garde juste une branche d'intégration pour regrouper les features en test ». C'est l'ancien modèle sous un nouveau nom ; ce regroupement est le rôle de l'environnement d'intégration alimenté par le trunk, flags allumés.&lt;/p&gt;

&lt;p&gt;Le flag architectural : un flag de release protège un point de divergence, à la frontière du module. Quand le même flag apparaît dans quinze fichiers, ce n'est plus un interrupteur, c'est une branche logicielle non versionnée.&lt;/p&gt;

&lt;p&gt;Le flag qui dépend d'un flag : les combinaisons deviennent intestables et les flips cessent d'être indépendants. Les interrupteurs doivent rester orthogonaux.&lt;/p&gt;

&lt;p&gt;Le staging-entrepôt : dix flags allumés en permanence « pour voir », et on a recréé la branche d'intégration en configuration. On valide une chose à la fois, pour les flags comme pour les branches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quand ce modèle n'est pas le bon
&lt;/h3&gt;

&lt;p&gt;L'honnêteté oblige à tracer les limites. Le trunk-based avec livraison continue suppose qu'on peut déployer à volonté, et ce n'est pas toujours vrai. Sur mobile, la review des stores impose des déploiements espacés ; les flags y sont paradoxalement plus précieux encore, seul levier de livraison entre deux releases. En embarqué ou en on-premise, quand le client déploie lui-même, la promotion d'artefact devient une gestion de versions supportées, et les flags de la configuration produit. Dans les domaines régulés, les gates de conformité ne disparaissent pas ; ils se déplacent dans le pipeline, revue, traçabilité, signature, plutôt que dans les branches. Et pour une équipe de deux personnes qui livre une fois par mois, le coût du système de flags peut dépasser son bénéfice : le modèle se justifie par la fréquence de livraison qu'on veut atteindre, pas par la mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Par où commencer demain matin
&lt;/h2&gt;

&lt;p&gt;Trois gestes, par ordre de rendement.&lt;/p&gt;

&lt;p&gt;Protégez votre branche principale et exigez le pipeline vert avant merge : dix minutes de configuration, effet immédiat. Livrez ensuite votre prochaine feature derrière un flag, même un simple booléen dans une config runtime ; vous découvrirez les questions concrètes, où vivent les valeurs, qui flippe, quand on nettoie, sur un cas réel et sans risque. Et mesurez votre fréquence de déploiement et votre délai commit → prod : ce sont deux des quatre métriques DORA, et elles diront, dans six mois, si la migration a tenu ses promesses.&lt;/p&gt;

&lt;p&gt;Ces trois gestes vous installent à la première étape du chemin. Les suivantes, unifier l'artefact, monter les review apps, poser les flags, se prendront une par une, quand leur échec fondateur se produira chez vous. Le plus dur n'est pas technique : c'est d'accepter que la sécurité vienne de la fréquence, pas de la prudence.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Pour aller plus loin.&lt;/strong&gt; &lt;a href="https://martinfowler.com/articles/feature-toggles.html" rel="noopener noreferrer"&gt;Feature Toggles&lt;/a&gt; de Pete Hodgson, la taxonomie de référence des flags et de leur cycle de vie. &lt;a href="https://trunkbaseddevelopment.com" rel="noopener noreferrer"&gt;trunkbaseddevelopment.com&lt;/a&gt; de Paul Hammant, le site de référence sur la méthode. &lt;a href="https://martinfowler.com/articles/branching-patterns.html" rel="noopener noreferrer"&gt;Patterns for Managing Source Code Branches&lt;/a&gt; de Martin Fowler, sur les branches d'environnement comme anti-pattern. &lt;a href="https://dora.dev" rel="noopener noreferrer"&gt;dora.dev&lt;/a&gt;, la recherche qui fonde empiriquement tout ce qui précède. Et &lt;a href="https://abseil.io/resources/swe-book" rel="noopener noreferrer"&gt;Software Engineering at Google&lt;/a&gt;, chapitres 16 et 24, en accès libre.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cicd</category>
      <category>git</category>
      <category>french</category>
    </item>
    <item>
      <title>The Future of DeFi in 2025: A Deep Dive into the Latest Innovations</title>
      <dc:creator>Luccin Masirika</dc:creator>
      <pubDate>Sat, 08 Feb 2025 12:13:14 +0000</pubDate>
      <link>https://dev.to/luccinmasirika/the-future-of-defi-in-2025-a-deep-dive-into-the-latest-innovations-egc</link>
      <guid>https://dev.to/luccinmasirika/the-future-of-defi-in-2025-a-deep-dive-into-the-latest-innovations-egc</guid>
      <description>&lt;p&gt;Decentralized Finance (DeFi) is rapidly changes are happening fast, with new tools like AI-driven smart contracts, cross-chain liquidity solutions, and advanced staking methods being thrown into the mix. Understanding these changes becomes important both for developers and blockchain engineers alike.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI-Powered Smart Contracts
&lt;/h2&gt;

&lt;p&gt;In 2025, DeFi protocols are increasingly integrating AI-driven automation to further improve efficiency and decision-making. AI models analyze real-time blockchain data to dynamically adjust the behavior of contracts. This enables smart contracts to dynamically optimize lending rates, execute trades, and detect fraud based on live market conditions. This will reduce human error, allow for self-adjusting lending pools, and improve fraud detection by finding anomalies before exploits can take place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next-Generation Oracles: Beyond Price Feeds
&lt;/h2&gt;

&lt;p&gt;From simple price feeds, traditional oracles have grown to offer a great deal more. Zero-knowledge proofs are used to provide verified data that doesn't give away sensitive information, while AI enhancements run automated market predictions and smart contract responses. Multi-chain oracles ensure consistency in the data across blockchains, with DeFi being more secure, accurate, private, and seamless in cross-chain operations through alignment of prices, liquidity, and risk metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Chain Liquidity and Unified Yield Strategies
&lt;/h2&gt;

&lt;p&gt;One of the primary pain points for DeFi has been fragmented liquidity across blockchains so far. In 2025, interoperability solutions such as LayerZero and Axelar allow fluent cross-chain transactions. There are unified liquidity pools where users can supply capital into several blockchains from one vault. The inter operability layers will manage the asset transfers themselves; wrapped tokens are not needed anymore. Smart routing algorithms optimize trades across chains for the best execution, fragmenting staking pools and letting users earn yield on-chain and across multiple chains simultaneously. This has made lending and borrowing across chains frictionless, enabling liquidity providers to maximize their efficiency by removing the need to manually bridge assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Restaking and Liquid Restaking
&lt;/h2&gt;

&lt;p&gt;Staking mechanisms too are evolving-including restaking and liquid restaking-to further improve capital efficiency. Solutions like EigenLayer and Babylon in the restaking platforms allow users to reuse their staked assets for the security of several networks without necessarily going through the unstaking process, while liquid restaking introduces new derivatives that keep staked tokens tradable while earning rewards. This approach allows the same assets to create multiple revenue streams, improves security by securing more networks with the same capital, and removes lock-up constraints, enabling users to trade or use their staked assets in DeFi.&lt;/p&gt;

&lt;h2&gt;
  
  
  RWAs in DeFi
&lt;/h2&gt;

&lt;p&gt;DeFi is going beyond crypto-native assets. Real-world assets are finding their way into the blockchain ecosystem. Stocks, bonds, and real estate, among other financial instruments, are being tokenized onto the chain. Tokenized government bonds and securities are used as collateral in DeFi, ownership of real estate is being fractionally owned on the blockchain, and commodities such as gold and oil have joined DeFi trading strategies. This integration attracts institutional capital into DeFi, increases transparency, reduces settlement times, and merges traditional finance with DeFi into a new hybrid financial system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2 Scaling and Modular Blockchains
&lt;/h2&gt;

&lt;p&gt;These innovations call for better scaling solutions for blockchains. This is being addressed by layer 2 solutions and modular blockchains. Optimistic and zk-Rollups bundle transactions for low gas fees, while modular blockchains like Celestia and EigenDA separate execution, consensus, and data availability. State channels together with rollup-based DeFi protocols are allowing faster speeds of transactions. In summary, new changes are finally allowing faster and cheaper transactions, specialized execution layers, removal of scalability bottlenecks for mass adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next-Generation Security and Self-Healing Smart Contracts
&lt;/h2&gt;

&lt;p&gt;The larger DeFi gets, the higher the risk of security. That is why next-generation security and self-healing smart contracts come to evolve: AI-driven risk detection and self-healing contracts. With AI-powered attack detection, catch exploits before they even happen. Self-healing smart contracts patch vulnerabilities in real time while on-chain anomaly detection continuously looks for suspicious activity. All this to avert possible hacks, gain trust in DeFi, and enable more developer creativity.&lt;/p&gt;

&lt;p&gt;DeFi in 2025 is more efficient, secure, and optimized in terms of capital than ever, with AI-driven automation, cross-chain liquidity, restaking, RWAs, modular scaling, and improved security.&lt;/p&gt;

&lt;p&gt;Which do you think will have the greatest impact on DeFi in the years to come? Discussion in comments welcome.&lt;/p&gt;

&lt;p&gt;If you enjoyed this deep dive, follow for more technical insights into the latest DeFi and blockchain developments.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>programming</category>
      <category>web3</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>You Won’t Believe What Happens When You Click ‘Upload’</title>
      <dc:creator>Luccin Masirika</dc:creator>
      <pubDate>Thu, 09 Jan 2025 02:21:31 +0000</pubDate>
      <link>https://dev.to/luccinmasirika/you-wont-believe-what-happens-when-you-click-upload-31bi</link>
      <guid>https://dev.to/luccinmasirika/you-wont-believe-what-happens-when-you-click-upload-31bi</guid>
      <description>&lt;p&gt;What Really Happens When You Upload a File? (It’s Not What You Think)&lt;/p&gt;

&lt;p&gt;When you click “📂 Choose File” in your browser, it feels simple. But beneath the surface, your browser kicks off a complex chain of low-level operations involving system calls, memory management, and network protocols. Let’s break it down, step by step, so you can go beyond frameworks and understand the real magic of frontend development.&lt;/p&gt;

&lt;p&gt;The Journey of an Uploaded File&lt;/p&gt;

&lt;p&gt;1️⃣ Requesting the File&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your browser interacts with the operating system to access the file using system calls like open() or fstat(). At this stage:&lt;/li&gt;
&lt;li&gt;It retrieves metadata: the file’s name, size, and MIME type.&lt;/li&gt;
&lt;li&gt;The file’s contents remain untouched—only a reference to the file (file descriptor) is created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2️⃣ Reading the File&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you upload, the browser reads the file in chunks to optimize memory usage.&lt;/li&gt;
&lt;li&gt;For large files, it might use memory mapping (mmap()), which maps the file into virtual memory, reading only the required portions.&lt;/li&gt;
&lt;li&gt;This ensures efficiency, especially for uploads like videos or high-resolution images.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3️⃣ Preparing the Data&lt;br&gt;
The file data is wrapped in a multipart/form-data format for HTTP transmission. Here’s what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--Boundary123
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

[File Content]
--Boundary123--
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Metadata headers provide context to the server (e.g., file type).&lt;/li&gt;
&lt;li&gt;Boundary markers separate the file data from other fields, like form inputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4️⃣ Sending the Data&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The data is fragmented into TCP/IP packets (each ~1460 bytes) and sent over the network.&lt;/li&gt;
&lt;li&gt;Sequence numbers ensure packets arrive in the correct order, and checksums verify their integrity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5️⃣ Encrypting the Data&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If HTTPS is used, the browser encrypts packets with TLS to protect your data during transit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;6️⃣ Handling Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a packet is lost, TCP retransmits it automatically.&lt;/li&gt;
&lt;li&gt;For resumable uploads, the browser may use techniques like chunking or Content-Range headers to resume from where the transfer stopped.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why Does This Matter for Frontend Developers?&lt;/p&gt;

&lt;p&gt;➡️ Frontend is more than frameworks. Knowing what happens behind the scenes lets you debug failed uploads, optimize large file handling, and avoid performance bottlenecks.&lt;/p&gt;

&lt;p&gt;➡️ It’s about solving real problems. Have you ever faced issues like uploads timing out, corrupted files, or unexpected slowdowns? Understanding the low-level process gives you the tools to solve these challenges effectively.&lt;/p&gt;

&lt;p&gt;➡️ It sets you apart. Mastering browser internals, from system calls to network protocols, elevates your expertise and opens doors to innovation.&lt;/p&gt;

&lt;p&gt;Frontend isn’t just about building beautiful interfaces. It’s about understanding the foundations that make those interfaces work.&lt;/p&gt;

&lt;p&gt;💡 Have you ever thought about how the browser handles file uploads? Share your thoughts below, and let me know which part of this process you’d like to dive deeper into!&lt;/p&gt;

&lt;p&gt;👩‍💻 Follow for more technical deep dives like this!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>system</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
