Skip to Content
L’échange d’apprentissage de HIC débute le 13 Juillet 2026. Voir le programme
LectureÉlément 6 sur 22 · 35 min

Health Sync : relier les données des établissements de santé

Comment le Rwanda connecte les bases de données DME des établissements au magasin central du HIC — le système, la méthodologie d’intégration des sites et les leçons apprises sur neuf déploiements hospitaliers en production entre mars et juillet 2026. Cette lecture accompagne les sessions d’architecture de données sur la couche source et l’ELT : Health Sync est le pipeline qui livre des données brutes continues au niveau établissement dans l’entrepôt sur lequel les ateliers s’appuient.

Compléments d’approfondissement — la documentation interne complète est publiée dans cette bibliothèque :

  • Aperçu de Health Sync — l’architecture, les trois boucles du runner et chaque décision de conception avec sa justification.
  • Runbook de déploiement — les commandes exactes des six parties du déploiement, reproductibles dans votre propre environnement.
Ce que vous apprendrez
  • Expliquer pourquoi la synchronisation établissement-centre repose sur la livraison « au moins une fois » et des upserts idempotents
  • Dérouler la méthodologie d’intégration de site en quatre étapes utilisée dans neuf établissements rwandais
  • Reconnaître les pièges récurrents d’infrastructure et de qualité des données dans les bases DME des établissements
  • Appliquer les leçons de sécurité — dont un véritable incident de chaîne d’approvisionnement — aux logiciels de flotte à mise à jour automatique
  • Répondre aux questions d’adaptation pays pour votre propre contexte SIS

Le problème en un paragraphe

Les DME des établissements (MySQL basé sur OpenMRS) sont isolés à l’intérieur de chaque établissement, alors que l’intelligence sanitaire nationale — la surveillance des épidémies avant tout — a besoin de ces données au centre en quelques minutes. La connectivité des établissements n’est pas fiable, personne ne peut se déplacer pour déployer un correctif, et les serveurs des établissements font tourner des systèmes cliniques de production fragiles. Health Sync répond aux trois : une file locale durable qui ne perd aucune donnée pendant les pannes, des runners à mise à jour automatique qui n’exigent jamais de déplacement, et une empreinte minimale, conteneurisée, en lecture seule à la source et manifestement inoffensive.

MySQL (établissement) → runner → file SQLite locale → HTTPS → API centrale → PostgreSQL │ │ └── interroge GitHub, s'auto-met à jour └── schéma par site, battements de cœur, journaux, métriques

L’idée de conception la plus importante pour les liaisons peu fiables : renvoyer est gratuit ; un trou perd des données. Les watermarks se chevauchent volontairement, la livraison est « au moins une fois », et le centre fait des upserts — la justesse vient de l’idempotence, pas de la lutte contre les doublons.

Comment les sites sont intégrés — la méthodologie

C’est l’artefact le plus directement transférable pour les pays qui adaptent le modèle. Il a évolué d’un premier déploiement prudent d’environ 5 heures à un playbook répétable en moins d’une heure au neuvième site. Chaque étape ci-dessous a ses commandes exactes dans le runbook de déploiement.

Étape 0 : prouver l’innocuité avant de toucher à la production

Avant tout déploiement hospitalier, un site de démonstration jetable sur un serveur de réserve a démontré de bout en bout que MySQL, Docker et le runner pouvaient être installés sans mettre en danger un serveur d’établissement fragile : tout conteneurisé, paquets épinglés contre les mises à jour automatiques, installations minimales, rien d’exposé publiquement. Cette démonstration — à laquelle le personnel de l’établissement a assisté — est ce qui a transformé l’hésitation institutionnelle en autorisation écrite de déploiement.

Étape 1 : précharger l’historique hors ligne ; ne synchroniser que le delta

Un rattrapage de plusieurs années d’historique à la première synchronisation martèlerait à la fois le serveur de l’établissement et l’API centrale. À la place :

  1. Obtenir un dump de la base de l’établissement.
  2. Extraire en streaming uniquement les tables cibles (les dumps rétrécissent de 60 à 80 %).
  3. Restaurer dans un conteneur MySQL jetable, plafonné en mémoire et réglé pour la vitesse sur le serveur central (redo log désactivé, binlog coupé — 2 à 4× plus rapide, annulable sans risque).
  4. Charger dans le schéma PostgreSQL de l’établissement ; ajouter les clés primaires, _synced_at et les index analytiques.
  5. Placer le watermark de départ du runner juste avant la coupure du dump (le chevauchement est gratuit).

Tout le pipeline tient dans un seul script reprenable : 14 phases suivies, des fichiers d’état par phase (délibérément pas dans /tmp — un redémarrage a un jour effacé des heures de travail), des vérifications mémoire préalables avec abandon automatique, et un mode incrémental qui peut ajouter de nouvelles tables à un site en production sans toucher aux données existantes ni faire tourner les identifiants du site.

Étape 2 : préparer la base source

Chaque base OpenMRS d’établissement rencontrée manquait d’index sur ses colonnes d’horodatage. Au premier site, chaque cycle de synchronisation devenait un balayage complet de 23 secondes d’une table de 16,7 millions de lignes. Le correctif coûte moins d’une minute :

CREATE INDEX idx_obs_date_created ON obs (date_created) ALGORITHM=INPLACE LOCK=NONE;

Le DDL en ligne de MySQL 8 construit l’index sans verrouiller la table — sûr sur un système clinique en production, et annulable sans risque. (Notez la syntaxe : les options sont séparées par des espaces, pas des virgules — appris sur un serveur de production.)

Mesurez avant de toucher à un système hospitalier en production. Comptages de lignes, charges moyennes et requêtes de test chronométrées ont transformé « est-ce que cela va nuire au DME ? » d’une crainte en une réponse quantifiée et défendable devant le personnel de l’établissement.

Étape 3 : installer et vérifier

Un installateur en une ligne clone le dépôt, construit l’image du runner, déroule un assistant interactif pour la configuration du site et la sélection des tables, puis démarre le conteneur. La vérification post-installation contrôle les battements de cœur, les premiers cycles de synchronisation et les deltas de comptages centraux.

Étape 4 : ne pas nuire — respecter ce dont on hérite

  • DDL en ligne uniquement ; réglages limités à la session ; utilisateurs de base en lecture seule.
  • Les problèmes qui relèvent de l’établissement (exposition réseau de la base, politique de mise à jour des paquets) sont signalés à ses administrateurs, pas modifiés unilatéralement.
  • Montées de version d’OS désactivées ; mises à jour de sécurité automatiques auditées plutôt que supprimées.

Leçons apprises

Chaque leçon provient d’un événement de production précis et daté.

Infrastructure — concevoir pour ce qui existe vraiment

  1. Le goulot d’étranglement n’est presque jamais le logiciel de synchronisation — c’est la base source. Un index manquant transformait chaque cycle en balayage complet de 23 secondes ; une construction d’index en ligne de 30 secondes l’a éliminé. Auditez les index sur chaque site avant la première synchronisation.
  2. Les serveurs nationaux partagés sont chroniquement sursouscrits — plafonnez tout. La croissance mémoire d’un travail d’import sans plafond a un jour affamé un serveur central de 15 Go hébergeant ~25 conteneurs de plusieurs programmes de santé : le noyau a tué des processus, l’accès distant est tombé et l’import a été perdu. Avec un plafond mémoire dur sur le même travail, l’import s’est terminé en 20 minutes au lieu de 6 heures d’agonie suivies d’une mort — et tout échec ne tue plus qu’un conteneur, pas l’hôte.
  3. L’infrastructure des établissements est hostile aux suppositions. Rencontré en pratique : des pannes à répétition de type coupure de courant sur le serveur central (remontées comme constat UPS/infrastructure), un IPv6 cassé qui faisait échouer en silence installations de paquets et builds Docker (correctif : forcer IPv4 dans apt et Docker), un pare-feu de réseau hospitalier qui bloquait les téléchargements de paquets à l’intérieur des builds Docker (six hypothèses avant le bon diagnostic ; le correctif est désormais automatisé dans l’installateur), et des sessions SSH coupées en pleine opération. Lancez chaque travail long dans une session de terminal persistante (tmux) ; concevez chaque opération pour être reprenable.
  4. Des preuves avant des accusations. Quand le serveur central a « planté » pendant un préchargement, l’analyse systématique des journaux du noyau a séparé l’incident en deux événements distincts : l’un réellement causé par notre import sans plafond (corrigé par des plafonds), l’autre un problème d’alimentation du bâtiment qui nous précédait (remonté au propriétaire de l’infrastructure). Problèmes différents, propriétaires différents, correctifs différents — et la confiance pour dire « cette partie n’était pas nous » venait des journaux, pas d’affirmations.
  5. Testez sur la plateforme où vous déployez. Un script de vérification validé sur un portable macOS a échoué sur le serveur Linux à cause d’une différence d’un caractère dans le comportement d’un outil. Le succès sur le portable du développeur ne valide pas le comportement du serveur.

Données — les vraies données de santé sont désordonnées

  1. « DME standard » n’est vrai qu’en grande partie. Entre établissements exploitant le même produit DME, nous avons trouvé : des formats de dumps différents (trois variantes ont cassé notre extracteur l’une après l’autre), des tables dont la colonne d’horodatage rompt la convention du produit (created_date au lieu de date_created — avec une granularité journalière exigeant un rattrapage périodique du watermark), des noms de clés primaires non conventionnels, des colonnes décimales qui semblaient entières, des zéro-dates malformées au-delà de la forme classique, et des octets non UTF-8 dans les dumps. Vérifiez par table, par site ; institutionnalisez chaque constat dans le code et la configuration, pas dans la mémoire de quelqu’un.
  2. Estimez la croissance des données avant de construire quoi que ce soit sur des serveurs contraints. La fonctionnalité de métriques d’ingestion a été conçue en agrégats horaires (~22 Mo/an) après avoir calculé qu’une journalisation brute par lot coûterait ~1,3 Go/an. Le calcul de coin de table a pris dix minutes et a tranché la conception.
  3. Les comptages exacts ne passent pas à l’échelle ; les estimations si. Le tableau de bord comptait au départ chaque ligne de chaque table à chaque rafraîchissement — des balayages complets de plusieurs secondes qui grossissaient avec les données. Le passage aux estimations du catalogue de la base l’a ramené à ~25–75 ms sans perte opérationnelle.

Processus — comment le travail est réellement devenu fiable

  1. Chaque exécution manuelle doit devenir un playbook, puis un script. Le site n° 1 a pris ~5 heures avec beaucoup d’inconnues. Chaque échec a été réinjecté dans un playbook écrit, puis automatisé dans le script de préchargement reprenable et l’installateur. Les sites n° 8 et n° 9 ont été de la routine. Automatisez après deux exécutions manuelles ; convertissez chaque échec en pré-vérification permanente.
  2. Diagnostiquez avant de réessayer. Pendant la saga de l’outil de migration (quatre modes d’échec distincts, dont un outil qui annonçait un succès en migrant zéro table), chaque échec a été analysé jusqu’à la cause racine avec des preuves en lecture seule — journaux de conteneurs, listes de processus des deux bases, mémoire de l’hôte — avant toute action. Chaque échec s’est avéré avoir une cause différente ; des relances à l’aveugle auraient gaspillé des jours.
  3. Savoir abandonner un outil. Après des blocages silencieux répétés, l’outil de migration tiers a été remplacé par un petit chargeur en streaming fait sur mesure en un après-midi. Le coût irrécupérable n’est pas une stratégie.
  4. Des revues calées sur la réalité de production attrapent ce que les suites de tests ne peuvent pas voir. Deux exemples : un bug de fuseau horaire qui aurait décalé chaque intervalle de métriques de deux heures sur des serveurs à l’heure de Kigali (tous les tests passaient sur des machines de dev en UTC), et la charge malveillante de la chaîne d’approvisionnement ci-dessous. Les deux ont été attrapés par la revue, pas par les tests.

Sécurité — dont un incident bien réel

  1. Attaque de la chaîne d’approvisionnement — étude de cas. Le dépôt du projet a subi une véritable compromission de chaîne d’approvisionnement : un chargeur malveillant obfusqué injecté dans un fichier de configuration de gestionnaire de processus, caché au-delà de la colonne 90 derrière des centaines d’espaces hors écran, avec des entrées de dissimulation ajoutées au .gitignore. Parce que les runners exécutent automatiquement le code tiré de ce dépôt, une compromission réussie aurait pu atteindre chaque établissement. Ce qui nous a sauvés, dans l’ordre :

    • La revue de code de routine a signalé le fichier injecté au premier contact.
    • La défense en profondeur : tous les runners s’exécutent dans Docker et n’évaluent jamais le fichier infecté, donc la charge n’a tourné dans aucun établissement de santé.
    • Le scepticisme envers le code « déjà nettoyé » : la charge a survécu à deux commits de nettoyage dédiés en se cachant hors écran ; la suppression finale a été vérifiée par comparaison octet par octet avec une référence saine connue et des balayages d’empreintes sur tout le dépôt — pas par inspection visuelle.

    La leçon pour tout pays adoptant un logiciel de flotte à mise à jour automatique : le dépôt de code est une frontière de sécurité des données patients. Protégez-le en conséquence (contrôle d’accès, portes de revue, vérification d’intégrité), et isolez l’exécution pour qu’un fichier compromis ne puisse pas posséder la flotte.

  2. Les secrets fuient par des fichiers anodins. Une revue a attrapé un jeton d’accès au dépôt, actif, posé dans un fichier texte égaré non couvert par .gitignore — le vecteur exact de re-compromission de l’incident ci-dessus. Il a été révoqué immédiatement et l’historique vérifié propre. Appris aussi : la rotation du secret de signature central invalide tous les jetons de site d’un coup — connaissez le rayon d’impact d’un changement d’authentification avant de le faire.

  3. Les métadonnées sont sensibles dans les systèmes de santé. Un point d’accès de métriques non authentifié exposant les volumes d’ingestion par site et par heure a été signalé en revue : même de « simples comptages agrégés » révèlent les schémas d’activité d’une clinique. Chaque point d’accès mérite une décision d’authentification explicite.

  4. Le moindre privilège s’est payé plusieurs fois. Des utilisateurs en lecture seule dans les établissements signifiaient que le système de synchronisation ne pouvait jamais corrompre les données cliniques ; des schémas et jetons par site signifiaient que la compromission d’un site ne peut pas toucher les données d’un autre ; le pare-feu en couches comptait parce que les plateformes de conteneurs peuvent contourner les pare-feu de l’hôte pour les ports publiés.

Organisationnel — les blocages sont souvent non techniques

  1. Un déploiement à l’échelle nationale est un exercice de coordination. Blocages réels levés : la politique de pare-feu d’un FAI pour l’accès de maintenance à distance (résolue par les canaux ministériels, pas par du code), une migration de serveur par le propriétaire de l’infrastructure qui a cassé en silence toute la connectivité entrante, et un mystérieux certificat TLS qui s’est révélé être le conteneur d’une autre équipe occupant le port d’un serveur partagé. Vérifiez les causes locales avant d’accuser le réseau — et budgétez du temps de relation avec les équipes informatiques, les gestionnaires de données des établissements et les propriétaires d’infrastructure.
  2. Le message de gouvernance fait partie de l’ingénierie. L’autorisation de déploiement par la direction des établissements a été obtenue avec des garanties de sécurité concrètes : isolation conteneurisée, installations épinglées en version, accès en lecture seule, le ministère comme responsable de traitement, et une couche d’anonymisation avant l’analytique. Le cadrage de gouvernance des données a fait partie intégrante de l’adhésion, pas d’une réflexion après coup.

Questions pour votre adaptation pays

Pour les sessions de travail de la semaine 2 et votre feuille de route nationale d’adaptation du HIC (sections 3–4), chaque délégation devrait examiner :

  1. Systèmes sources : quelles bases DME/SIS tournent dans vos établissements ? Leurs tables sont-elles horodatées et indexées ? Qui détient les identifiants des bases ?
  2. Profil de connectivité : quelle disponibilité est réaliste dans vos établissements ? (La conception « au moins une fois » + file locale suppose que la réponse est « médiocre » — si la vôtre est pire, la conception tient toujours ; la file se vide seulement plus lentement.)
  3. Infrastructure centrale : avez-vous un serveur partagé aujourd’hui ? Qui d’autre y tourne ? Quels plafonds mémoire/CPU imposeriez-vous dès le premier jour ?
  4. Gestion de flotte : qui peut se déplacer physiquement dans vos établissements, et à quelle fréquence ? Qu’est-ce que cela implique pour un logiciel à mise à jour automatique et le diagnostic à distance ?
  5. Frontières de confiance : qui contrôle le dépôt de code depuis lequel votre flotte se met à jour ? Qui relit les changements avant qu’ils n’atteignent la production ?
  6. Gouvernance : qui est votre responsable de traitement ? Quelle anonymisation s’applique avant que les analystes ne voient les données ? Quelle autorisation un directeur d’établissement doit-il signer ?