Health-data infrastructure in Rust, built on open standards.

FerroHEALTH is the family behind five servers that do one job each and run beside each other: a form builder that a clinician types into, a record server that speaks openEHR, a terminology server that speaks HL7 FHIR, a bridge that carries a record out to FHIR and to the OMOP Common Data Model, and a gateway that queries the record where another organisation holds it. No JVM, no language runtime, no search cluster. Three more are planned around them: who the patient is, how it all runs, and what happens next.

Ferro is ferrum, iron. Rust is an oxide of it, which is the language every one of them is written in.

The products

Five servers, one at a time

Each one is its own repository, its own release train, and its own site. Run the one you need; nothing here requires the others.

FerroCHART

The way in
v0.1.1

An openEHR form builder and renderer. It compiles an operational template into a form, renders it for a clinician, and turns what they type back into a COMPOSITION, so the last mile between a clinical model and a person is not hand-built per form.

  • Fields derived from the Reference Model type at each template node
  • Hand-authored layout in a separate overlay, so a template revision does not destroy it
  • Any openEHR CDR over ITS-REST, never a plugin inside one
  • The round trip to a real CDR runs in CI on every pull request

FerroEHR

The record
v5.0.0

An openEHR Clinical Data Repository. Applications store and query structured health records through a vendor-neutral REST API and the Archetype Query Language, so the record outlives the application that wrote it.

  • The openEHR REST API and AQL, generated from the official machine-readable models
  • Contribution-atomic versioning, attestations and per-version signatures
  • One self-contained binary on PostgreSQL, no JVM in the write path
  • Every conformance claim run against the live server each release

FerroTERM

The meaning
v0.1.8

An HL7 FHIR terminology server. It answers the FHIR terminology API from one static binary over a memory-mapped index built once per release, which is what lets a full SNOMED CT edition run on ordinary hardware.

  • SNOMED CT, LOINC, ICD-10, ICD-11, RxNorm, UCUM and any FHIR CodeSystem; its site carries the full list
  • Several FHIR releases from one binary, each under its own path, and a web viewer in the same binary
  • No JVM, no Elasticsearch, no database to run
  • Every published figure rendered from a committed benchmark record

FerroBRIDGE

The way out
v0.0.10

A bridge from openEHR to two targets: HL7 FHIR, and the OMOP Common Data Model for research. Mappings are specification-conformant YAML validated against published schemas, never hand-coded per resource or per table. The design is written down and the tracker on GitHub is the live record of the build.

  • FHIRconnect for the FHIR side, OMOCL for the OMOP side
  • Its own process beside any CDR it reaches over ITS-REST, never a plugin
  • A FHIR facade that stores nothing, and a batch load that writes typed rows
  • Every decision carries its citation, in the architecture document and on the tracker

FerroFED

Where else the record is
v0.0.11

An openEHR federation gateway. It finds the patient across organisations and queries the record where it lives, and it keeps no second copy that could compete with the source. The design is written down and the tracker on GitHub is the live record of the build.

  • A transparent ITS-REST intermediary: a client sends an ordinary AQL query and never learns it was federated
  • The patient is resolved first, through the index, so no directly identifying identifier travels in a query
  • Standard AQL to each node, the local FerroEHR or a remote CDR, scoped to that node's own EHR id and merged with its provenance
  • Its own process beside the CDR, over the published API and never a plugin

Three more, planned

The five above carry the record. These three will surround it: who the patient is, how it all runs, and what happens next. Each has a name, a registered domain and a repository that opens with its licence and its mark. The badge on a card is read from GitHub when this page is assembled and says when its code last moved. A planned product joins the products above when it publishes a first release.

FerroPIX

Who the patient is

A Master Patient Index. Every organisation issues its own identifiers for the same person, and records move, so one service holds the cross-reference and the record's location and answers the question every other component starts with.

  • IHE PIX and PDQ, and their FHIR forms PIXm and PDQm, so an integrator finds the surface they expect
  • Its own store, outside the CDR, so the clinical record carries little that identifies a person directly
  • The EHR Index of the openEHR Platform Service Model, as a separate server
  • Fed by FerroEHR when an EHR is created or its subject changes, and asked by FerroFED and by the application that opens a record; FerroCHART receives the EHR it is launched with and asks nobody
GitHub ferropix.eu code moved 2026-10-05

FerroSYS

How it all runs

The control plane. It touches no clinical content and carries what every server would otherwise invent for itself: health and readiness across the deployment, telemetry, the event log, notification subscriptions, and how the whole is installed, configured and deployed.

  • Liveness and readiness for every server, in one place
  • One event log and one subscription service, so no component invents its own delivery
  • Telemetry and dashboards for the deployment as a whole
  • Installation, configuration and deployment of the family as one unit
GitHub ferrosys.eu code moved 2026-10-05

FerroTASK

What happens next

The task planning and decision support server. A record says what has happened to a patient; a care pathway says what should happen next, who does it, and what to decide when a result comes in. FerroTASK runs that half, against the record FerroEHR keeps.

  • openEHR Task Planning, from the PROC component: plans for clinical work, with the Decision Language for the rules inside them
  • GDL2, the guideline language of the openEHR CDS component, evaluated against archetype and template paths
  • A client of the CDR: it reads what has happened over AQL and commits the state of each plan back, so it keeps no clinical record of its own
GitHub ferrotask.eu code moved 2026-10-05
How they fit

What calls what

Every arrow is a published specification, so any one of them can be swapped for another implementation of the same standard. Solid is a server you can run today; dashed is planned.

A clinician uses FerroCHART in a browser. FerroCHART expands value sets against FerroTERM and commits compositions to FerroEHR over the openEHR ITS-REST API, which any other application can call directly. FerroEHR validates coded values against FerroTERM. FerroBRIDGE reads FerroEHR over ITS-REST, calls FerroTERM to look up and translate codes, exchanges resources with HL7 FHIR over its FHIR facade in both directions, and writes typed rows into an OMOP Common Data Model database over SQL. Four services frame those four servers, and the three still planned are drawn dashed: FerroEHR feeds FerroPIX, the Master Patient Index, each EHR it creates; applications send FerroFED, the federation gateway, an ordinary AQL query, and it asks the planned FerroPIX where the record is, then dispatches the query to FerroEHR and to other organisations' openEHR CDRs as federation nodes; and FerroSYS, the control plane, spans everything as the band every server reports to; FerroTASK, the task planning and decision support server, reads FerroEHR over ITS-REST and AQL and commits the state of each plan back to it. Each server checks the access tokens it is handed against the deployment's own authorization server, so no FerroHEALTH service holds the key every server depends on. A frame around the eight marks one FerroHEALTH instance serving one tenant; clinicians, applications, FHIR, OMOP and other organisations sit outside it.

The frame is one FerroHEALTH instance serving one tenant: the eight inside are the family, and everything outside is a caller, a target or another organisation. Every product is single-tenant: one instance serves one organisation, and an organisation that serves several runs several instances. Left to right is the order data moves. An arrowhead points at what is called or written to, and the FHIR side carries one at both ends because the bridge reads openEHR out to FHIR and writes FHIR back in. The other three servers call a FHIR terminology server, for three different reasons: FerroCHART to expand the value set behind a coded field so the form can offer the codes it admits, FerroEHR to validate a coded value at commit time, with $expand configured in its place against a server that does not offer $validate-code, and FerroBRIDGE to resolve a display, translate a code and validate one. That seam is the FHIR terminology API, so FerroTERM fills it and so does any other implementation. The facade speaks the FHIR release FHIRconnect's mappings name, and FerroBRIDGE's site says which. OMOP is a database schema, so its edge names no protocol: the OMOCL mappings compile to SQL that writes typed rows into the CDM tables.

The dashed boxes are the three planned products. No authorisation server is drawn: each server is its own SMART App Launch resource server and checks the access tokens it is handed against the deployment's own authorization server, because one central service would hold the signing key every server's access depends on. An application sends FerroFED an ordinary AQL query and never learns it was federated: the gateway asks FerroPIX where the record is (the index FerroEHR feeds each time it creates an EHR), then sends standard AQL to each node, the local FerroEHR or another organisation's CDR, and merges what comes back. An application that opens a record asks FerroPIX the same question; FerroCHART receives the EHR it is launched with and asks nobody. FerroSYS is drawn as a band under everything because every server reports to it and is configured from it, and a line from each would say nothing the band does not. FerroTASK reads the record over AQL and commits the state of each plan back to it, like any other client of the CDR. Which release of each standard a product implements is on that product's site, rendered from its own pins.

What the family holds in common

The same four commitments in every repository

The products differ in what they do. They are built, licensed and evidenced the same way.

The standard is the interface

openEHR for the record, HL7 FHIR for exchange and terminology, OMOP for research. Where a specification publishes a machine-readable model, the code is generated from it, so a specification update is a regeneration.

One licence, no open-core tier

Every product is source-available under the Business Source License 1.1, with each capability in one repository and nothing held back for a paid edition. Free for non-commercial production; other production use needs a commercial licence, and each version becomes Apache 2.0 four years after it is published. What that means for you.

Measured, never typed

Conformance verdicts and performance figures are rendered into these sites from records committed to the repository, and a check fails the build when a page and its records disagree. Every number on these sites comes from a run.

One binary to operate

Each server is a single self-contained Rust binary in a minimal distroless image: no application server, no language runtime to patch, and no garbage-collection pause in the request path. What you deploy is what you read.

Ecosystem

What the five speak

Each product's own site carries the exact versions it implements and the evidence for each claim.

Records

openEHR ITS-REST AQL Reference Model ADL / OPT PostgreSQL

Terminology

HL7 FHIR SNOMED CT LOINC ICD-10 / ICD-11 RxNorm UCUM

Exchange and research

FHIRconnect OMOCL OMOP CDM AMQP S3

Operations

OIDC / Keycloak IHE ATNA audit OpenTelemetry Prometheus Kubernetes / Helm
Quick start

The whole stack, from one file

Nothing to check out. Each command below names a product's latest release, so it runs the same after the next one is cut. Each product's site carries the full installation, the configuration, and the licensing each code system needs.

shell
# FerroCHART's release compose file starts FerroCHART, FerroEHR with its
# PostgreSQL, and FerroTERM. Three products, three licences; the file's
# header says what the demo profile is for.
$ curl -LO https://github.com/FerroHEALTH/FerroCHART/releases/latest/download/compose.yaml
$ FERROCHART_CDR_URL=http://ferroehr:8080/ferroehr/rest/openehr \
  FERROCHART_TERM_URL=http://ferroterm:8080/r4 \
  docker compose --profile demo up
# then open http://localhost:8080

# FerroTERM alone. The image serves UCUM and the registries with no
# configuration, and its viewer is at /ui.
$ docker run --rm -p 8080:8080 ghcr.io/ferrohealth/ferroterm:0.1.8
# then open http://localhost:8080/ui
Status

Where each product is

Three figures per product, read from its repository on GitHub when this page is assembled: the latest release it has published, the day that release went out, and the day its code last moved. None of them is typed by hand, and the page is rebuilt several times a day, so a release cut this morning is here by this afternoon. What a release contains is on the product's own site. A planned product joins this table with its first release; until then its card above says when its code last moved.

Latest release, its date, and the last push per product, read from the GitHub API when this page was assembled.
Product Does Latest release Published Last change Licence
FerroCHART Takes the record down v0.1.1 BUSL-1.1
FerroEHR Stores and queries the record v5.0.0 BUSL-1.1
FerroTERM Answers what a code means v0.1.8 BUSL-1.1
FerroBRIDGE Carries the record onward v0.0.10 BUSL-1.1
FerroFED Queries the record where it lives v0.0.11 BUSL-1.1
Licensing

Do you need a commercial licence?

Every product, planned or released, is source-available under the Business Source License 1.1, which is not an OSI-approved open-source licence. The terms that apply to you are in each repository's own LICENSE, which names its Licensor, its Licensed Work, its Additional Use Grant and its Change Date. This page summarises them for evaluators, and each LICENSE is the authority.

The same answer holds for every product. Each product's LICENSE states it for that product.
What you are doing What you need Why
Reading, building, modifying or redistributing the source Free The licence grants it without a fee and without asking anyone.
Development, testing, evaluation, prototyping Free All non-production use is granted.
Production use for Non-Commercial Purposes Free Personal use, academic or scientific research, teaching, and use by a non-profit organisation or public body that is not in the course of a business, does not deliver a service for payment, and is not for commercial advantage.
A hospital, clinic or care provider running it for its patients Delivering health care, or any other service for payment, is production use outside the grant.
A vendor or integrator, or any company running it in production Production use in the course of a business is outside the grant.
Offering it, or a work derived from it, to third parties as a hosted, managed or embedded service Excluded from the grant in every case, whoever you are.
Selling, sublicensing or otherwise distributing it for a fee, on its own or inside another product Excluded from the grant in every case, whoever you are.

FerroCHART

Licensor Cadasto B.V. The Licensed Work is FerroCHART, each version as published on GitHub.

FerroCHART LICENSE

FerroEHR

Licensor Cadasto B.V. The Licensed Work is FerroEHR, each version as published on GitHub.

FerroEHR LICENSE

FerroTERM

Licensor Cadasto B.V. The Licensed Work is FerroTERM, each version as published on GitHub. The code systems it serves are licensed by their owners, and it ships none of their content.

FerroTERM LICENSE

FerroBRIDGE

Licensor Cadasto B.V. The Licensed Work is FerroBRIDGE, each version as published on GitHub.

FerroBRIDGE LICENSE

FerroPIX

Licensor Cadasto B.V. The Licensed Work is FerroPIX, each version as published on GitHub.

FerroPIX LICENSE

FerroFED

Licensor Cadasto B.V. The Licensed Work is FerroFED, each version as published on GitHub.

FerroFED LICENSE

FerroSYS

Licensor Cadasto B.V. The Licensed Work is FerroSYS, each version as published on GitHub.

FerroSYS LICENSE

FerroTASK

Licensor Cadasto B.V. The Licensed Work is FerroTASK, each version as published on GitHub.

FerroTASK LICENSE

The Change Date. Each version becomes available under the Apache License 2.0, its Change License, four years after that version is published. The change applies per version, so a version you run today gets there on its own date.

The published crates are listed by their product. Some products publish Rust crates on crates.io, some under Apache-2.0 so any Rust project can use them with no licence conversation, and some under the same Business Source License as the server. Which crate carries which licence, and the terms every vendored third-party file keeps, is on each product's own licensing page: FerroCHART's, FerroEHR's, FerroTERM's and FerroBRIDGE's. A crate list typed here would be wrong within a release.

The software licence and the content are two questions. FerroTERM's page answers the one its evaluators arrive with. SNOMED CT is licensed by SNOMED International, LOINC by Regenstrief, ICD by the WHO and RxNorm by the NLM. FerroTERM ships none of that content, and a deployment brings the release it is licensed for.

Getting a commercial licence. Companies and care providers building on these products are wanted here, and the commercial licence is the normal path for them. Cadasto B.V., the Licensor, handles the business side of every product, the commercial licence included: write to info@cadasto.com or use cadasto.com/contact. Technical questions go to the maintainer named in that product's MAINTAINERS.md.

Send the improvements back

The one thing the family asks, and cannot require. A private fork pays for the whole maintenance surface alone; upstreamed, the same work is maintained once for everyone, and a defect found once gets fixed everywhere. That is what clinical software should do.