La Révolution S.O.A.P : pourquoi nous avons supprimé 20 000 lignes
tech

La Révolution S.O.A.P : pourquoi nous avons supprimé 20 000 lignes

20 000 lignes de code mort supprimées en un commit : pourquoi CodeMyShop a basculé vers une architecture S.O.A.P souveraine, DB-First sur MariaDB.

8 min de lecture

Le 11 avril 2026, j’ai supprimé 20 000 lignes de code du monorepo CodeMyShop en un seul commit. 113 files changed, 558 insertions(+), 20349 deletions(-). Aucun utilisateur final ne s’en est aperçu. Ce chantier a duré quatre phases étalées sur deux semaines, et il a transformé notre architecture d’un système de fichiers statiques vers une plateforme d’orchestration DB-First que nous appelons désormais S.O.A.P (Service Orchestration and Automation Platform). L’opération était risquée, elle a été totale, et elle a surtout été réversible à chaque étape. Si vous opérez une stack qui mélange fichiers .md, scripts Python one-shot et table de base de données, vous avez probablement déjà le même goulot d’étranglement que nous avions. Voici comment nous l’avons identifié, comment nous l’avons contourné sans downtime, et ce que vous pouvez appliquer tel quel.

Les quatre problématiques d’une architecture fichiers-first

Cet article fait partie de notre dossier techarchitecture.

Avant la bascule, CodeMyShop reposait sur trente profils d’agents IA stockés dans agents/.md, onze workflows dans workflows/.md, et quarante-sept scripts publish_*.py dans automation/. Le système fonctionnait. Le problème n’était pas la fiabilité — il était la friction cumulée.

Symptôme observé Origine structurelle Coût mesuré
Désynchronisation prod ↔︎ fichier Deux sources de vérité (disque + base) maintenues à la main 1 incident prod de 5 min le 7 avril (Academy et Dictionnaire à 0 entrée)
Temps de correction d’une faute de frappe dans un profil d’agent Édition fichier → commit → push → build → redéploy ~15 min / correction × 30 agents × 3 modifs/jour
Impossibilité de lister les articles par statut 1 script Python par article, aucune table centrale Pas de pipeline, pas de republication, pas de filtrage
Conflits de merge sur données éditables Fichiers versionnés pour du contenu qui n’a rien à faire en git Bloque les sessions parallèles, crée de la dette quotidienne

Comment nous avons basculé en quatre phases

L’incident du 7 avril a été le déclencheur. Ce matin-là, une mise à jour apparemment anodine — renommer une convention de slug partagée entre le code Nuxt et la base de données — a laissé la production en mode dégradé pendant cinq minutes. L’Academy et le Dictionnaire affichaient zéro entrée sur les pages publiques, les crawlers sont passés dessus, et nos propres monitors n’ont rien vu parce qu’ils pinguaient des URLs qui renvoyaient bien un HTTP 200 avec du vide dedans. La cause racine tenait en une phrase : nous avions exécuté l’UPDATE de la base avant de déployer le code aligné. Cinq minutes de désynchronisation suffisent à casser la confiance d’un crawler Google. Le dimanche suivant, nous avons décidé de transformer cette cicatrice en architecture.

Le principe directeur de toute la réarchitecture : aucune phase ne doit produire de fenêtre vulnérable en production. Si une phase échoue, elle doit pouvoir être annulée en une commande. Cette contrainte a dicté l’ordre des opérations — un ordre contre-intuitif qui consiste à déployer le code avant les données. Nous avons découpé le chantier en quatre phases, chacune révocable, chacune auditée avant de passer à la suivante, chacune déployée sans demander d’autorisation spéciale au reste de l’équipe.

Phase 1 — Poser le schéma DB

Nous avons créé trois tables dans la base MariaDB existante : ps_ac_agents (avec une colonne content_md de type mediumtext), ps_ac_workflows sur le même modèle, et ps_ac_article_draft — la table centrale de la pipeline de contenu avec ses champs title, slug, meta_data (JSON), content_md, status (draft / ready / published / archived). À ce stade, les tables étaient vides, personne ne les lisait. Aucun risque.

Phase 2 — Écrire les façades Active Record

Chaque table reçoit une classe Python qui encapsule create(), update(), get(), validate(). Un hook pre-commit refuse tout script qui tente d’écrire en ps_ac_* en SQL brut sans passer par une façade. Ce n’est pas un lint amical — c’est un barrage. Cette couche rend les mutations auditables et testables, et elle concentre la logique de validation en un seul endroit.

Phase 3 — Déployer le code avec dual-read

C’est l’étape qui rend le cutover invisible. Tous les consommateurs (scripts d’audit, runner d’agents, générateur de cover, processeur de cicatrices) ont été patchés pour lire en priorité la nouvelle source (DB) et retomber sur l’ancienne (fichiers) si la DB est vide. Nous déployons ce code, nous le laissons tourner trois jours en production, nous surveillons les logs. Résultat : la prod continue de servir exactement la même chose, mais elle est déjà prête à basculer. Si un bug apparaît pendant ces trois jours, on corrige sans urgence — les deux sources tiennent encore.

Phase 4 — La suppression massive

Samedi 11 avril, filet de sécurité posé sous forme de tag git pre-phase4-cutover. Puis dans un seul commit :

  • git rm agents/*.md (30 fichiers)
  • git rm workflows/*.md (11 fichiers)
  • git rm automation/publish_*.py (47 fichiers)
  • Réécriture de dix-huit scripts Python pour retirer les références aux fichiers supprimés
  • Mise à jour de CLAUDE.md pour graver la nouvelle doctrine

Le commit a touché 113 fichiers, supprimé 20 349 lignes, ajouté 558. Aucun rebuild spécial, aucun redéploy d’urgence, aucun incident. La prod lisait déjà la DB depuis trois jours — la suppression des fichiers n’a changé que le nombre d’inodes sur le disque.

Les solutions apportées, problème par problème

Problème Solution DB-First Gain opérationnel
Désynchronisation prod ↔︎ fichier Une seule source : ps_ac_* en MariaDB, façades Active Record obligatoires Classe entière de bugs éliminée — impossible d’avoir deux valeurs divergentes
Temps de correction d’un profil d’agent UPDATE ps_ac_agents.content_md en SQL, zéro redéploy 15 min → 2 secondes, édition à chaud pour tous les agents
Pipeline de contenu inexistante Moteur unique ac_publisher_engine.py lit ps_ac_article_draft Liste, filtre, republie, archive — toutes actions en une commande
Conflits de merge sur données éditables Données hors git, code seul dans git Sessions parallèles sans friction, dette quotidienne supprimée

Ce que ça change pour un commerçant

L’architecture S.O.A.P n’est pas un exercice de style technique. Elle conditionne la vitesse de modification d’une boutique en ligne. Quand vous utilisez un site sous CodeMyShop et que vous voulez ajouter une fonction multi-devise, il n’y a plus de script à écrire : la fonction s’active par une mutation en base, et votre front Nuxt la sert à la seconde suivante. Quand vous voulez publier un article, vous insérez un enregistrement dans ps_ac_article_draft, vous appelez le moteur, votre article est en ligne. Quand vous voulez modifier votre menu principal, vous éditez la ligne correspondante — aucun redéploy. C’est exactement le principe que nous décrivons dans le module Architecture headless souveraine en Nuxt 3, et c’est le cœur de notre boucle Flywheel : chaque seconde gagnée à l’exécution est une seconde rendue à la pensée stratégique.

Prenons un exemple concret. Un commerçant de fruits secs découvre, un vendredi à 16h, qu’un concurrent vient de sortir une promotion sur les dattes. Sur une stack traditionnelle, réagir demande d’éditer un fichier de configuration, de committer, de pousser, d’attendre le build du front, puis de vérifier que rien n’a cassé — compter vingt à quarante minutes dans le meilleur des cas, et la promotion est déjà obsolète. Sur CodeMyShop, il ouvre son back-office, il écrit une règle de remise dans la table ps_ac_promotions, elle est visible sur le front en trois secondes, et il retourne à son café. La différence n’est pas une différence d’outil — c’est une différence de champ des possibles. Ce qui coûtait trop cher à tenter devient gratuit, et le commerçant commence à expérimenter là où il subissait avant.

Source d’autorité — Martin Fowler, Patterns of Enterprise Application Architecture
Le pattern Active Record, formalisé par Martin Fowler en 2002, repose sur un principe simple : « An object that wraps a row in a database table, encapsulates the database access, and adds domain logic on that data. » Vingt-deux ans plus tard, ce pattern reste la réponse la plus solide pour éliminer la divergence entre le code applicatif et l’état persistant. Nous l’appliquons sans modification théorique — uniquement avec un garde-fou supplémentaire sous forme de hook pre-commit qui refuse tout raw SQL hors façade. Référence : martinfowler.com/eaaCatalog/activeRecord.html.

Conclusion — la vitesse de correction est la vraie métrique

Si vous retenez une seule chose de ce chantier, retenez celle-ci : le nombre de secondes entre le moment où vous décidez un changement et le moment où la production le reflète est la métrique qui sépare les stacks qui scalent des stacks qui stagnent. Chaque friction fichier, chaque script one-shot, chaque synchro manuelle ajoute des minutes à cette métrique. Au bout de quelques mois, cette dette devient une architecture qui se maintient elle-même plutôt qu’un outil au service de votre stratégie.

La bascule DB-First n’est pas un projet d’ingénieur. C’est une décision stratégique qui rend votre équipe capable de changer d’avis sans payer un redéploiement. Sur CodeMyShop, cette vitesse de modification est désormais de moins de trois secondes pour n’importe quelle donnée runtime. C’est le seuil à partir duquel un commerçant peut expérimenter sans crainte — et c’est le seuil qui transforme un site vitrine en terrain de jeu.

Votre architecture vous ralentit ?

Audit gratuit de 30 minutes : je regarde votre stack actuelle, je repère les goulots d’étranglement, je vous dis exactement par où commencer. Zéro engagement, zéro commercial.

Réserver 30 min avec Alexandre →

Sources citées

Questions fréquentes

Tout ce que vous devez savoir sur ce sujet.

Une question ?

Contactez-nous directement.

Gratuit & sans engagement — réponse sous 24h

Discussion

Votre avis sur cet article

Les commentaires sont modérés et répondus par une intelligence artificielle. Votre email ne sera jamais affiché.

0 / 2000

En publiant, vous acceptez que votre nom et commentaire soient affichés publiquement. Votre email est utilisé uniquement pour la modération (base légale : intérêt légitime, durée : 3 ans). Politique de confidentialité.