Migration HL7 v2 vers FHIR : plan par phases pour les hôpitaux et intégrateurs européens
Comment mener une migration HL7 v2 vers FHIR sans casser les circuits cliniques : inventaire des interfaces, coexistence via un moteur d'intégration, façade FHIR, guide HL7 V2-to-FHIR, reprise de l'historique, validation et arrêt des flux v2.
Ala Ben Aicha

Réponse directe
Une migration HL7 v2 vers FHIR est une coexistence par étapes, pas un remplacement en bloc. On laisse tourner les flux v2 événementiels (ADT, ORM, ORU), on les traduit dans un moteur d'intégration en ressources FHIR profilées, on les expose via une façade FHIR aux nouveaux consommateurs, on reprend l'historique avec des écritures conditionnelles idempotentes, et on n'arrête chaque flux v2 qu'une fois ses consommateurs migrés et le rapprochement validé. Le guide d'implémentation HL7 V2-to-FHIR sert de base de correspondance plutôt que de réinventer chaque mapping de champ.
Plan de migration HL7 v2 vers FHIR par phases
| Phase | Objectif | Travaux principaux | Critères de sortie |
|---|---|---|---|
| 0. Inventaire | Savoir ce que l'on migre | Recenser chaque interface : émetteur, destinataire, responsable, version v2, événements déclencheurs, volumes, domaines d'identification, segments Z, usages cliniques en aval | Registre des interfaces validé et jeu d'exemples désidentifiés par flux |
| 1. Coexistence | Traduire sans toucher aux sources | Le moteur d'intégration écoute les flux v2 existants et écrit en FHIR en mode fantôme ; rien ne le lit encore en production | Rapprochement quotidien dans les seuils convenus ; file d'exceptions avec un responsable |
| 2. Façade FHIR | Offrir une API FHIR aux nouveaux consommateurs | API de lecture et de recherche profilées (Patient, Encounter, Observation, DiagnosticReport, ServiceRequest) avec autorisation SMART ou backend | Premier consommateur en production sur FHIR ; la v2 reste la référence |
| 3. Reprise de l'historique | Rendre l'historique disponible en FHIR | Chargement en masse des données passées avec identifiants, Provenance et écritures conditionnelles | Comptages et contrôles par échantillon conformes à la source ; rechargement idempotent |
| 4. Écritures contrôlées | Accepter des entrées FHIR là où c'est nécessaire | Un seul chemin d'écriture de référence, retraduction FHIR vers v2 pour les systèmes existants, prévention des boucles | Retour arrière testé ; aucune commande en double lors des tests de rejeu |
| 5. Arrêt des flux | Supprimer les interfaces v2 une à une | Migrer chaque consommateur vers FHIR ou une interface native, puis couper le flux | Plus aucun consommateur sur le flux ; archives et supervision mises à jour |
Les phases 2 et 3 se chevauchent souvent. L'ordre qui compte : rapprochement, responsabilités et retour arrière doivent exister avant que quoi que ce soit ne dépende du côté FHIR.
Avant la bascule : preuves et retour arrière
Commencez par un inventaire des interfaces : responsables côté émetteur et destinataire, versions des messages, événements déclencheurs, volume quotidien, volume de pointe, domaines d'identification et dépendances cliniques en aval. Validez les règles de correspondance sur des exemples représentatifs et désidentifiés, pas sur un seul message du cas nominal. Le guide des types de messages HL7 et exemples fournit une liste utile des événements que vous risquez de rencontrer.
Pendant la phase fantôme en lecture seule, rapprochez les événements sources des ressources cibles et analysez les enregistrements manquants, les doublons, les corrections tardives et les codes rejetés. Validez par rapport aux profils FHIR retenus et appuyez-vous sur le modèle de compte rendu FHIR R4 pour séparer le contexte du compte rendu des résultats individuels.
Avant d'ouvrir les écritures, définissez un chemin d'écriture de référence unique, la prévention des boucles et une politique de rejeu. La liste de bascule exige des responsables nommés, des seuils d'acceptation, une condition d'arrêt et un retour arrière testé : désactiver le nouvel écrivain, rétablir le routage, rapprocher le stock en attente et rejouer sans dupliquer les commandes.
Le guide des flux radiologie et laboratoire donne des scénarios concrets de demandes et de résultats à intégrer à ces tests. La correspondance terminologique OBX vers Observation constitue le contrat LOINC/SNOMED à l'intérieur du moteur. Si la cible est un serveur FHIR australien, validez avec AU Core R2 plutôt qu'avec des profils R4 Patient et ServiceRequest non contraints.
Pourquoi HL7 v2 reste en place pendant la migration
HL7 v2 est événementiel. À l'admission d'un patient, le système hospitalier envoie un ADT^A01. Une demande part sous forme d'ORM^O01 (les versions v2 plus récentes définissent aussi les messages de demande OML), et les résultats reviennent en ORU^R01. Ces messages circulent en général en MLLP sur des connexions TCP persistantes entre le SIH, le RIS, le SIL et les autres systèmes médico-techniques.
| Type de message | Événement déclencheur | Rôle clinique |
|---|---|---|
| ADT (A01, A02, A03, A04...) | Admission, mutation, sortie | Synchroniser l'identité patient et les données de venue entre tous les systèmes |
| ORM (O01) | Saisie de demande | Déclencher les circuits cliniques : biologie, imagerie, actes |
| ORU (R01) | Résultat d'observation | Renvoyer les résultats : valeurs de biologie, comptes rendus d'imagerie |
| SIU (S12, S14, S15...) | Planification | Création, modification, annulation de rendez-vous |
| DFT (P03) | Transaction financière | Remonter l'activité clinique pour la facturation |
| MDM (T01, T02) | Document médical | Notifier les systèmes de documents cliniques nouveaux ou mis à jour |
Interrompre ces flux peut retarder les soins, casser la facturation et créer des risques pour la sécurité des patients. C'est pourquoi couper la v2 en espérant que tout fonctionne en FHIR le lendemain matin échoue. La transition doit être progressive et menée en parallèle.
L'architecture de coexistence
Un moteur d'intégration se place au centre, souvent Mirth Connect (NextGen Connect), et joue le rôle de traducteur bidirectionnel entre le monde HL7 v2 et le monde FHIR. D'autres moteurs suivent le même schéma ; le comparatif des moteurs d'interface en détaille les compromis.
Legacy Systems Integration Engine Modern Applications
┌──────────────┐ ┌─────────────────┐ ┌──────────────┐
│ EHR │──ADT/ORM/ORU──►│ │──FHIR API──►│ Patient App │
│ (HL7 v2) │◄──ACK──────────│ Mirth Connect │◄─────────────│ (React/RN) │
└──────────────┘ │ │ └──────────────┘
┌──────────────┐ │ ┌───────────┐ │ ┌──────────────┐
│ RIS │──ORM/ORU──────►│ │ Transform │ │──FHIR──────►│ Analytics │
│ (HL7 v2) │◄──ACK──────────│ │ & Route │ │ │ Platform │
└──────────────┘ │ └───────────┘ │ └──────────────┘
┌──────────────┐ │ ┌───────────┐ │ ┌──────────────┐
│ LIS │──ORU──────────►│ │ HL7 ↔ FHIR│ │──Webhook───►│ Clinical │
│ (HL7 v2) │◄──ACK──────────│ │ Mapping │ │ │ Dashboard │
└──────────────┘ │ └───────────┘ │ └──────────────┘
└─────────────────┘
│
┌────▼────┐
│ FHIR │
│ Server │
│ (HAPI) │
└─────────┘
Le serveur FHIR derrière la façade est un choix à part entière (open source, cloud managé ou commercial) ; voir le comparatif des serveurs FHIR pour des critères comme la validation des profils, les abonnements et les opérations en masse.
Comment fonctionne la traduction
Un canal du moteur comporte trois étapes. Le connecteur source reçoit le message v2 brut en MLLP/TCP. Le transformateur analyse les segments et construit les ressources FHIR. Pour un ADT^A01, il lit le PID pour l'identité et le PV1 pour la venue :
HL7 v2 Segment.Field → FHIR Resource.Element
─────────────────────────────────────────────────────────
PID-3 (Patient ID) → Patient.identifier
PID-5 (Patient Name) → Patient.name
PID-7 (Date of Birth) → Patient.birthDate
PID-8 (Sex) → Patient.gender
PID-11 (Address) → Patient.address
PV1-2 (Patient Class) → Encounter.class
PV1-3 (Assigned Location) → Encounter.location
PV1-7 (Attending Doctor) → Encounter.participant
PV1-44 (Admit Date/Time) → Encounter.period.start
OBR-4 (Universal Service) → ServiceRequest.code
OBX-3 (Observation ID) → Observation.code
OBX-5 (Observation Value) → Observation.value
OBX-14 (Date/Time of Obs) → Observation.effectiveDateTime
Le connecteur de destination envoie les ressources au serveur FHIR, en général dans un Bundle de type transaction pour que les ressources issues d'un même message réussissent ou échouent ensemble. Les systèmes existants ignorent que leurs messages sont traduits, ce qui rend l'approche additive.
Prendre le guide HL7 V2-to-FHIR comme base de correspondance
HL7 a publié le guide d'implémentation V2-to-FHIR en version 1.0.0 (STU 1) en octobre 2025, sur la base de FHIR R4. Il fournit des ConceptMaps pour les messages, segments, types de données et vocabulaires, en partant de la v2.9 tout en couvrant des structures plus anciennes encore présentes en production. Il documente aussi les questions que vous rencontrerez de toute façon : correspondance du MSH vers MessageHeader et Provenance, réutilisation d'un même Practitioner cité dans plusieurs segments, champs v2 répétables associés à des éléments FHIR non répétables, et génération des Resource.id.
Considérez-le comme le contrat de départ, puis consignez vos écarts locaux (segments Z, identifiants nationaux, tables de codes du site) comme des surcharges explicites. Le guide couvre le standard de base, pas les profils v2 nationaux ou propres à un éditeur.
Correspondance terminologique
La correspondance structurelle est la partie facile. Les messages HL7 v2 transportent souvent des codes locaux qui n'ont aucun sens hors du système d'origine. Un laboratoire peut envoyer « GLU » pour le glucose là où les consommateurs FHIR attendent le code LOINC 2345-7 (Glucose [Mass/volume] in Serum or Plasma). Maintenez des tables de correspondance partagées :
- Codes de biologie locaux → LOINC pour les observations
- Codes de diagnostic locaux → CIM-10 / SNOMED CT pour les pathologies
- Codes médicaments locaux → ATC / codes nationaux pour les médicaments
Lorsqu'un code manque dans la table, envoyez le message dans une file d'exceptions pour analyse. Ne le supprimez jamais en silence et ne devinez pas la correspondance.
ACK/NACK et fiabilité
Le destinataire de chaque message v2 renvoie un ACK (accepté) ou un acquittement négatif. Dans l'architecture de coexistence :
- Acquittez la source une fois le message stocké durablement dans le moteur, pour éviter que la source n'expire.
- Transformez et livrez de manière asynchrone : correspondance vers FHIR, puis envoi au serveur FHIR.
- Gérez à part les échecs en aval : si le serveur FHIR est indisponible, placez le message dans une file d'erreurs plutôt que de renvoyer un rejet qui ferait boucler la source.
Messages mal formés
Les messages v2 de production sont rarement propres. Prévoyez :
- Fins de ligne incohérentes : certains systèmes utilisent
\nau lieu du\rrequis comme séparateur de segments. Normalisez avant l'analyse. - Encodage des caractères : le MSH-18 déclare le jeu de caractères, mais beaucoup de systèmes l'ignorent. Les noms accentués, courants en Europe, sont alors altérés.
- Segments Z non standard : mappez-les délibérément ou ignorez-les volontairement, et documentez votre choix.
- Champs obligatoires manquants : rejetez ou mettez en quarantaine les enregistrements incomplets, sauf dérivation documentée et validée cliniquement. Ne fabriquez jamais de valeur clinique obligatoire.
Reprendre l'historique dans FHIR
Les flux temps réel ne couvrent que ce qui se passe après la mise en service. Les consommateurs ont généralement aussi besoin de l'historique : venues, résultats et comptes rendus passés. Une migration de données vers FHIR est un traitement par lots, avec des risques différents de ceux du flux temps réel.
- Les identifiants d'abord. Chargez Patient et Encounter avec leurs identifiants métier (system et value pour chaque autorité d'affectation) avant les ressources qui en dépendent. Les fusions et liens issus de l'index patient doivent être résolus, sinon l'historique se rattache à la mauvaise personne.
- Écritures conditionnelles pour l'idempotence. Utilisez la mise à jour ou création conditionnelle sur les identifiants métier, de sorte qu'un nouveau passage mette à jour au lieu de dupliquer.
- Provenance. Tracez l'origine de chaque ressource avec Provenance (système source, date d'extraction, version du mapping). C'est ce qui permet d'expliquer ou de recharger un enregistrement plus tard.
- Mécanique de chargement en masse. La spécification FHIR Bulk Data Access normalise l'export, pas l'import. Les gros volumes passent par des Bundles transaction ou batch, ou par une opération d'import propre au serveur ; testez le débit et l'intégrité référentielle sur une copie à taille réelle.
- Corrections et statuts. L'historique contient des résultats rectifiés ou annulés. Faites correspondre leurs statuts explicitement au lieu de ne charger que la dernière valeur.
Une entrée de reprise d'historique peut ressembler à ceci (données désidentifiées) :
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"fullUrl": "urn:uuid:7f9c2b1e-0d4a-4c3e-9a51-2b8e6f0c1a01",
"resource": {
"resourceType": "Patient",
"identifier": [{ "system": "https://hospital.example.org/mrn", "value": "MRN-EXAMPLE-0001" }],
"name": [{ "family": "DOE", "given": ["JANE"] }],
"birthDate": "1977-04-12"
},
"request": {
"method": "PUT",
"url": "Patient?identifier=https://hospital.example.org/mrn|MRN-EXAMPLE-0001"
}
},
{
"resource": {
"resourceType": "Provenance",
"target": [{ "reference": "urn:uuid:7f9c2b1e-0d4a-4c3e-9a51-2b8e6f0c1a01" }],
"recorded": "2026-10-06T09:00:00Z",
"agent": [{ "who": { "display": "Historical load job v1.3 (example)" } }]
},
"request": { "method": "POST", "url": "Provenance" }
}
]
}
Tests et validation
- Validation des profils : passez chaque ressource générée dans un validateur FHIR, par rapport aux profils sur lesquels vous vous êtes engagé (profils nationaux de base, US Core, AU Core ou les vôtres).
- Non-régression des correspondances : conservez par flux un corpus de messages v2 désidentifiés avec la sortie FHIR attendue, et relancez-le à chaque modification de mapping. Les conversions de test du guide V2-to-FHIR constituent un bon point de départ.
- Rapprochement : comparez chaque jour les volumes par type d'événement et par type de ressource, puis contrôlez des enregistrements champ par champ.
- Revue clinique : faites vérifier par des cliniciens les résultats et comptes rendus affichés, pas seulement le JSON.
- Exercices de panne : indisponibilité du serveur FHIR, messages en double, mises à jour A08 hors séquence, fusions (A40) et demandes annulées.
Quand arrêter un flux v2
N'arrêtez une interface v2 que lorsque tous ses consommateurs ont migré, que le rapprochement est stable depuis une période convenue, que le retour arrière est documenté et que l'accès aux archives est réglé. Arrêtez les flux un par un. Le rôle du moteur passe de traducteur à routeur à mesure que les systèmes parlent FHIR nativement.
Les programmes européens d'interopérabilité rendent les échanges fondés sur des standards de plus en plus pertinents. Vérifiez pour chaque projet les guides d'implémentation applicables, les interfaces nationales et les exigences échelonnées ; l'EHDS ne constitue pas à lui seul une obligation universelle d'exposer une API FHIR donnée. Pour les hôpitaux francophones soumis aux contraintes HPRIM et INS, le guide dédié aux hôpitaux francophones détaille l'inventaire local.
Si vous préparez une migration HL7 v2 et cherchez de l'aide pour l'inventaire des interfaces, les canaux du moteur, la correspondance FHIR ou la reprise de l'historique, consultez les services d'intégration HL7 et FHIR.