
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.
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 tech › architecture.
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.mdpour 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.
Articles dans le même univers
Sources citées
- Martin Fowler, Patterns of Enterprise Application Architecture, Addison-Wesley, 2002 — chapitre Active Record (martinfowler.com/eaaCatalog/activeRecord.html)
- Google Cloud, DORA 2024 State of DevOps Report — métrique Lead time for changes (cloud.google.com/devops/state-of-devops)
-
MariaDB Foundation, documentation officielle
MEDIUMTEXTetInnoDB(mariadb.com/kb/en/) -
Alexandre Carette, Journal de chantier CodeMyShop — commits
9fcd1a53etf86afa22(préprod, 11 avril 2026)
Approfondir dans l'Academy
Questions fréquentes
Tout ce que vous devez savoir sur ce sujet.
Une question ?
Contactez-nous directement.