Helios FHIR Server (HFS)
A high-performance FHIR server built in Rust.
An open test server is available at https://hfs.heliossoftware.com/ for experimentation and evaluation.
Features
- Full FHIR RESTful API support
- Multiple FHIR version support
- Pluggable storage backends (SQLite, PostgreSQL, MongoDB)
- Content negotiation (JSON)
- Conditional operations with ETag support
- Multi-tenant support via X-Tenant-ID header
- CORS support
Installation
From Source
# Clone the repository
# Build with default features (R4 + SQLite)
# Build with all FHIR versions
Usage
Running the Server
# Run with default settings (R4, SQLite, port 8080)
# Specify a different port
# Use an in-memory database
# Enable debug logging
Command Line Options
Usage: hfs [OPTIONS]
Options:
--port <PORT> Server port [env: HFS_SERVER_PORT=] [default: 8080]
--host <HOST> Host to bind [env: HFS_SERVER_HOST=] [default: 127.0.0.1]
--log-level <LOG_LEVEL> Log level (error, warn, info, debug, trace)
[env: HFS_LOG_LEVEL=] [default: info]
--database-url <URL> Database connection URL [env: DATABASE_URL=]
--data-dir <PATH> Path to FHIR data directory containing search parameter
definitions [env: HFS_DATA_DIR=] [default: ./data]
--max-body-size <BYTES> Maximum request body size [env: HFS_MAX_BODY_SIZE=]
[default: 10485760]
--request-timeout <SECS> Request timeout in seconds [env: HFS_REQUEST_TIMEOUT=]
[default: 30]
--enable-cors Enable CORS [env: HFS_ENABLE_CORS=] [default: true]
--cors-origins <ORIGINS> Allowed CORS origins [env: HFS_CORS_ORIGINS=] [default: *]
-h, --help Print help
-V, --version Print version
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
HFS_SERVER_PORT |
8080 | Server port |
HFS_SERVER_HOST |
127.0.0.1 | Host to bind |
HFS_LOG_LEVEL |
info | Log level (error, warn, info, debug, trace) |
DATABASE_URL |
fhir.db | Database connection string |
HFS_DATA_DIR |
./data | Path to FHIR data directory (search parameters) |
HFS_MAX_BODY_SIZE |
10485760 | Max request body size (bytes; applies to the decompressed body for compressed requests) |
HFS_REQUEST_TIMEOUT |
30 | Request timeout (seconds) |
HFS_ENABLE_CORS |
true | Enable CORS |
HFS_CORS_ORIGINS |
* | Allowed CORS origins |
HFS_CORS_METHODS |
GET,POST,PUT,DELETE,OPTIONS | Allowed HTTP methods |
HFS_CORS_HEADERS |
Content-Type,Authorization,X-Requested-With | Allowed headers |
HFS_DEFAULT_TENANT |
default | Default tenant ID |
HFS_TERMINOLOGY_SERVER |
(none) | Terminology server URL for :in/:not-in modifiers and FHIRPath memberOf()/subsumes() |
HFS_COMPOSITE_SYNC_MODE |
asynchronous |
Composite-store write sync mode for ES-backed backends (sqlite-elasticsearch, postgres-elasticsearch, mongodb-elasticsearch, s3-elasticsearch). One of asynchronous, synchronous, hybrid. With asynchronous (default) the write returns as soon as the primary commits and the search backend is updated on a background worker — lowest latency, but a follow-up search can race the indexing. Use synchronous when callers need read-your-write semantics (e.g. integration tests, bulk-load flows that immediately search). Ignored when the storage backend has no search secondary. |
FHIR Version Support
Build with specific FHIR versions using feature flags:
# R4 only (default)
# R5 only
# Multiple versions
Database Backends
SQLite (Default)
# Run with file-based database
# Run with in-memory database
PostgreSQL
MongoDB
API Endpoints
| Interaction | Method | URL |
|---|---|---|
| capabilities | GET | /metadata |
| read | GET | /[type]/[id] |
| vread | GET | /[type]/[id]/_history/[vid] |
| update | PUT | /[type]/[id] |
| patch | PATCH | /[type]/[id] |
| delete | DELETE | /[type]/[id] |
| create | POST | /[type] |
| search | GET/POST | /[type]?params or /[type]/_search |
| history (instance) | GET | /[type]/[id]/_history |
| history (type) | GET | /[type]/_history |
| history (system) | GET | /_history |
| batch/transaction | POST | / |
| health | GET | /health |
Examples
Create a Patient
Read a Patient
Search for Patients
Get CapabilityStatement
Batch and Transaction Support
HFS supports both batch and transaction bundles for processing multiple operations in a single request.
Note: Transaction bundles require ACID transaction support. The default SQLite backend fully supports transactions. If using other backends, check the capability matrix in the persistence crate documentation.
Transaction Bundle (Atomic)
All operations succeed or all fail. Entries are processed in FHIR-specified order: DELETE → POST → PUT → GET.
The urn:uuid:patient-1 reference is automatically resolved to the actual Patient ID after creation.
Batch Bundle (Independent)
Each operation is processed independently; failures don't affect other entries.
Current Limitations
The following FHIR bundle features are not yet implemented:
- Conditional reference resolution (
Patient?identifier=12345) - PATCH method in bundles
- Prefer header handling (
return=minimal, etc.)
Search Parameter Configuration
HFS loads FHIR SearchParameter definitions from JSON bundle files to enable comprehensive search functionality. By default, these files are expected in a data/ directory relative to the working directory or executable.
Data Directory Structure
data/
├── search-parameters-r4.json # FHIR R4 SearchParameters (HL7 spec)
├── search-parameters-r4b.json # FHIR R4B SearchParameters (HL7 spec)
├── search-parameters-r5.json # FHIR R5 SearchParameters (HL7 spec)
├── search-parameters-r6.json # FHIR R6 SearchParameters (auto-downloaded at build time)
└── *.json # Custom SearchParameter files (see below)
Search Parameter Loading
On startup, HFS loads SearchParameters in this order:
- Minimal fallback - Built-in
_id,_lastUpdated,_tag,_profile,_security(always available) - Spec file - Loads from the appropriate
search-parameters-*.jsonbased on configured FHIR version - Custom files - Loads any additional
.jsonfiles in the data directory (not matchingsearch-parameters-*.json) - Stored parameters - Loads any custom SearchParameters POSTed to the server
Custom SearchParameter Files
You can add custom SearchParameters by placing JSON files in the data directory. Each file can contain:
- A single SearchParameter resource
- An array of SearchParameter resources
- A FHIR Bundle containing SearchParameter resources
Example custom SearchParameter file (data/custom-search-params.json):
Or as a Bundle:
Custom Data Directory
Specify a custom location for the data files:
# Via command line
# Via environment variable
HFS_DATA_DIR=/opt/hfs/data
If the spec file is missing, HFS logs a warning and continues with minimal fallback parameters. This ensures the server can start even without the full spec files, though search functionality will be limited.
R6 Automatic Download
When building with the R6 feature enabled, the search-parameters-r6.json file is automatically downloaded from the HL7 build server during compilation. The download is skipped if:
- The file already exists and is less than 24 hours old
- The
DOCS_RSenvironment variable is set (for docs.rs builds)
Multi-Tenant Support
Use the X-Tenant-ID header to isolate data between tenants: