Open-source healthcare integration engine
HL7 v2 · FHIR · DICOM · X12 · CDA — in one static binary
An Apache-2.0 alternative to Mirth Connect. Your existing Mirth JavaScript runs unchanged.
Intel Macs, ARM64 Linux, ARM64 Windows and checksums · Source on GitHub
A lab sends results in HL7 v2. An imaging department speaks DICOM. A payer sends X12. The system receiving all of it wants FHIR. Perfuse sits in the middle, parses each of them properly, transforms what needs transforming, and delivers without losing anything.
It is written in Go, licensed under Apache 2.0, and runs on Linux, macOS and Windows with nothing installed beside it. The web console is compiled into the binary, and everything the configuration files can express can also be done from the browser — a feature reachable only from YAML is treated as a bug.
Coming from Mirth? The migration guide covers E4X, what converts and what refuses.
You do not need a contract, a vendor relationship or anyone's approval to find out whether this works on your messages. Add one destination to your existing Mirth channel that forwards a copy to Perfuse, and give the Perfuse channel a directory as its only destination. Nothing reaches a downstream system, because there is nothing else for it to send to.
# 1. What would stop you, before you commit to anything
perfuse explain mirth-channel-export.xml
# 2. Convert it
perfuse translate mirth-channel-export.xml -o channels/
# 3. Run it beside Mirth on real traffic, delivering nothing to anyone
perfuse run channels/labs.yaml
# 4. Prove the two engines agree, on your own messages
perfuse compare -left-name Mirth -right-name Perfuse mirth-out/ perfuse-out/
perfuse compare pairs the two directories by message control id and reports where they
disagree, grouped by cause — so three thousand messages differing for one reason are one finding,
not three thousand. Message content is withheld by default, because a report is a thing people paste into
tickets.
perfuse explain is worth running first. It tells you what converts cleanly, what converts with
caveats, and what does not convert at all — by name, not as a count. A migration that surprises you in week
three is worse than one that refuses on day one.
| Perfuse | Mirth Connect | |
|---|---|---|
| Memory at rest | 31 MB | 383 MB |
| Runtime | None. One static binary | OpenJDK 17 plus an install |
| Install size | One file | 254 MB plus the JRE |
| Licence | Apache 2.0, and staying that way | Closed source since 4.6 — commercial only |
| Existing Mirth JavaScript | Runs unchanged, including E4X | Native |
| Kafka | Source and destination, keyed for per-patient ordering | No connector |
| Config in the browser | Everything, by policy | Most things |
| Multi-server view | Fleet view, included | A paid feature |
| Production track record | None yet. v0.1.3 | Twenty years, thousands of sites |
That last row is the honest one. Perfuse v0.1.3 has never processed production clinical traffic, and the Windows and ARM64 Linux binaries have never been executed at all. Everything that was verified is recorded, and so is everything that was not. Evaluate it in parallel, against real messages, with the incumbent still delivering — and decide from your own evidence rather than this page.
The full itemised list is in the README, fifteen areas, with the partial ones marked as partial. Every setting is described in the reference manual.
Interoperability claims are cheap. Perfuse's SAML was tested against real Keycloak and real Microsoft Entra, its Mirth import against a real Mirth Connect export, its FHIR output against HAPI, and its DICOM against Orthanc. Two of those found defects in the other party.
It is also measured against other people's data rather than only its own. All 2,912 example files published with the FHIR R4 specification were run through it: 13,723 resources validated, none reported wrongly, and every refusal names the type it cannot read. The HAPI HL7 v2 test corpus — the reference Java implementation's own awkward material — parses completely, 59 of 59.
And the question nobody answers: what happens when it is killed? Terminated with SIGKILL part way through a batch, at five different points, 255 messages were acknowledged and 255 were present downstream. None lost, none duplicated. The numbers for the faster acknowledgement mode, which loses almost everything in flight, are published alongside, because a setting like that should be chosen knowing the size of it.
What was tested, what it found, and what was never run →
Perfuse is developed and maintained by BioDream LLC. Bug reports are welcome as GitHub issues. Code contributions are not accepted — the source has a single maintainer by design, which is worth knowing before you build on it.