On m’a confié un SaaS sur Firebase à faire passer sur Supabase, avec un budget très limité. Cet article présente les techniques que j’ai utilisées pour y arriver avec un harnais IA.

Point de départ

L’application était un SaaS Nuxt.js avec 20 gros écrans qui tournaient sur Firebase, déjà écrit en TypeScript. Elle fonctionnait comme un workflow qui enrichissait les données métier étape par étape.

Les utilisateurs pouvaient gérer plusieurs projets. Chaque projet appartenait à un ou plusieurs « managers », qui pouvaient inviter des « contributors » à parcourir le workflow. Cela impliquait un système de rôles. Il y avait également une partie administration.

Les contraintes liées à la protection des données dans un domaine sensible, ainsi que le projet de proposer une version auto-hébergée, ont poussé le client à remplacer son backend et sa base de données par des technologies plus ouvertes et moins coûteuses.

Le périmètre Firebase à remplacer était le suivant :

  • Auth : email/mot de passe basique
  • Base de données : 66 tables avec beaucoup de relations en cascade
  • Realtime : utilisé pour rafraîchir la page de chaque utilisateur lors des mises à jour
  • Stockage de fichiers : utilisé uniquement par une fonctionnalité d’export de rapports qui n’a jamais tourné en production

Un autre développeur, spécialisé en Nuxt.js, avait estimé cette migration à 30 jours.

Pourquoi cela semblait impossible

Dès mon premier regard sur le projet, il était clair que la base de code n’était pas adaptée à une migration.

À l’origine, c’était un petit SaaS développé par un seul développeur avec peu de budget, et beaucoup de raccourcis avaient été pris au fil du temps pour limiter les coûts.

  • Pas d’ORM, pas de couche d’abstraction.
  • Pas de tests — et cela va influencer toutes les décisions dans la suite de cet article.
  • Pas de couches, pas de vrai travail d’architecture pour séparer les responsabilités.
  • Des appels Firebase un peu partout.
  • Les entités étaient directement des objets générés par Firebase.
  • Les règles métier et l’accès à la base de données étaient mélangés dans l’application Nuxt.js.
  • Certaines règles métier étaient calculées côté client sans vraie raison (une simulation de Monte-Carlo, par exemple).

En plus de cela, les vérifications de rôles et de permissions étaient dispersées dans le code. Chacune pouvait poser un problème de sécurité pendant la migration :

  • Périmètre des rôles (propriétaires et contributeurs)
  • Multi-tenancy
  • Multi-projets
  • Un dashboard d’administration, directement accessible depuis l’application publique, qui servait à configurer les données statiques et l’application en général

Une seule chose jouait en ma faveur : l’application n’était pas encore en production. La plupart des données étaient des données de configuration statiques ou des données de test.

Avec tout ça, la migration semblait impossible — ou au minimum beaucoup trop compliquée pour le budget du client sans l’aide de l’IA.

La mauvaise approche

Au début, je suis parti sur une migration étape par étape, comme on l’aurait fait manuellement :

  • Strangler Fig : remplacer petit à petit l’ancien système par le nouveau.
  • CDC (Change Data Capture) : faire tourner les deux systèmes en parallèle pendant la migration, puis supprimer l’ancien.

J’ai rapidement compris que ce n’était pas la bonne approche. Je l’ai testée sur un seul écran, puisqu’une approche par couches n’était pas possible. Malgré mes tentatives pour guider le modèle, le résultat restait incohérent, et il confondait les données partagées avec les données propres à chaque tenant. Des données se retrouvaient au mauvais endroit, ce qui m’a fait craindre des fuites de données.

J’ai supposé — à juste titre, comme la suite l’a montré — qu’une approche plus globale réduirait ce risque. Une migration étape par étape aurait probablement fonctionné, mais elle aurait demandé plus de temps pour construire un bon harnais. C’était le signal d’alarme, alors je suis finalement parti sur une migration big bang. Ce n’était probablement pas l’option la plus sûre, mais sur ce projet, le coût comptait plus que le risque.

Après tout, l’IA est meilleure que moi pour explorer une base de code, et elle est plus rapide. Ce sont les principales compétences que demande une migration. En théorie, elle devait donc gérer un big bang mieux que moi.

Big bang, oui — mais avec une phase d’analyse

Big bang, oui. Mais pas sans préparation.

J’ai commencé par une phase d’analyse. Le modèle a lu le code, puis m’a posé des questions fonctionnelles et techniques. Il a produit un gros fichier Markdown qui expliquait comment faire la migration, et ce fichier est devenu ma spec.

Ensuite, je lui ai demandé d’écrire une liste de tâches dans un deuxième fichier Markdown.

Enfin, j’ai lancé la migration en donnant au modèle les deux fichiers : la liste des tâches et l’analyse.

Les outils

Les modèles les plus avancés savent choisir et combiner des outils par eux-mêmes pour venir à bout de tâches complexes.

Je me suis appuyé là-dessus et j’ai laissé l’IA utiliser tout ce dont elle avait besoin. Je lui ai donc donné accès à :

  • Des outils pour interroger la base de données source
  • Des outils pour interroger la base de données cible
  • Un environnement Docker local pour déployer l’application
  • Et surtout, un navigateur Chrome via MCP — pour accéder à l’application et à tout ce dont le modèle pourrait avoir besoin

Gérer la paresse de l’IA

Quand j’ai fait cette migration, Opus était à la pointe. Il était très bon pour les tâches de développement répétitives et qui demandaient beaucoup de logique, mais il avait tendance à être paresseux et à s’arrêter au milieu en disant : « c’est terminé ».

Astuce : quand une session dit que le travail est terminé, demandez à une autre session Claude de le vérifier. Cela m’a sauvé plusieurs fois. Ajouter cette instruction dans le fichier de prompt CLAUDE.md ne suffit pas : la fenêtre de contexte reste la même, donc la paresse et l’auto-satisfaction finissent quand même par revenir.

Ma technique pour réduire cette paresse a été d’utiliser autant d’objectifs et de boucles que possible.

Depuis, Fable est sorti. Il est cher, mais il est optimisé pour les tâches qui durent longtemps, il devrait donc réduire ce problème de paresse.

Laisser tourner la boucle

Pour cette mission, j’ai construit un système de boucles. Il fait travailler le modèle pendant des heures au lieu de le laisser crier victoire trop tôt. L’idée est simple : donner un objectif au modèle et ne pas le laisser s’arrêter tant que l’objectif n’est pas atteint.

Voici quelques objectifs que j’ai utilisés :

  1. Migrer cette application de Firebase vers Supabase en suivant les étapes de @tasks.md et l’analyse de @analysis.md.
  2. Installer cette application ainsi que les prérequis Supabase sur mon Kubernetes local (k3d).
  3. Lister toutes les pages dans une checklist dans un fichier Markdown. Tester chacune avec Chrome MCP, corriger les bugs et cocher la page une fois terminée. Ne pas s’arrêter tant que toutes les pages ne sont pas vérifiées.
  4. Vérifier les permissions d’accès de chaque ressource Supabase, une par une. Écrire les corrections proposées dans threat.md.
  5. Il y a un problème de performance lors du chargement de <screen url>. Corriger le problème.

Ensuite, l’agent de développement fait son travail et teste lui-même ses changements avec Chrome MCP.

Ce système de boucles a corrigé beaucoup d’écrans qui ne se chargeaient plus. Il a aussi corrigé tout seul une mauvaise redirection à la connexion. Et il a détecté des données nulles ou incorrectes, en comparant chaque composant de chaque écran entre l’ancienne et la nouvelle version.

Script de migration des données

La migration des données elle-même était simple, pour la raison expliquée plus tôt : l’application n’était pas en production, donc il n’y avait pas de vraies données clients, seulement des données statiques. Pour l’IA, cela revenait à faire du copier-coller dans un script SQL de seeding.

Résultat

La migration a pris 5 jours au lieu des 30 jours estimés par l’autre développeur. Le déploiement a pris un jour de plus, également avec l’aide de l’IA.

L’application a depuis été mise en production et fonctionne sans aucun problème.