Le coût caché de la double saisie
On compte le temps de recopie. C’est la partie visible, et la moins chère.
La partie coûteuse arrive plus tard. Une adresse mise à jour dans le CRM mais pas dans la facturation. Un client marqué inactif d’un côté, relancé de l’autre. Un stock à jour dans l’outil de gestion, faux sur le site. Chaque écart est individuellement mineur ; leur accumulation produit un état où plus personne ne sait quel outil a raison, et où la réponse devient « je vais vérifier », c’est-à-dire ouvrir les deux.
À partir de ce moment, les deux outils coûtent plus cher qu’ils ne rapportent, et l’équipe se met à tenir un troisième fichier — un tableur — qui est censé arbitrer. C’est le symptôme classique.
Ce qu’on automatise
La désignation d’une source de vérité. Pour chaque donnée, un seul outil fait foi. C’est une décision d’organisation, pas de technique, et c’est la première chose qu’on écrit.
La traduction. La table de correspondance entre les champs des deux systèmes, y compris les listes de valeurs et les unités.
Le transfert. En continu quand les outils le permettent, ou par lots réguliers. Les deux sont légitimes ; le temps réel n’est pas toujours utile et coûte plus cher.
La déduplication. Reconnaître qu’un client existe déjà, même avec une orthographe différente, avant de le créer une deuxième fois.
La reprise après panne. File d’attente, réessais, alerte si la situation dure.
Le journal. Quel enregistrement a été transféré, quand, avec quelles valeurs. Indispensable le jour où quelqu’un demande pourquoi un montant a changé.
Comment ça marche techniquement — pour qui veut le détail
Les modes de lecture. Par ordre de préférence. Webhook quand la source sait notifier — c’est immédiat et économe. Interrogation incrémentale sinon : on ne redemande pas tout, on demande ce qui a changé depuis le dernier curseur (updated_after), et on stocke ce curseur. Export planifié quand le logiciel ne propose que ça : un CSV déposé chaque nuit sur un partage, récupéré par un systemd path unit qui réagit au dépôt du fichier. Lecture directe en base quand l’éditeur l’autorise, via un compte en lecture seule et, idéalement, une vue dédiée plutôt que les tables brutes. Automatisation d’interface avec Playwright en dernier recours, avec sélecteurs stables et capture d’écran systématique en cas d’échec, pour diagnostiquer les changements de l’éditeur.
L’idempotence. Chaque transfert porte une clé stable — identifiant source, ou empreinte du contenu métier. Avant d’écrire, on vérifie. C’est ce qui permet de rejouer un lot entier sans créer de doublons, et donc de réparer sereinement après un incident. Une passerelle non idempotente est une passerelle qu’on n’ose pas relancer.
La file et les réessais. Une table de tâches en PostgreSQL avec SELECT … FOR UPDATE SKIP LOCKED suffit à tenir une file fiable sans ajouter un courtier de messages : plusieurs travailleurs peuvent consommer en parallèle sans se marcher dessus, et l’état survit à un redémarrage. Réessais à délai exponentiel avec un peu d’aléa, plafond de tentatives, puis mise en file morte avec le message d’erreur brut conservé. Redis intervient pour le cache et la limitation de débit, pas pour la durabilité.
Le rapprochement des enregistrements. Correspondance exacte d’abord sur un identifiant fort — SIREN, e-mail normalisé, référence client. Correspondance approchée ensuite sur le nom, après normalisation (minuscules, accents retirés, formes juridiques supprimées, espaces réduits), avec une mesure de type trigrammes (pg_trgm en PostgreSQL) ou distance de Levenshtein. Au-dessus d’un seuil : rapprochement automatique. Entre deux seuils : file de validation humaine. En dessous : création d’un nouvel enregistrement. Les seuils se règlent sur vos données réelles, pas sur une valeur par défaut.
Les limites de débit. Les API commerciales plafonnent les appels. On respecte le plafond par un seau à jetons côté client, on lit les en-têtes Retry-After et X-RateLimit-Remaining, et on regroupe les écritures quand l’API accepte les lots. Ignorer ce point mène au blocage du compte, ce qui est un incident plus ennuyeux qu’une lenteur.
Les transactions et la cohérence. Deux systèmes distincts n’offrent pas de transaction commune. On écrit donc dans un ordre pensé, on rend chaque étape rejouable, et on accepte une cohérence différée plutôt que de prétendre à une atomicité qui n’existe pas. Le journal des opérations est ce qui rend cette cohérence différée vérifiable.
La surveillance. Un battement régulier : si aucun transfert n’a eu lieu depuis N heures alors qu’il aurait dû y en avoir, alerte. Uptime Kuma sur un point de contrôle suffit. Une passerelle qui tombe en silence est le pire scénario, parce qu’on la découvre par l’écart, des semaines plus tard.