Produit

Un prototype prouve qu'une chose est possible. Un produit tient quand elle se passe mal : une API qui ne répond pas, un utilisateur qui clique deux fois, une base à restaurer un dimanche soir. L'écart entre les deux ne se compte pas en fonctionnalités mais en sept chantiers que le prototype n'a jamais eu besoin d'ouvrir, et dont trois deviennent nettement plus chers si on les ouvre après la mise en ligne.

7 min de lecture · mis à jour le 19 septembre 2026

Un prototype n'a prouvé qu'une seule chose

Un prototype fait fonctionner le chemin heureux. L'utilisateur clique là où il faut, le réseau répond, les données sont propres, et il n'y a qu'une personne devant l'écran. C'est exactement ce qu'on lui demande : lever un doute de faisabilité, vite et pour pas cher.

Un produit passe l'essentiel de son code sur tout le reste. Ce n'est pas la même quantité de travail, c'est une autre nature de travail : le prototype ajoute des capacités, le produit ajoute des garanties.

La confusion coûte cher parce qu'elle ne se voit pas. À l'écran, un prototype et un produit se ressemblent. La démonstration convainc, et on en conclut logiquement que le projet est presque terminé. Il est terminé à l'endroit où on regarde.

Les sept chantiers qui suivent ne se valent pas : trois se rattrapent mal, trois se rattrapent en travaillant plus, un seul mérite d'être repoussé. Les confondre dans un même « on verra plus tard » est ce qui coûte le plus cher dans un passage en production.

Les erreurs : le chantier qui traverse tout le code

Dans un prototype, un appel qui échoue fait planter l'écran ou ne fait rien du tout. Personne ne s'en plaint, parce que personne ne déclenche l'erreur : la démonstration suit le script.

Un produit doit décider, pour chaque appel, ce qui se passe quand il échoue. Quatre réponses possibles, pas interchangeables : réessayer, afficher quelque chose, annuler ce qui a déjà été écrit, alerter quelqu'un. Le bon choix dépend de la fonction concernée, pas d'une règle posée une fois pour toutes.

Ajouté après coup, ce chantier ne se localise pas. Il faut rouvrir chaque fonction qui parle au réseau ou à la base, changer ce qu'elle retourne, puis propager ce changement à tout ce qui l'appelle. Le coût est là : pas dans l'écriture du code de secours, mais dans la relecture de la moitié du produit pour savoir où le brancher.

Le vrai risque n'est pas l'écran blanc, qui se voit et se signale. C'est l'échec silencieux : un paiement enregistré d'un côté et pas de l'autre, un formulaire qui affiche une confirmation alors que rien n'a été écrit. Ces cas-là se réparent à la main, dossier par dossier, une fois que quelqu'un s'en est aperçu.

L'attente : ce que les états de chargement révèlent

Un prototype tourne sur des données locales, instantanées. La question de l'attente ne se pose pas, donc l'interface n'a ni indicateur de chargement, ni squelette, ni protection contre le double clic.

C'est le moins cher des sept, parce qu'il reste dans l'interface. C'est aussi celui qui dénonce les autres : quand on regarde enfin ce qu'on attend, on découvre où les données sont réellement demandées.

Le cas le plus courant est la liste qui déclenche une requête par ligne. En local, sur dix lignes, c'est invisible. En production, sur deux cents lignes et avec de la latence réseau, c'est une page qui met plusieurs secondes et un serveur qui reçoit deux cents fois plus d'appels que prévu. La correction n'est pas dans l'affichage, elle est dans la façon dont la page demande ses données.

La raison de traiter ce point tôt n'est pas esthétique : un bouton qui ne se désactive pas pendant l'envoi produit des doublons. Deux commandes, deux débits, un client à rembourser.

Sans journalisation, un incident se raconte au lieu de se lire

Un prototype n'a pas besoin de mémoire : quand il casse, le développeur est devant l'écran. En production, l'incident remonte des heures plus tard, par quelqu'un qui décrit ce qu'il croit avoir fait.

Journaliser, ce n'est pas semer des messages de débogage. C'est conserver ce qui s'est produit : quelle opération, pour quel compte, avec quel résultat, à quelle heure, en combien de temps. Et remonter les erreurs à un endroit que quelqu'un est chargé de lire.

Ce chantier a une particularité désagréable : son rattrapage ne rattrape rien. Des journaux installés aujourd'hui n'expliquent pas l'incident d'hier. On ajoute la capacité de comprendre, jamais la compréhension du passé. Chaque semaine passée sans journalisation est une semaine d'incidents définitivement non élucidés, et ce sont souvent ceux des premiers utilisateurs, donc ceux qui comptent le plus.

L'arbitrage porte sur la durée de rétention et sur le contenu, jamais sur le principe : un journal qui enregistre des mots de passe, des jetons de session ou des données personnelles en clair devient lui-même le problème qu'on cherchait à éviter.

L'authentification : le seul chantier qui change la forme des données

Un prototype a un utilisateur unique et implicite. Ses données vivent dans des tables sans propriétaire, et chaque requête les lit toutes.

Ajouter des comptes ensuite ne consiste pas à poser un écran de connexion devant l'existant. Il faut attribuer un propriétaire à chaque ligne déjà écrite, filtrer chaque requête existante sur ce propriétaire, et trancher une question qui n'a pas de bonne réponse : à qui appartiennent les données créées avant qu'il y ait des comptes.

C'est le plus cher des sept à rattraper, pour une raison structurelle : il modifie le modèle de données, donc toutes les couches posées dessus. Et il ne tolère pas l'oubli. Une seule requête non filtrée laisse un utilisateur voir les données d'un autre. Si ces données sont personnelles, ce n'est plus un correctif à livrer, c'est un incident à documenter et, selon le cas, à notifier.

La bonne version au démarrage peut rester modeste : un compte, un mot de passe correctement haché, une session, un identifiant de propriétaire sur les tables concernées, et un filtrage appliqué partout. Le reste se change plus tard sans douleur — mot de passe, lien de connexion, fournisseur externe, double facteur. La présence d'un propriétaire, non.

Sauvegardes et reprise : le rattrapage se paie en données, pas en jours

Mettre en place une sauvegarde après coup prend peu de temps, et c'est ce qui rend l'arbitrage trompeur : le coût de son absence ne se mesure pas en temps d'installation, mais en données perdues entre la mise en ligne et l'installation. Quand on s'en aperçoit, il est déjà payé.

Une sauvegarde n'existe que si elle a été restaurée. Tant que personne n'a remonté une copie sur un environnement neuf et vérifié que le produit démarre dessus, on possède un fichier, pas une sauvegarde. Le dump tronqué, la base chiffrée dont la clé est restée sur la machine perdue, la copie qui ignore les fichiers déposés par les utilisateurs : cela ne se découvre qu'à la restauration.

La reprise ne concerne pas que les données. Elle concerne aussi le code : pouvoir revenir à la version précédente en quelques minutes change ce qu'on s'autorise à déployer un jeudi après-midi. Sans ce retour, chaque mise en ligne devient une décision lourde ; les mises en ligne lourdes deviennent rares ; les rares deviennent grosses ; les grosses cassent davantage. Le manque de reprise fabrique le risque qu'il prétendait éviter.

  • Où la sauvegarde est-elle écrite, et cet endroit survit-il à la perte du serveur principal ?
  • Quand a-t-elle été restaurée pour de bon, et par qui ?
  • Combien de temps faut-il pour remettre le service debout à partir de rien ?

La montée en charge : le seul des sept qu'on a raison de repousser

Contrairement aux six autres, optimiser avant de mesurer est du gaspillage. On ne sait pas où un produit tiendra mal, et les endroits qu'on devine sont rarement ceux qui cèdent. Rendre rapide une fonction que personne n'utilisera prend du temps aux chantiers ci-dessus.

Ce qui se fait tôt n'est pas l'optimisation, c'est le fait de s'en garder la possibilité. Trois décisions suffisent, et ne coûtent rien au moment où on les prend : pas d'état dans la mémoire du processus, pas de fichier utilisateur sur le disque local, et une mesure des temps de réponse dès le premier jour.

Prise à l'envers, chacune interdit plus tard la solution simple. De l'état en mémoire empêche de lancer un deuxième processus, donc de répartir la charge. Des fichiers sur le disque local empêchent de changer de machine sans les déplacer. L'absence de mesure condamne à optimiser au jugé.

Le reste — cache, index, file d'attente, réplication — s'ajoute quand la mesure le réclame, et là où elle pointe. C'est du travail localisé, sans migration de données. Exactement l'inverse de l'authentification, et c'est pour cette raison qu'il attend.

Ressources