Jam EMR v1.0 — 16 clinical modules, FHIR R4 native, MIT licensed. Deploy with one command →
Open source · FHIR R4 native · MIT licensed

The EMR where
every record
is a FHIR resource

Jam EMR is the only open source clinical system that stores patient data natively as FHIR R4 — not translated, not wrapped, not exported. 16 clinical modules, SMART on FHIR v2, DHIS2 national reporting, and a complete insurance revenue cycle. Runs anywhere with one Docker command.

Aligned with HL7 FHIR R4 SMART App Launch v2 HAPI FHIR 7 WHO DHIS2 PEPFAR DATIM IHE ATNA Spring Modulith
188Java source files
128Thymeleaf templates
16Clinical modules
27FHIR R4 resource types
138Audit log call sites
MITOpen source licence
The Jam EMR difference

Built FHIR-first — not FHIR-adapted

Every other open source EMR stores clinical data in a proprietary schema and adds a FHIR facade on top. Jam EMR uses HAPI FHIR JPA as its only database — giving you a fully interoperable system from day one, with zero translation overhead.

HAPI FHIR JPA R4 is the one and only database

Patients are Patient resources. Prescriptions are MedicationRequest resources. Invoices are Invoice resources. Query the standard FHIR API directly at http://localhost:8090/fhir — no custom endpoints, no wrappers, no second database to manage. Any FHIR-capable system integrates from day one.

27 FHIR R4 resource types — all native storage
From Patient and Encounter to Coverage, Claim, ClaimResponse, and AuditEvent — the entire clinical and financial workflow expressed in standard FHIR. Any FHIR-capable system integrates directly. No custom adapter work, ever.
16 Spring Modulith modules — verified every build
Declared allowedDependencies verified by ModularStructureTest on every Maven build. Cycle-free. Feature-flagged with @ConditionalOnProperty — turn off what you don't need for zero startup cost.
Event-driven CDS — modules talk without coupling
7 Spring application events connect modules without imports: VitalsSavedEvent triggers NEWS2, MedicationSavedEvent triggers drug-allergy, CriticalResultEvent surfaces alerts. Each is a typed Java record — impossible to send the wrong payload.
Caffeine-cached dashboard — instant page loads
Nine HAPI queries fire in parallel via CompletableFuture, cached for 60 seconds with a 200-entry maximum. The dashboard is always fast — even on large datasets with thousands of patients and encounters.
iText 7 PDF generation — stored as FHIR DocumentReference
Prescription PDFs and patient summaries generated with iText 7, stored as FHIR DocumentReference resources with LOINC codes 57833-6 and 60591-5. Every printable document is also a queryable FHIR resource.
FHIR Questionnaire forms engine — zero code for custom forms
Build intake forms and screening tools using Questionnaire + QuestionnaireResponse with group nesting, conditional logic, LOINC codes per item, and all FHIR item types. No Java required.
Who deploys Jam EMR

The right fit for every clinical setting

From a single-doctor outpatient clinic to a 200-bed district hospital reporting to a national HMIS — Jam EMR scales with your organisation and grows with your needs.

🏥
Outpatient clinic
Start with the core clinical record and appointment queue. Add billing and insurance when ready — no reinstall, no migration, just flip a feature flag.
  • Patient registry + encounter notes from day one
  • Appointment queue with public TV waiting-room display
  • Prescriptions, LOINC vitals, ICD-10 conditions
  • PDF prescription printing and patient summaries
  • Full FHIR insurance claim cycle when needed
🏨
District hospital
Enable inpatient, paediatrics, radiology, ANC, HIV, and STD modules. SMART on FHIR v2 launches from your existing HIS. NEWS2 and drug-allergy CDS protect patients around the clock.
  • IPD ward rounds with SOAP notes and inline vitals
  • DICOM imaging via Orthanc PACS + OHIF Viewer 3
  • WHO growth charts and EPI vaccination schedules
  • HIV ART programme with PEPFAR reporting ready
  • NEWS2 early warning on every vitals save
🌍
National health programme
Configure DHIS2 data element UIDs once and the reporting module handles the rest. PEPFAR DATIM UIDs pre-configured. Six national HMIS endpoints documented and tested.
  • OPD, malaria, TB, NCD, EPI indicators built in
  • DHIS2 dataValueSet POST or HMIS CSV download
  • PEPFAR TX_CURR, TX_NEW, HTS_TST, HTS_POS
  • Age/sex disaggregation via categoryOptionCombo
  • Multi-facility deployment via Docker Compose
Clinical modules

Everything your clinic needs. Only what you turn on.

Feature flags via @ConditionalOnProperty mean unused modules never start. Configure once in Docker Compose; override any flag per environment with a single environment variable.

Patient Registry + Full Clinical Record
Always active
Complete clinical timeline: encounters with SOAP notes, allergies with severity grading, ICD-10 conditions, LOINC-coded vitals, MedicationRequest prescriptions, CVX-coded immunisations, diagnostic reports, procedures, family history, and documents. MRN, blood group, emergency contacts as FHIR extensions.
PatientEncounterConditionMedicationRequestObservationImmunization
Vitals: 8310-5 temp · 8867-4 HR · 85354-9 BP · 29463-7 weight · 8302-2 height · 2708-6 SpO₂
Appointments + Practice Queue
Always active
7-day calendar view, per-practitioner queues with sequential token assignment, receptionist check-in / call / no-show / undo flow, and a public TV display at /queue/display/ — no auth required, designed for lobby screens. Lifecycle: proposed → booked → arrived → fulfilled → cancelled.
AppointmentQueue tokensTV displayCheck-in flow
Billing + Full Insurance Revenue Cycle
emr.modules.billing · emr.modules.insurance
FHIR-native revenue cycle, three phases complete. Phase 1: Coverage + InsurancePlan catalogue, primary/secondary ordering. Phase 2: Claim generation from Invoice — pre-tax lines, duplicate-claim guard, draft → submit → void. Phase 3: ClaimResponse adjudication, automatic Invoice reconciliation with gap invoicing.
CoverageInsurancePlanClaimClaimResponseInvoice
5 claim-tracking extensions on Invoice keep billing and insurance modules fully independent
Inpatient — Beds, Ward Rounds, Discharge
emr.modules.ipd
Ward dashboard with live bed-status grid, bed management (FHIR Location), admissions (EpisodeOfCare), SOAP ward-round notes with inline vitals, patient transfer, discharge with disposition coding. Bed lifecycle: Available → Occupied → Housekeeping → Available.
EpisodeOfCareLocationSOAP roundsDischarge
Clinical Decision Support
emr.modules.cds
Drug-allergy checker with three-level matching (exact SNOMED → display overlap → drug class cross-reactivity). Fires asynchronously on every prescription save. NEWS2 (National Early Warning Score 2) fires on every vitals save, stored as FHIR RiskAssessment. Both create persistent DetectedIssue alerts on the patient chart.
DetectedIssueRiskAssessmentNEWS2 (0–20)3-level allergy
HIV / ART Programme
emr.modules.hiv
Complete ART programme: enrolment (EpisodeOfCare), viral load and CD4 trend observations, WHO clinical staging, regimen prescribing and switching. All routes require ROLE_HIV_PROVIDER via @PreAuthorize — enforced at the service layer so protection holds in every security mode.
ART regimensViral load trendsWHO stagingRole-gated
Paediatrics + WHO Growth Monitoring
emr.modules.paediatrics
Age guard on registration. WHO growth monitoring with z-scores: WAZ, HAZ, WHZ, MUAC. Interactive Chart.js growth charts. WHO EPI vaccination schedule with due/overdue/given status per antigen. Weight-based dosing calculator with dose capping and age-band validation.
WAZ/HAZ/WHZ z-scoresWHO EPI scheduleDosing calculator
National Reporting + DHIS2 / DATIM Export
Always active
FHIR-to-analytics ETL (nightly 2 AM or manual trigger), 7 operational reports. Aggregates OPD, malaria (ICD-10 B50–B54), TB (A15–A19), NCDs (I10–I15, E10–E14), and EPI vaccine doses by CVX code. Exports as DHIS2 dataValueSet JSON, PEPFAR DATIM, or HMIS CSV flat file.
DHIS2 dataValueSetPEPFAR DATIMHMIS CSV7 reports
TX_CURR · TX_NEW · HTS_TST · HTS_POS — PEPFAR MER UIDs pre-configured
Radiology + PACS Integration
emr.modules.imaging
FHIR ImagingStudy resources, radiology order workflow, Orthanc PACS integration via DICOMweb (WADO-RS, STOW-RS, QIDO-RS), and OHIF Viewer 3 launch links for browser-based DICOM viewing — no separate viewer login required.
ImagingStudyServiceRequestOrthanc PACSOHIF Viewer 3
ANC · Gynaecology · Sexual Health
Three flags — deploy only what applies
ANC follows WHO 8-contact model with gestational age, fundal height, FHR, urinalysis, and PMTCT status. Gynaecology covers Pap smear with Bethesda classification. STD module: FHIR security labels, Cache-Control: no-store on all /std/** responses, ICD-10 A50–A64 hidden from general lists.
WHO ANC 8-contactBethesdaFHIR security labels
Dynamic Forms + Questionnaires
emr.modules.forms
Build custom clinical forms using FHIR Questionnaire — intake assessments, screening tools, consent forms. All FHIR item types: string, integer, decimal, boolean, choice, group with nested items, enableWhen conditional logic, LOINC linkId per item. Responses stored as QuestionnaireResponse resources.
QuestionnaireQuestionnaireResponseenableWhen
SMART on FHIR App Launch v2.0
emr.security.mode=smart
Complete SMART App Launch v2.0: PKCE S256 with 96-byte verifier, RS256 id_token validation via Nimbus JOSE+JWT against RemoteJWKSet, proactive token refresh 120s before expiry, session fixation protection. Launches from Epic, Cerner, and any SMART v2-compliant EHR.
PKCE S256RS256 JWTToken refreshEpic · Cerner
How it works

From patient registration to national report — every step in FHIR

Jam EMR's clinical workflow is a continuous chain of FHIR resources. Every action creates or updates a resource that is immediately queryable, auditable, and interoperable.

1
Patient arrives — a FHIR Patient resource is created
The receptionist registers the patient. Jam EMR creates a Patient resource in HAPI FHIR JPA with demographics, MRN as identifier, blood group and emergency contacts as extensions. PatientCreatedEvent fires. The patient is instantly searchable by name, MRN, phone, or any FHIR search parameter.
FHIR: Patient · Identifier · AuditEvent
2
Appointment booked — token assigned, queue updated live
An Appointment resource is created and a queue token assigned. Check-in sets status to arrived. The practitioner calls the patient — calledAt recorded. The TV display at /queue/display/ updates in real time — no auth required, designed for lobby screens.
FHIR: Appointment · status lifecycle
3
Encounter opened — all clinical records attach to it
The doctor opens an Encounter (class: AMB / IMP / EMER). All clinical actions — vitals, conditions, prescriptions, investigations — reference this encounter. EncounterCreatedEvent fires. The encounter timeline is the canonical record for the visit.
FHIR: Encounter · Condition · Observation
4
Vitals saved — NEWS2 fires automatically, no trigger needed
Vitals stored as FHIR Observation resources with standard LOINC codes. VitalsSavedEvent fires asynchronously. News2Calculator computes the NEWS2 score (0–20) and stores a RiskAssessment. Elevated scores log a CDS audit event. The practitioner sees the score on next page load.
FHIR: Observation · RiskAssessment · AuditEvent
5
Prescription written — drug-allergy check runs immediately
A MedicationRequest is created. MedicationSavedEvent fires. DrugAllergyChecker runs three-level matching: exact SNOMED → display name overlap → drug class cross-reactivity. A DetectedIssue is stored and shown as a banner on the chart if a conflict is found.
FHIR: MedicationRequest · DetectedIssue · AllergyIntolerance
6
Invoice generated — insurance claim submitted and reconciled
Billing generates a FHIR Invoice with ChargeItemDefinition line items. A Claim is generated with pre-tax item[].net values. The insurer's remittance creates a ClaimResponse. reconcileInvoice() updates patientOwes and marks the invoice balanced. Gap invoicing keeps the invoice open if the patient owes a remainder.
FHIR: Invoice · Coverage · Claim · ClaimResponse
7
ETL runs — national indicators submitted to DHIS2 automatically
The ETL reads FHIR resources and populates the analytics database. NationalIndicatorService aggregates OPD, malaria (B50–B54), TB, EPI doses, and PEPFAR HIV indicators. Dhis2ExportService POSTs a dataValueSet JSON to your DHIS2 instance, or produces a CSV for manual upload.
Reporting: DHIS2 dataValueSet · DATIM · HMIS CSV
Technical architecture

Engineered for correctness, built to last

Every design decision in Jam EMR has a documented reason. Here are the decisions that matter most in a clinical system.

FHIR storage layer HAPI FHIR 7

  • HAPI FHIR JPA R4 backed by PostgreSQL 15-alpine
  • Full FHIR search indexing on every resource type
  • Version history preserved — no hard deletes in clinical workflow
  • Connection pool: max 10/route, 50 total, 30s connect / 60s socket timeout
  • Reporting ETL writes to isolated reporting schema via @Qualifier("reportingTx")
  • Secondary EntityManagerFactory — reporting DB fully isolated from HAPI

Spring Modulith Build-time verified

  • 16 packages each with package-info.java declaring allowedDependencies
  • ModularStructureTest.verifiesModularStructure() fails the build on any violation
  • Internal DTOs in internal/ packages — inaccessible cross-module
  • Cross-module communication via Spring application events only
  • @ApplicationModuleListener on CDS and contact-tracing listeners
  • @ConditionalOnProperty on every feature-flagged module's beans

Insurance revenue cycle FHIR-native

  • Coverage.payor[] → Organization (insurer) — no separate insurer entity
  • Claim.item[].net = pre-tax subtotal (insurers don't pay VAT/GST)
  • 5 claim-tracking extensions on Invoice keep billing and insurance modules decoupled
  • ClaimResponseService.reconcileInvoice() is idempotent — safe to call twice
  • Gap invoicing: if patientOwes > 0, Invoice stays issued for cash collection
  • Coverage.class[] uses standard coverage-class CodeSystem for plan/group

Security hardening Production-ready

  • HTTP headers: CSP, X-Frame-Options: DENY, Referrer-Policy: strict-origin, Permissions-Policy
  • HSTS in smart mode (requires HTTPS); skipped in development to avoid breaking HTTP
  • Global @ControllerAdvice strips HAPI URLs, JDBC strings, stack traces from browser
  • Patient deactivate is POST (CSRF-protected) — prevents link-based data loss
  • Caffeine cache: 60s TTL, max 200 entries — no unbounded memory growth
  • Actuator: only health and info exposed — env never accessible

7 clinical application events — modules that talk without coupling

CriticalResultEvent, VitalsSavedEvent (triggers NEWS2), MedicationSavedEvent (triggers drug-allergy), StdDiagnosisConfirmedEvent (triggers contact-tracing), PregnancyRegisteredEvent, EncounterCreatedEvent, PatientCreatedEvent. Each is a typed Java record — no stringly-typed payloads, no runtime surprises.

VitalsSavedEvent
News2Calculator
RiskAssessment (FHIR)
MedicationSavedEvent
DrugAllergyChecker
DetectedIssue (FHIR)
StdDiagnosisConfirmedEvent
ContactTracingService
RelatedPerson (FHIR)
Technology stack

Proven, well-supported, battle-tested

Every dependency is a deliberate choice — maintained by large organisations, widely deployed in healthcare, and stable enough to build a clinical system on.

Runtime
Java 17
LTS · Eclipse Temurin
Long-term support. Runs on any JVM — bare metal, Docker, or cloud VM.
Framework
Spring Boot
3.2.0
Auto-configuration, dependency injection, Security, Scheduling. The industry standard for Java services.
FHIR engine
HAPI FHIR
7.0.0 · JPA R4
The dominant open-source FHIR implementation on the JVM. Used in Epic integrations worldwide.
Database
PostgreSQL
15-alpine (Docker)
HAPI FHIR JPA's primary store. H2 in-memory for development without Docker.
Architecture
Spring Modulith
1.1.0
Build-time boundary verification. Module allowedDependencies enforced on every Maven build.
Templates
Thymeleaf
3.x · 128 templates
Server-side rendering. Works without JavaScript. Accessible, SEO-friendly clinical UI.
PDF generation
iText 7
7.2.5
Prescriptions, summaries, invoices — stored as FHIR DocumentReference with LOINC codes.
SMART / JWT
Nimbus JOSE+JWT
9.40
RS256 id_token validation against RemoteJWKSet. Full PKCE and nonce verification.
Cache
Caffeine
3.x · 60s TTL
Bounded cache with TTL eviction. Prevents unbounded memory growth on high-traffic deployments.
PACS
Orthanc
latest · DICOMweb
Open-source DICOM server. WADO-RS, STOW-RS, QIDO-RS. Paired with OHIF Viewer 3.
DICOM Viewer
OHIF Viewer 3
React · DICOMweb
Browser-based DICOM viewer. No plugin, no install. Launched directly from radiology orders.
Reporting
DHIS2 Web API
v2.36+ · dataValueSet
Aggregated indicators to national HMIS. Any DHIS2 v2.36+ instance worldwide.
Clinical decision support

Safety checks that run before harm reaches the patient

Jam EMR's CDS layer is embedded in the prescription and vitals workflow — not bolted on as an afterthought. Two systems fire automatically with zero configuration required.

Drug-allergy matching levels
Level 1: exact SNOMED code. Level 2: display name word overlap. Level 3: drug class cross-reactivity — prescribing amoxicillin is blocked when a penicillin allergy is recorded. Fires asynchronously on every MedicationRequest save. Persistent FHIR DetectedIssue alerts surface on the chart.
0–20
NEWS2 early warning score
NHS National Early Warning Score 2 calculated on every vitals save. Scores respiratory rate, SpO₂, systolic BP, heart rate, temperature, and consciousness. Elevated scores log a CDS audit event and store a FHIR RiskAssessment. Zero configuration — activates automatically on any vital sign save.
138
Audit log call sites — every action recorded
Every CREATE, UPDATE, DELETE, and CDS-ALERT across all 16 modules written as a FHIR AuditEvent asynchronously via @Async("taskExecutor"). Audit writes never block the HTTP request thread. If HAPI is slow, clinical operations complete normally.
Quick start

A fully configured clinical environment in under two minutes

Docker Compose launches HAPI FHIR JPA, Orthanc PACS, OHIF Viewer 3, and the Jam EMR app — all networked, all configured, all ready. No FHIR expertise required to get started.

Terminal
# Clone and start git clone https://github.com/vedpr625/FHIR-Electronic-Medical-Records cd FHIR-Electronic-Medical-Records docker compose up -d # Wait ~45s for HAPI to initialise, then open open http://localhost:8080 # Jam EMR open http://localhost:8090/fhir # HAPI FHIR R4 API open http://localhost:8042 # Orthanc PACS open http://localhost:3000 # OHIF Viewer 3 # Configure via environment variables — no config files to edit FHIR_SERVER_URL=http://your-hapi/fhir EMR_MODULES_HIV=true DHIS2_URL=https://hmis.health.gov.ke SPRING_SECURITY_USER_PASSWORD=your-secure-password
Jam EMR
:8080 · Spring Boot 3.2 · Java 17
HAPI FHIR JPA R4
:8090 · PostgreSQL 15-alpine
Orthanc PACS
:8042 · DICOMweb · DICOM :4242
OHIF Viewer 3
:3000 · React · WADO-RS
01 — CONFIGURE
Set environment variables
Override FHIR_SERVER_URL, security credentials, and DHIS2 UID mappings via env vars. No YAML to edit.
02 — ACTIVATE
Enable the modules you need
EMR_MODULES_HIV=true, EMR_MODULES_PAEDIATRICS=true per deployment. Unused modules add zero startup cost.
03 — REPORT
Connect to national HMIS
Set DHIS2_URL and your facility's data element UIDs. OPD, malaria, TB, EPI, and HIV PEPFAR indicators automatically.
04 — INTEGRATE
Launch from any SMART EHR
Set emr.security.mode=smart and register with Epic, Cerner, or any SMART v2-compliant EHR. PKCE launch flow in under 10 minutes.
SMART on FHIR

Full SMART App Launch v2.0 — every control, no shortcuts

Jam EMR implements the complete SMART App Launch Framework v2.0. Not a subset, not "mostly compliant." Every PKCE parameter, every RS256 claim, every token-refresh rule — implemented to spec.

1
EHR initiates the launch
Epic, Cerner, or any SMART EHR calls GET /smart/launch?iss=&launch=. The EMR validates ISS against the SMART discovery document (cached per-ISS), builds a PKCE pair with a 96-byte cryptographically random verifier and S256 challenge, then redirects to the EHR authorize endpoint with a state nonce for CSRF protection.
2
Identity verified with RS256 — no trust-on-first-use
After code exchange, the id_token is validated using Nimbus JOSE+JWT DefaultJWTProcessor with RemoteJWKSet against the EHR's JWKS endpoint. Signature, expiry, issuer, audience, and nonce all verified. Full RFC 7517 key rotation support — no key pinning that breaks on EHR certificate renewals.
3
Session secured, tokens proactively refreshed
SmartLaunchContext stored in HTTP session with session-fixation protection. SmartSecurityFilter populates the Spring SecurityContext on every request. TokenRefreshFilter proactively refreshes tokens on /api/** routes 120 seconds before expiry — no expired-token errors surfacing to clinicians mid-workflow.
PKCE
96-byte verifier
S256 challenge · RFC 7636
ID token
RS256 · RemoteJWKSet
Nimbus DefaultJWTProcessor
Token refresh
120s proactive
Before expiry · /api/** routes
CSRF
Double Submit Cookie
CookieCsrfTokenRepository
Session
Fixation protection
changeSessionId() on auth
Security mode
3-mode config
development · smart · basic
Security & compliance

Production-hardened — every control is explicit and documented

Clinical systems handle the most sensitive personal data that exists. Every security control in Jam EMR is deliberate — because "it probably works" is not acceptable in healthcare.

HTTP security headers — all modes
CSP, X-Frame-Options: DENY, Referrer-Policy: strict-origin, Permissions-Policy (camera, mic, geolocation off). Applied via applySecurityHeaders() in every security mode.
HSTS — smart mode only
max-age=31536000, includeSubDomains. Only activated with emr.security.mode=smart — skipped in development so plain-HTTP local setups work normally.
Global exception handler — no stack traces in browser
@ControllerAdvice catches every unhandled exception. HAPI URLs, JDBC connection strings, and internal paths are stripped by sanitise() before any message reaches the browser.
138 FHIR AuditEvent call sites — IHE ATNA aligned
Every CREATE, UPDATE, DELETE, and CDS-ALERT across all 16 modules written as a FHIR AuditEvent asynchronously. Audit writes never block the HTTP request thread.
@PreAuthorize at the service layer, not just controllers
HIV (ROLE_HIV_PROVIDER) and STD (ROLE_STD_PROVIDER) enforcement on service methods — protection holds in every security mode including development.
STD privacy stack — FHIR labels + Cache-Control: no-store
Sexual health resources carry FHIR security labels. All /std/** responses set Cache-Control: no-store, Pragma: no-cache. ICD-10 A50–A64 filtered from general condition lists.
Patient deactivation — POST only, never GET
POST /patients/deactivate/{id} sets Patient.active=false (CSRF-protected, preserves full record history). The GET delete URL redirects with an error — no link-based or crawled data loss.
Caffeine cache — 60s TTL, 200 entries max
Replaces ConcurrentMapCacheManager which had no eviction. Bounded cache prevents unbounded memory growth on high-traffic deployments with thousands of daily dashboard loads.
Actuator — only health + info endpoints exposed
Spring Boot Actuator exposes /actuator/health (Docker/K8s probe) and /actuator/info only. /actuator/env, /actuator/beans, and all introspection endpoints are never accessible.
National alignment

Built for health systems, not just individual clinics

Configure your country's DHIS2 UID mappings once and the reporting module handles the rest. PEPFAR/DATIM UIDs are pre-configured across all deployments.

🇰🇪 Kenya — KHIS
Kenya Health Information System · DHIS2-based · OPD, maternal, immunisation
Set DHIS2_URL=https://hiskenya.org
OPD indicatorsMalaria B50–B54EPI antigens
🇺🇬 Uganda — DHIS2
Ministry of Health DHIS2 · District-level facility reporting · HIV care
Set DHIS2_URL=https://dhis.health.go.ug
HIV programmeTB casesOPD attendance
🌍 PEPFAR / DATIM
PEPFAR MER indicators · 20+ countries · Standardised UIDs across all programs
Pre-configured — no setup needed
TX_CURRTX_NEWHTS_TSTHTS_POS
🇮🇳 India — ABDM / NHM
Ayushman Bharat Digital Mission · FHIR-based exchange · NHM HMIS
HMIS CSV export compatible
FHIR ABDM profilesOPD data
🇬🇭 Ghana — DHIMS2
Ghana Health Service · Disease surveillance · EPI programme
Set DHIS2_URL=https://dhims.chimiphgh.org
Disease burdenEPI coverage
🌐 Any DHIS2 country
80+ countries run national DHIS2 · Configure with your data element UIDs
Any DHIS2 v2.36+ Web API supported
dataValueSet POSTAge/sex disaggJSON + CSV
Comparison

Where Jam EMR stands out

Jam EMR leads in three areas no other open source EMR addresses together: native FHIR storage, automatic CDS that fires without configuration, and a complete insurance revenue cycle expressed entirely in FHIR resources.

FeatureJam EMROpenMRS 3.xBahmniGNU HealthOSCAR EMR
FHIR R4 as native storage✓ Native HAPI JPAAdapter
SMART App Launch v2.0 (PKCE + RS256)✓ Full v2.0PartialPartial
Drug-allergy CDS at prescribing (auto)✓ 3-level matchPharmacy only
NEWS2 early warning score (automatic)✓ Every vitals save
FHIR insurance claim lifecycle (3 phases)✓ Coverage → Claim → ClaimResponseNon-FHIRPartial✓ (non-FHIR)
DHIS2 / DATIM national reporting✓ Built-inModuleModuleExport only
STD privacy stack (FHIR security labels)✓ Labels + no-store headers
WHO growth charts + z-scores✓ WAZ / HAZ / WHZModulePartial
Orthanc PACS + OHIF Viewer 3✓ In Docker ComposeModule✓ dcm4cheePartialPartial
Spring Modulith architecture (build-time)✓ Verified every build
Single command deploy (docker compose up)PartialPartial
Open source licenceMITMPL 2.0LGPL / MPLGPL 3.0GPL 2.0
188Java files · no generated code
16Modulith modules · verified
27FHIR R4 resource types
7Spring application events
3Insurance phases complete
Frequently asked

Questions from evaluators

Why use FHIR R4 as the storage layer rather than just an export format?
Other EMRs store data in a proprietary schema and generate FHIR on demand — meaning FHIR queries are slow, the schema drifts from the spec over time, and external systems need custom integration work. Jam EMR stores directly as FHIR resources in HAPI FHIR JPA. Any FHIR-capable system — Epic, Cerner, a public health dashboard, a mobile app — can query http://localhost:8090/fhir with standard FHIR search parameters from day one. No custom adapter work, ever.
How does the insurance revenue cycle work end-to-end?
Phase 1: Record the patient's Coverage (insurer, policy number, copay/deductible). Phase 2: Generate a Claim from the issued Invoice — pre-tax line items map to Claim.item[], 5 claim-tracking extensions are written back to the Invoice so billing and insurance modules stay independent. Phase 3: When the insurer's Remittance Advice arrives, record a ClaimResponse. Click "Reconcile Invoice" to set insuranceCovered, update patientOwes, and mark the invoice balanced. If a gap remains, the invoice stays issued so billing can collect the patient's portion normally.
What does DHIS2 reporting require to configure?
Four environment variables: DHIS2_URL, DHIS2_USERNAME, DHIS2_PASSWORD, and DHIS2_ORG_UNIT (your facility's org unit UID). Then one property per indicator mapping your data element UIDs. PEPFAR DATIM UIDs (TX_CURR, TX_NEW, HTS_TST, HTS_POS) are pre-configured and don't vary by country. In download-only mode you still get a JSON dataValueSet and HMIS CSV for manual upload.
Can I add custom modules without forking?
Yes. Create com.emr.fhir.yourmodule, add a package-info.java with @ApplicationModule(allowedDependencies = {"core"}), annotate your service with @ConditionalOnProperty, and add the flag to Docker Compose. The Modulith architecture test verifies your boundary declarations on every build. Subscribe to existing clinical events without coupling to any other module's internal classes.
Can Jam EMR run without internet access?
Completely. Docker Compose includes a local HAPI FHIR JPA instance backed by PostgreSQL — no external FHIR server required. All clinical operations work locally with no network access. The only internet-dependent features are SMART on FHIR (requires the EHR's JWKS endpoint) and DHIS2 submission (requires the national HMIS URL). Both are optional and fully skippable in air-gapped environments.
Support tiers

Open source. Professionally supported.

Community support is free and permanent. Structured support is available for clinics and governments that need deployment guarantees.

Community
Free forever
  • GitHub Issues + Discussions
  • Full documentation
  • All releases · MIT licence
Standard
Contact us
  • Email support
  • 2-business-day SLA
  • Security patch notifications
  • Configuration guidance
Recommended
Enterprise
Contact us
  • Phone + email support
  • 4-hour SLA
  • 24-hour security patches
  • Custom feature roadmap
  • On-premises deployment
Government
Contact us
  • Custom SLA · 24/7 coverage
  • National DHIS2/DATIM alignment
  • Technical team training
  • Procurement documentation