vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
Helios Software는 보스턴 기반 헬스테크 기업으로 의료기관에 상용급 HL7 FHIR 데이터베이스 솔루션을 제공합니다
Helios Software is a Boston-based health technology company offering a commercial-grade HL7 FHIR database solution for healthcare organizations.
데이터Rust · TypeScriptGitHub @HeliosSoftware온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
The Helios FHIR Server is an implementation of the HL7® FHIR® standard, built in Rust for high performance and optimized for clinical analytics workloads.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
The Helios FHIR Server is an implementation of the HL7® FHIR® standard, built in Rust for high performance and optimized for clinical analytics workloads. It provides modular components that can be run as standalone command-line tools, integrated as microservices, or embedded directly into your data analytics pipeline.README 전문 보기 ↗The Helios FHIR Server is an implementation of the HL7® FHIR® standard, built in Rust for high performance and optimized for clinical analytics workloads. It provides modular components that can be run as standalone command-line tools, integrated as microservices, or embedded directly into your data analytics pipeline.
The Helios FHIR Server includes several components:
hfs — the main FHIR serverhts — the FHIR Terminology Serverfhirpath-cli and fhirpath-server — FHIRPath evaluationsof-cli and sof-server — SQL-on-FHIR transformationpysof — Python bindings for SQL-on-FHIRSee Core Components for details on each.
The server supports SQLite, PostgreSQL, Elasticsearch, and S3 in various configurations — see Storage Backends for setup options.
Pre-built binaries are available on the GitHub Releases page. Download the appropriate archive for your platform and extract it.
Windows users: Add
.exeto all binary names (e.g.,hfs.exe,fhirpath-cli.exe,sof-cli.exe).
The following are independent examples showing how to run each executable — pick whichever ones apply to your use case:
# FHIR server (access at http://localhost:8080/metadata)
./hfs
# FHIR Terminology Server (access at http://localhost:8090/metadata)
./hts
# Evaluate a FHIRPath expression
echo '{"resourceType": "Patient", "id": "123"}' | ./fhirpath-cli 'Patient.id'
# Transform FHIR Bundle to CSV using SQL-on-FHIR
./sof-cli --view examples/patient-view.json --bundle examples/patients.json
# Transform NDJSON file to CSV using SQL-on-FHIR
./sof-cli --view examples/patient-view.json --bundle examples/patients.ndjson
# SQL-on-FHIR HTTP server (POST to http://localhost:8080/$sql-run)
./sof-server
# FHIRPath HTTP server (POST expressions to http://localhost:3000/fhirpath)
./fhirpath-server
Pre-built multi-arch Docker images (amd64/arm64) are available on GitHub Container Registry.
# FHIR Server (default: R4, in-memory SQLite, port 8080)
docker run -p 8080:8080 ghcr.io/heliossoftware/hfs:latest
# With persistent SQLite storage
docker run -p 8080:8080 -v hfs-data:/data -e HFS_DATABASE_URL=/data/fhir.db ghcr.io/heliossoftware/hfs:latest
# With PostgreSQL
docker run -p 8080:8080 \
-e HFS_STORAGE_BACKEND=postgres \
-e HFS_DATABASE_URL="postgresql://user:pass@host:5432/fhir" \
ghcr.io/heliossoftware/hfs:latest
# FHIRPath Server (port 3000)
docker run -p 3000:3000 ghcr.io/heliossoftware/fhirpath-server:latest
# SQL-on-FHIR Server (port 8080)
docker run -p 8080:8080 ghcr.io/heliossoftware/sof-server:latest
# FHIR Terminology Server (default: SQLite, port 8090)
docker run -p 8090:8090 ghcr.io/heliossoftware/hts:latest
# HTS with persistent SQLite storage
docker run -p 8090:8090 -v hts-data:/data -e HTS_DATABASE_URL=/data/hts.db ghcr.io/heliossoftware/hts:latest
See Environment Variables for all available configuration options.
Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Install LLD
Linux (Ubuntu/Debian):
sudo apt install clang lld
Windows:
Download a pre-build binary from llvm-project's GitHub page.
macOS:
LLD is not required for macOS.
Configure config.toml
Create or modify ~/.cargo/config.toml:
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=lld", "-C", "link-arg=-Wl,-zstack-size=8388608"]
[target.aarch64-apple-darwin]
linker = "clang"
rustflags = [
"-C", "link-arg=-Wl,-dead_strip",
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup"
]
[target.x86_64-pc-windows-msvc]
linker = "lld-link.exe"
rustflags = ["-C", "link-arg=/STACK:8388608"]
Memory-constrained builds (optional):
💡 Tip: If you run out of memory during compilation on Linux, especially on high CPU core count machines, limit parallel jobs to 4 (or less):
bash export CARGO_BUILD_JOBS=4
# Clone the repository
git clone https://github.com/HeliosSoftware/hfs.git
cd hfs
# Build (R4 only by default). Uses workspace default-members and skips the Python bindings crate (pysof).
cargo build --release
# Or build with all FHIR versions
cargo build --release --features R4,R4B,R5,R6
# Build all workspace members (including pysof)
cargo build --workspace --release
The Helios FHIR Server supports multiple storage backend configurations. Choose a configuration based on your search requirements and deployment scale.
| Configuration | Search Capability | Use Case |
|---|---|---|
| SQLite (default) | Built-in FTS5 full-text search | Development, testing, small deployments |
| SQLite + Elasticsearch | Elasticsearch-powered search with relevance scoring | Production deployments needing robust search |
| PostgreSQL | Built-in full-text search (tsvector/tsquery) | Production OLTP deployments |
| PostgreSQL + Elasticsearch | Elasticsearch-powered search with PostgreSQL CRUD | Production deployments needing RDBMS + robust search |
| S3 | Object storage for CRUD, versioning, history, and bulk operations (no search) | Archival, bulk analytics, cost-effective storage |
| S3 + Elasticsearch | Elasticsearch-powered search with S3 CRUD | Large-scale storage with full FHIR search |
# SQLite (default) — no external dependencies
./hfs
# SQLite + Elasticsearch
HFS_STORAGE_BACKEND=sqlite-elasticsearch \
HFS_ELASTICSEARCH_NODES=http://localhost:9200 \
./hfs
# PostgreSQL
HFS_STORAGE_BACKEND=postgres \
HFS_DATABASE_URL="postgresql://user:pass@localhost:5432/fhir" \
./hfs
# PostgreSQL + Elasticsearch
HFS_STORAGE_BACKEND=postgres-elasticsearch \
HFS_DATABASE_URL="postgresql://user:pass@localhost:5432/fhir" \
HFS_ELASTICSEARCH_NODES=http://localhost:9200 \
./hfs
# S3 (requires AWS credentials via standard provider chain:
# https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html)
HFS_STORAGE_BACKEND=s3 \
HFS_S3_BUCKET=my-fhir-bucket \
AWS_PROFILE=your-aws-profile \
AWS_REGION=us-east-1 \
./hfs
# S3 + Elasticsearch
HFS_STORAGE_BACKEND=s3-elasticsearch \
HFS_S3_BUCKET=my-fhir-bucket \
HFS_ELASTICSEARCH_NODES=http://localhost:9200 \
AWS_PROFILE=your-aws-profile \
AWS_REGION=us-east-1 \
./hfs
Server
| Variable | Default | Description |
|---|---|---|
HFS_STORAGE_BACKEND | sqlite | Backend mode: sqlite, sqlite-elasticsearch, postgres, postgres-elasticsearch, mongodb, mongodb-elasticsearch, s3, or s3-elasticsearch |
HFS_SERVER_PORT | 8080 | Server port |
HFS_SERVER_HOST | 127.0.0.1 | Host to bind |
HFS_BASE_URL | http://localhost:8080 | Public HTTP(S) base used in Location headers and Bundle links |
HFS_DATABASE_URL | fhir.db | Database URL (SQLite path or PostgreSQL connection string) |
HFS_DATA_DIR | ./data | Directory containing FHIR data files (search parameters) |
HFS_SEARCH_PARAM_CACHE_TTL | 3600 | Seconds between refreshes of the in-memory SearchParameter registry from storage; a param POSTed to one cluster node becomes visible to others within this interval. 0 disables the refresh. |
HFS_DEFAULT_FHIR_VERSION | R4 (a build without R4 uses its only enabled version, and refuses to start without this setting if it enables more than one) | FHIR version (R4, R4B, R5, R6) |
HFS_LOG_LEVEL | info | Log level (error, warn, info, debug, trace) |
HFS_UI_ENABLED | true | Serve the web UI at /ui. Set false for headless deployments; /ui then returns 404 + OperationOutcome. Has no effect on a binary built without the ui feature. |
HFS_DASHBOARD_RECONCILE_SECS | 30 | Seconds between Home dashboard reconcile passes against storage (CLI --dashboard-reconcile-interval-secs). Whole seconds, must be > 0; or a non-numeric value is a startup error. A tenant's full recount is additionally spaced to at most every max(interval, 10 × its last recount duration); also how soon a failed background seed is retried. |
Set HFS_BASE_URL to the URL clients use, including any reverse-proxy path
prefix, for example https://fhir.example.com/fhir. HFS accepts only absolute
http or https URLs without credentials, query strings, or fragments. It
removes trailing slashes at startup. HFS does not derive this value from
Host, Forwarded, or X-Forwarded-* request headers.
Limits & behavior
| Variable | Default | Description |
|---|---|---|
HFS_MAX_BODY_SIZE | 134217728 | Max request body size (bytes; applies to the decompressed body for compressed requests). The 128 MiB default covers the largest per-patient Synthea Bundle (#1662); a batch or transaction body is parsed whole in memory, so lower it on small hosts. A bundle that size takes minutes to process (the largest, 27,056 entries, took about 2 minutes on a release build with SQLite), and HFS_REQUEST_TIMEOUT can answer 408 before it finishes: raise that too when posting large bundles. |
HFS_REQUEST_TIMEOUT | 30 | Request timeout (seconds) |
HFS_DEFAULT_PAGE_SIZE | 20 | Default search result page size |
HFS_MAX_PAGE_SIZE | 1000 | Maximum search result page size |
HFS_EVERYTHING_MAX_UNPAGED | 10000 | Ceiling on match entries for an unpaged Patient/$everything; when reached the response is paged and carries a next link. |
HFS_ENABLE_REQUEST_ID | true | Enable request ID tracking |
HFS_ENABLE_VERSIONING | true | Enable ETag versioning |
HFS_RETURN_GONE | true | Return 410 Gone for deleted resources (vs 404) |
HFS_REQUIRE_IF_MATCH | false | Require If-Match header for updates |
Request bodies may be sent compressed (Content-Encoding: gzip, deflate,
br, or zstd); unsupported encodings are rejected with 415. Responses are
compressed when the client sends Accept-Encoding.
CORS
| Variable | Default | Description |
|---|---|---|
HFS_ENABLE_CORS | true | Enable CORS |
HFS_CORS_ORIGINS | * | Allowed origins |
HFS_CORS_METHODS | GET,POST,PUT,PATCH,DELETE,OPTIONS | Allowed methods |
HFS_CORS_HEADERS | Content-Type,Authorization,Accept,… | Allowed headers |
Multi-tenancy
| Variable | Default | Description |
|---|---|---|
HFS_DEFAULT_TENANT | default | Default tenant ID for requests without an X-Tenant-ID header |
HFS_TENANT_ROUTING_MODE | header_only | Tenant routing: header_only, url_path, or both |
HFS_TENANT_STRICT_VALIDATION | false | Error if URL and header tenant disagree |
HFS_JWT_TENANT_CLAIM | tenant_id | JWT claim name for tenant |
Terminology
| Variable | Default | Description |
|---|---|---|
HFS_TERMINOLOGY_SERVER | (none) | HTS base URL for :in/:not-in search and FHIRPath terminology functions (memberOf, subsumes) |
Elasticsearch
| Variable | Default | Description |
|---|---|---|
HFS_ELASTICSEARCH_NODES | http://localhost:9200 | Comma-separated ES node URLs |
HFS_ELASTICSEARCH_INDEX_PREFIX | hfs | ES index name prefix |
HFS_ELASTICSEARCH_USERNAME | (none) | ES basic auth username |
HFS_ELASTICSEARCH_PASSWORD | (none) | ES basic auth password |
HFS_ELASTICSEARCH_REFRESH_INTERVAL | 1s | Index refresh_interval, set on creation and reconciled onto existing {prefix}_* indices at startup, overwriting hand-set values (-1 disables periodic refresh). With wait_for it is the price of every write |
HFS_ELASTICSEARCH_WRITE_REFRESH | false | refresh parameter on index/delete writes: false, wait_for, or true |
HFS_ELASTICSEARCH_NESTED_OBJECTS_LIMIT | 50000 | Index mapping.nested_objects.limit: max nested objects per document across all nested search-parameter fields. Set on new indices; raised at startup on existing indices below it |
HFS_ELASTICSEARCH_REQUEST_TIMEOUT_MS | 30000 | ES request timeout in milliseconds, including _bulk. A _bulk request that times out is split in half and resent |
HFS_ELASTICSEARCH_BULK_MAX_BYTES | 10485760 | Byte cap per _bulk request body (10 MiB), applied together with the 500-operation cap |
HFS_ELASTICSEARCH_BULK_CONCURRENCY | 1 | _bulk requests of one page in flight at once; splitting and back-off stay sequential per request |
HFS_ELASTICSEARCH_REINDEX_PREPARE_THREADS | 0 | Extraction threads for $reindex pages on the Elasticsearch writer (the composite rebuild): 0 = cores − 1 (1–4), = none beyond the page's own thread (#1250). |
PostgreSQL (used to assemble a connection when HFS_DATABASE_URL is not set)
| Variable | Default | Description |
|---|---|---|
HFS_PG_HOST | localhost | PostgreSQL host |
HFS_PG_PORT | 5432 | PostgreSQL port |
HFS_PG_DBNAME | helios | Database name |
HFS_PG_USER | helios | Database user |
HFS_PG_PASSWORD | (none) | Database password |
HFS_PG_MAX_CONNECTIONS | cores * 4, 16 to 64 | Connection pool size. Without this variable (or with a value that does not parse) the pool is also limited at startup to half of the server's max_connections, shared with the other pools hfs opens against the same host and port, such as the HFS_AUDIT_BACKEND=database pool: on a stock server (max_connections = 100) the two get at most 25 each. A value you set is used as given, with a warning in the log when the pools add up to more than the server's limit. Raise it when PostgreSQL shares the machine with hfs and writes wait on the WAL flush; on a database with its own cores a larger pool did not raise throughput (#2216). |
HFS_PG_CONNECT_TIMEOUT_SECS | 5 | How long establishing a connection may take before failing (s), covering DNS, TCP, TLS and authentication. Raise it for a server that is slow to answer a fresh connection. |
HFS_PG_STATEMENT_TIMEOUT_MS | 30000 | Server-side statement_timeout applied to every pooled connection. Raise it for migrations or other long-running maintenance work. |
HFS_PG_COUNT_BY_TENANT_STATEMENT_TIMEOUT_MS | 25000 | Statement budget for the cross-tenant resource count behind the Tenants UI, GET /admin/tenants, the existence check of DELETE /admin/tenants/{id} and the console tenant metrics, applied as SET LOCAL statement_timeout in the count's own transaction, so no other statement carries it. It only tightens HFS_PG_STATEMENT_TIMEOUT_MS: the count runs under the smaller of the two. Past it PostgreSQL stops the count and the call fails with a timeout error, never a zero count. The REST endpoints answer only when this budget is below , as the defaults are (25 s against 30 s); at or above it the request timeout answers first, and logs a startup warning. Like it covers lock waits and execution, not waiting for a pooled connection, so the at defaults assumes the pool checkout and the handler's earlier work take less than the 5 s of headroom; a checkout that waits longer on a saturated pool (, default 10 s) still ends in . Must be 1 to 2147483647; an out-of-range value fails startup, and one that does not parse is ignored like the other settings. The 25 s default is policy, not a large-store measurement. Since schema v49 the count is an index-only scan of (see ). |
MongoDB
| Variable | Default | Description |
|---|---|---|
HFS_MONGODB_URL / HFS_MONGODB_URI | (none) | MongoDB connection string |
HFS_MONGODB_DATABASE | helios | Database name |
HFS_MONGODB_MAX_CONNECTIONS | 10 | Connection pool size |
HFS_MONGODB_SEARCH_TIMEOUT_MS | (unset) | Soft MongoDB search/count budget (ms), 1–2147483647, shared by admission, planning, pages, totals and inline includes. Unset or blank preserves existing behavior. Checks occur before commands and matching batches, never per ID. Completed search results are returned even if late; unfinished planning, retries and additional batches can still time out. Active commands/cursor reads may overrun; detected expiry returns an error without partial results. New commands receive the remaining maxTimeMS; implicit getMore retains its cursor budget. The HTTP timeout is separate. |
HFS_MONGODB_PROBE_TIMEOUT_MS | 10 | Server execution budget for optional cardinality and ordered-page probes (ms), from 1 through 2147483647. Unset or blank preserves the default. A probe’s own timeout falls back to normal matching; the optional whole-search deadline still applies. |
HFS_MONGODB_ADAPTIVE_OFFSET_PAGING | true | Samples eligible no-total offsets and caches their execution strategy. false disables adaptive offset selection; other search plans are unchanged. |
HFS_MONGODB_MISSING_METADATA | true | Records absent search parameters on each resource (missing_params) and builds idx_resources_missing_params so :missing=true can use them. false stops recording them (each write removes the field), skips the index build, and answers :missing=true from the value indexes instead; results are the same. An existing index is not dropped. |
HFS_MONGODB_CONNECT_TIMEOUT_MS | 5000 | TCP handshake timeout (ms) |
HFS_MONGODB_BROAD_SEARCH_CONCURRENCY | (unset: no limit) | How many potentially broad standard searches run at once per process; others wait for a slot. Reads and narrow searches (, a reference or uri, a date with /, ) bypass this admission limit. A value at or above the pool size is accepted with a startup warning; fails startup. |
S3
| Variable | Default | Description |
|---|---|---|
HFS_S3_TENANCY | prefix-per-tenant | Where tenants live: prefix-per-tenant (one shared bucket, tenant-scoped key prefixes) or bucket-per-tenant (a dedicated bucket per mapped tenant; #1598) |
HFS_S3_BUCKET | hfs | The shared bucket (prefix-per-tenant only; refused under bucket-per-tenant) |
HFS_S3_TENANT_BUCKETS | (none) | Bucket-per-tenant only, required: tenant=bucket,tenant=bucket,…. HFS_DEFAULT_TENANT must be among them; each tenant needs its own bucket, and the buckets must already exist |
HFS_S3_SYSTEM_BUCKET | (none) | Bucket-per-tenant only, optional: the tenant-independent bucket that holds the tenant registry (/admin/tenants), /_user/settings, web login sessions, the $bulk-submit worker index and the __system__ tenant (AuditEvents). Without it those answer 501, login sessions stay in process, and HFS_AUDIT_BACKEND=database needs HFS_AUDIT_S3_BUCKET |
HFS_S3_REGION | (AWS provider chain) | AWS region override |
HFS_S3_PREFIX | (none) | Optional key prefix prepended to all S3 object keys |
HFS_S3_ENDPOINT | (AWS) | S3-compatible endpoint URL (e.g. MinIO http://localhost:9000) |
HFS_S3_FORCE_PATH_STYLE | false | Path-style addressing (required by MinIO and most S3-compatible providers) |
HFS_S3_ALLOW_HTTP | true | Allow insecure http:// endpoint URLs (only relevant when HFS_S3_ENDPOINT is set) |
HFS_S3_VALIDATE_BUCKETS | true | Validate bucket access on startup |
HFS_S3_KEYSPACE_LAYOUT | v1 | v1 (flat) or v2 (sharded by id hash, no ): the layout get; fixed per tenant by a marker object once chosen (see S3 keyspace layout) |
S3 keyspace layout (HFS_S3_KEYSPACE_LAYOUT). Each tenant has one layout, v1 or v2, recorded in a marker object history/_keyspace.json ({"layout":2}). The variable only decides the layout of a tenant that has no marker and no data yet; a tenant that already holds objects without a marker is always v1, and a stamped marker always wins, so changing the variable never moves existing data. v2 stores resources/{type}/{h2}/{id}/… and history/type/{type}/{h2}/… with h2 = hex(sha256(id))[0..2] (256 sub-prefixes) and drops the tenant-wide history/system/ index (system history is served from history/type/), so each write does 3 PUTs instead of 4. The layout of a tenant is immutable: there is no migration, and purge_tenant_data keeps the marker. To change it, stop every instance and delete the tenant's prefix by hand. v2 requires every instance that writes the bucket to run a build that reads the marker and to use the same setting; an older binary ignores the marker and would write v1 keys into a v2 tenant, leaving them unreachable. Opt-in: the default is v1.
SQL-on-FHIR async export
The $sql-export operation writes tabular output
asynchronously to an export sink. See the rest crate README
for the full HFS_EXPORT_* table.
| Variable | Default | Description |
|---|---|---|
HFS_SOF_ENABLED | true | Master switch for SQL-on-FHIR operations ($sql-run, $sql-export); requires a sqlite/postgres backend |
HFS_SOF_SQLQUERY_MAX_ROWS | 100000 | Maximum rows in a SQL Query's own result ($sql-run, $sql-export); rows beyond it are silently dropped, not an error |
HFS_SOF_SQLQUERY_MAX_SOURCE_ROWS_PER_VD | 1000000 | Maximum rows materialized per SQL Query dependency (a depends-on ViewDefinition or SQL View). Each dependency is materialized in full before the query's WHERE runs; one that produces more fails the request with a 422 naming it. Narrow it with a ViewDefinition where, or raise this limit |
HFS_SOF_SQLQUERY_MAX_VDS | 16 | Maximum nodes in a SQL Query's resolved dependency graph: every ViewDefinition and SQL View reached, not just the direct depends-on entries |
HFS_SOF_SQLQUERY_TIMEOUT_SECS | 30 | Timeout, seconds, for each SQL statement a SQL Query runs (its own SQL and each SQL View's); does not cover materializing a dependency |
HFS_EXPORT_SINK | fs | Output sink for finished shards: fs (local filesystem) or s3. Any other value fails startup; s3 fails startup on a build without the s3 feature. Not checked when HFS_SOF_ENABLED=false |
HFS_EXPORT_DIR | ./exports | Root directory for the fs export sink |
HFS_EXPORT_S3_BUCKET | (none) | S3 bucket for the s3 sink; required when HFS_EXPORT_SINK=s3 |
HFS_EXPORT_S3_REGION | (AWS chain) | Region override for the s3 sink; defaults to us-east-1 when HFS_EXPORT_S3_ENDPOINT is set |
Authentication & SMART-on-FHIR
JWT/bearer auth (HFS_AUTH_*, e.g. HFS_AUTH_ENABLED, HFS_AUTH_JWKS_URL, HFS_AUTH_ISSUER, HFS_AUTH_AUDIENCE) and SMART configuration endpoints (HFS_SMART_*) plus HFS_OUTBOUND_BEARER_TOKEN are documented in the helios-auth README.
Audit, subscriptions & bulk export
| Variable | Default | Description |
|---|---|---|
HFS_AUDIT_BACKEND | none | Audit backend: none, file, database, or cloudwatch |
HFS_AUDIT_FILE_PATH | (none) | Required when HFS_AUDIT_BACKEND=file; NDJSON file path for persisted AuditEvent logs |
HFS_AUDIT_DATABASE_URL | (none) | Optional dedicated audit database URL/path (SQLite/PostgreSQL/MongoDB families) |
HFS_AUDIT_MONGODB_DATABASE | (none) | Optional dedicated MongoDB database name for audit events |
HFS_AUDIT_S3_BUCKET | (none) | Optional dedicated S3 bucket for audit events |
HFS_AUDIT_S3_PREFIX | (none) | Optional dedicated S3 prefix for audit events |
HFS_AUDIT_S3_REGION | (none) | Optional dedicated S3 region for audit events |
HFS_AUDIT_S3_VALIDATE_BUCKETS | (none) | Optional dedicated S3 bucket validation toggle for audit events |
HFS_AUDIT_SOURCE_OBSERVER | Device/hfs | Sets AuditEvent.source.observer |
HFS_AUDIT_EXCLUDE_PATHS | (none) | Comma-separated paths to exclude from audit middleware |
HFS_AUDIT_QUEUE_CAPACITY | 10000 | Audit write-queue capacity |
HFS_AUDIT_WRITERS | 4 × cores (4–64) | Writer tasks draining the audit queue (bounds concurrent audit writes) |
HFS_AUDIT_OVERFLOW | block | Full audit queue: block the response until queued, or drop the event (counted in audit_events_dropped_total) |
The SMTP delivery channel (HFS_SUBSCRIPTION_SMTP_*), delivery-retry tuning (HFS_SUBSCRIPTION_HANDSHAKE_*), and the remaining startup-rehydration knobs (HFS_SUBSCRIPTION_REHYDRATE_*) are documented in the helios-subscriptions README.
For detailed backend setup instructions (building from source, Docker commands, and search offloading architecture), see the persistence crate documentation.
The Helios FHIR Server is organized as a Rust workspace with modular components that can be used independently or together. Each component is designed for high performance and can be embedded directly into your data analytics pipeline.
helios-hfs - Main Server Applicationhfs - The main Helios FHIR Server application.helios-hts - FHIR Terminology Serverhts - The Helios Terminology Server (default port 8090)helios-fhir - FHIR Data ModelsGenerated from FHIR StructureDefinitions, type-safe Rust representations of all FHIR resources and data types.
--all-features for all versions)helios-fhir-gen - Code GeneratorGenerates the FHIR data models from official HL7 specifications.
helios-fhirpath - FHIRPath Expression EngineComplete implementation of the FHIRPath 3.0.0-ballot specification.
fhirpath-cli - Evaluate FHIRPath expressions from the command linefhirpath-server - HTTP server for FHIRPath evaluationhelios-sof - SQL-on-FHIR ImplementationTransform FHIR resources into tabular data using ViewDefinitions.
sof-cli - Command-line tool for batch transformationssof-server - HTTP server with $sql-run operationpysof - Python BindingsPython bindings for SQL-on-FHIR using PyO3, bringing high-performance FHIR data transformation to Python.
Key Capabilities:
Python API Example:
import pysof
# Transform FHIR bundle to CSV using a ViewDefinition
result = pysof.run_view_definition(
view_definition=view_def_json,
bundle=fhir_bundle_json,
format="csv"
)
# Process individual resources
result = pysof.run_view_definition(
view_definition=view_def_json,
resources=[patient1, patient2],
format="parquet"
)
Distribution:
helios-cds-hooks - CDS Hooks Protocol TypesRust types and traits for building CDS Hooks clinical decision support services.
CdsHooksService trait compatible with any Rust web frameworkhelios-fhir-macro - Procedural MacrosHelper macros for code generation used by other components.
helios-fhirpath-support - Shared UtilitiesCommon types and traits for FHIRPath evaluation.
helios-persistence - Polyglot Persistence LayerStorage backend abstraction supporting multiple database technologies optimized for different FHIR workloads. Also hosts the Bulk Data Export job-state stores, worker runtime, and output stores backing the server's $export operation (REST endpoints and HFS_BULK_EXPORT_* configuration live in helios-rest).
helios-audit - BALP Audit LoggingIHE BALP-compliant AuditEvent logging for REST, auth, persistence, and lifecycle events. Supports file, database, and AWS CloudWatch Logs sinks. See the helios-audit README for full configuration details.
$sql-run operation$export) at system, Patient, and Group level$purge (permanent, irreversible erasure of a resource and its history) and $reindex (rebuild the search index), each gated on its own scopeAuditEvent logging for REST and auth interactions, including the $export, $purge, and $reindex operations# Build with default features (R4 only)
# Note: pysof (Python bindings) is excluded by workspace default-members
cargo build
# Build with all FHIR versions
cargo build --all-features
# Build specific component
cargo build -p helios-fhirpath
# Build Python bindings (requires Python 3.11)
# Option A: Rust-only build of the crate
cargo build -p pysof
# Option B (recommended): build via maturin into a virtual env
cd crates/pysof
uv venv --python 3.11
uv sync
uv run maturin develop --release
# Build distributable artifacts for pysof
uv run maturin build --release -o dist # wheels
uv run maturin sdist -o dist # source distribution
# Build everything except Python bindings (alternative)
cargo build --workspace --exclude pysof
Docker Required: PostgreSQL and Elasticsearch integration tests use testcontainers to spin up real database instances in Docker. Make sure Docker is installed and running to execute the full test suite. To skip these tests (e.g., if Docker is unavailable), add -- --skip postgres_integration --skip es_integration to your test command.
# Run all tests (R4 only by default)
cargo test
# Run tests for all FHIR versions
cargo test --all-features
# Run tests without Docker (skips PostgreSQL and Elasticsearch integration tests)
cargo test --all-features -- --skip postgres_integration --skip es_integration
# Run specific test
cargo test test_name_pattern
# Run with output
cargo test -- --nocapture
To regenerate FHIR models from HL7 specifications:
# This will download the latest R6 (build) specifications from https://build.fhir.org/
# Note the lack of use of --all-features and the lack of skip-r6-download here.
cargo build -p helios-fhir-gen --features R4,R4B,R5,R6
# This will generate all FHIR code models (r4.rs, r4b.rs, r5, and r6)
./target/debug/helios-fhir-gen --all
# Format the generated files accordingly
cargo fmt --all
Published crate documentation is available on crates.io. To generate and view documentation locally:
cargo doc --no-deps --open
See our Roadmap for current development priorities and planned features.
Please see our Contributing Guidelines for details.
The Helios FHIR Server is licensed under the MIT License.
We welcome contributors and feedback at every level — from opening issues to joining design discussions.
HL7® and FHIR® are registered trademarks of Health Level Seven International.
0HFS_DASHBOARD_REFRESH_SECS | 5 | Seconds between refreshes of a Home dashboard whose figures are moving (approximate, or an import running) (CLI --dashboard-refresh-secs). Re-reads in-memory counters only, never storage. Whole seconds, must be > 0 and <= HFS_DASHBOARD_IDLE_REFRESH_SECS; otherwise a startup error. |
HFS_DASHBOARD_IDLE_REFRESH_SECS | 10 | Seconds between watch ticks of a Home dashboard whose figures are settled (exact, no import running), so an open tab notices an import starting (CLI --dashboard-idle-refresh-secs). Whole seconds, must be > 0 and >= HFS_DASHBOARD_REFRESH_SECS; otherwise a startup error. |
1HFS_REINDEX_BATCH_BYTES | 33554432 (32 MiB) | Byte cap on one page of the automatic rebuild (0 = count only). Honoured by the SQLite source (a page may exceed the cap by one resource) and by the PostgreSQL and MongoDB sources (a page never exceeds the cap unless it holds a single resource); the Elasticsearch and S3 sources page by count only |
HFS_REINDEX_PREFETCH | true | Fetch the next $reindex page from the primary while the current one is written, for POST $reindex and the automatic rebuild alike, wherever the source allows it: standalone MongoDB and mongo-es (id phase), and sqlite-es, postgres-es, s3-es, where search is offloaded so the page read and the Elasticsearch write touch disjoint stores. false restores the serial fetch → write loop on every backend (#1250) |
HFS_ELASTICSEARCH_REINDEX_REFRESH | (unset) | refresh parameter for $reindex and deferred-rebuild writes: false, wait_for, or true. Unset follows HFS_ELASTICSEARCH_WRITE_REFRESH |
HFS_REINDEX_BATCH_SIZE | 1000 | Page size of the automatic deferred rebuild after a bulk import (all backends). POST $reindex keeps its own batchSize, capped at 10,000 |
504HFS_REQUEST_TIMEOUT408hfsstatement_timeout504HFS_PG_POOL_WAIT_TIMEOUT_SECS408HFS_PG_*idx_resources_live_tenantHFS_PG_POOL_WAIT_TIMEOUT_SECS | 10 | How long a request waits for a free pooled connection before failing with 503 |
_ideqapidentifier=system|code0HFS_MONGODB_COUNT_BY_TENANT_MAX_TIME_MS | 25000 | Server execution budget (maxTimeMS) for the cross-tenant resource count behind the Tenants UI, GET /admin/tenants, the existence check of DELETE /admin/tenants/{id} and the console tenant metrics. No other query carries it. Past it the server stops the count and the call fails with a timeout error, never a zero count. A caller outside the HTTP request timeout, such as the Tenants UI, sees that error directly and shows its error state instead of counts. The REST endpoints answer 504 only when this budget is below HFS_REQUEST_TIMEOUT, as the defaults are (25 s against 30 s). The request timeout starts when the request arrives, before the count, so with a budget at or above it the request timeout answers 408 first; the budget still stops the count on the server a moment later. Keep it below HFS_REQUEST_TIMEOUT when raising either. It bounds server execution only, not server selection, waiting for a pooled connection or network time. Must be 1 to 2147483647; anything else fails startup. The 25 s default is policy (five seconds under the default request timeout), not a large-store measurement. The count is a covered scan of the idx_resources_live_tenant index, which boot creates; for its build cost on an existing store see docs/mongodb/tenant-count-index.md. |
HFS_MONGODB_SOF_CURSOR_BATCH_SIZE | 512 | Documents per cursor batch of a SQL-on-FHIR scan (1 to 100000; anything else fails startup). Lower = lower first-row latency on selective views (the first row waits for one full batch); higher = fewer round trips against a remote MongoDB (about 3,500 getMore per 1.8M rows at 512, about 7,000 at 256). Memory is bounded by this many documents per reply. |
HFS_MONGODB_SERVER_SELECTION_TIMEOUT_MS | 15000 | How long an operation waits for a usable server before failing (ms). This, not the connect timeout, bounds how quickly an unreachable MongoDB surfaces an error. |
HFS_MONGODB_MAX_CONCURRENT_TRANSACTION_BUNDLES | 4 | How many standard-size transaction Bundles (see HFS_MONGODB_TRANSACTION_BUNDLE_WEIGHT_ENTRIES) run at once; the rest wait their turn within the request timeout. Each Bundle is one MongoDB transaction held in WiredTiger's cache until commit, so this bounds cache pressure (see Sizing the WiredTiger cache for transaction Bundles). 0 removes the limit. |
HFS_MONGODB_TRANSACTION_BUNDLE_WEIGHT_ENTRIES | 1000 | The entry count of one standard Bundle. Bundles are admitted while their entries fit in limit × this, each counting at least 1 entry and at most the whole room, so small Bundles share a slot and a large one takes several. 0 counts every Bundle as one slot (the #1776 behaviour). The limit counts standard Bundles of this many entries, not Bundles, so with the default weight many small transaction Bundles can be open at once, each with its own session and transaction, bounded by the entry room and the connection pool rather than by the limit. For a hard cap on concurrent Bundles (for example limit 1 to serialise them), set this to 0. |
HFS_MONGODB_TRANSACTION_BUNDLE_DEFERRED_INDEX_ENTRIES | auto (the admission room, 4000) | Transaction Bundles with at least this many entries commit their resources and history without their search rows, which are written right after the commit, before the response; other clients may see search lag for those resources. off or 0 writes every Bundle's rows inside its transaction. Ignored on mongodb-elasticsearch. See Deferred search indexing for large MongoDB transaction Bundles. |
HFS_MONGODB_DEFERRED_INDEX_REPAIR_INTERVAL | 60 | Seconds between passes of the task that finishes the search rows a large Bundle left unwritten after its commit (crash, cancelled request, failure); it also runs once at startup. A pass takes only Bundles whose ledger is older than the larger of 60 s and the Bundle deadline (HFS_REQUEST_TIMEOUT less 2 s). 0 turns the task off. |
HFS_MONGODB_INDEX_BUILD | background | When the generation-2 search_index indexes and resources.idx_resources_missing_params are built: background serves immediately and builds after boot, inline waits for the build before serving, off only warns so an operator can pre-build (see docs/mongodb/search-indexes.md). |
HFS_MONGODB_REINDEX_OVERLAP | true | Overlap search-parameter extraction with search_index inserts inside a $reindex page; false restores the serial writer. |
HFS_MONGODB_REINDEX_PREPARE_THREADS | 0 | Extraction threads for $reindex pages: 0 = cores − 1 (1–4), 1 = none beyond the page's own thread. |
HFS_MONGODB_REINDEX_PREFETCH | true | Fetch the next id-order $reindex page while the current one is written, on standalone MongoDB and on mongo-es (#1250); the MongoDB-specific switch under HFS_REINDEX_PREFETCH, which covers every backend. |
history/system/HFS_S3_SCAN_CONCURRENCY | 32 | The most GetObject requests S3 reads may have in flight at once, shared by every request on the S3 store: SQL-on-FHIR scans and by-id reads ($sql-run, previews, SQL Query, $sql-export), type counts, conditional-create and SearchParameter scans, and _history. A whole number of at least 1. Writes (startup seeding, bulk writes) are unaffected |
HFS_EXPORT_S3_ENDPOINT| (AWS) |
Custom S3 endpoint URL for the s3 sink (e.g. MinIO); forces path-style addressing |
HFS_EXPORT_S3_FORCE_PATH_STYLE | false | Path-style addressing for the s3 sink; forced on when HFS_EXPORT_S3_ENDPOINT is set |
HFS_EXPORT_OUTPUT_TTL | 86400 | Retention (seconds) for a finished job's output and bookkeeping; the cleanup reaper deletes shards and drops the job afterward |
HFS_EXPORT_CLEANUP_INTERVAL | 300 | Cleanup-reaper scan interval (seconds; clamped to ≥ 1) |
HFS_AUDIT_WRITE_RETRIES | 5 | Retries of a transient database-sink write before the event is dropped and counted |
HFS_AUDIT_CLOUDWATCH_LOG_GROUP | (none) | Required when HFS_AUDIT_BACKEND=cloudwatch; CloudWatch Logs log group name |
HFS_AUDIT_CLOUDWATCH_LOG_STREAM | hfs-audit | CloudWatch Logs log stream name |
HFS_AUDIT_CLOUDWATCH_REGION | (AWS chain) | AWS region override for CloudWatch Logs |
HFS_SUBSCRIPTIONS_ENABLED | false | Enable the subscription engine when HFS is built with the subscriptions feature |
HFS_SUBSCRIPTION_MESSAGING_ENABLED | false | Enable the FHIR Messaging subscription channel |
HFS_SUBSCRIPTION_MESSAGE_SOURCE_ENDPOINT | HFS_BASE_URL | Source endpoint URL used in outbound FHIR message headers |
HFS_SUBSCRIPTION_ALLOW_PRIVATE_ENDPOINTS | false | Allow subscription deliveries to private or loopback endpoints; intended for local development and CI only |
HFS_SUBSCRIPTION_REHYDRATE | true | Reload stored Subscription/SubscriptionTopic resources into the engine at startup, so subscriptions keep delivering across a restart |
HFS_SUBSCRIPTION_REHYDRATE_HANDSHAKE | true | Re-run the activation handshake for stored requested subscriptions during rehydration |
HFS_BULK_EXPORT_ENABLED | true | Enable the Bulk Data Export $export operation; when false, all $export endpoints return 501 |
HFS_BULK_EXPORT_OUTPUT_BACKEND | local-fs | Bulk export output store: local-fs or s3. See the rest crate README for the full HFS_BULK_EXPORT_* table |
HFS_BULK_SUBMIT_ENABLED | true | Enable the Bulk Data Submit $bulk-submit operation (HFS as Data Consumer — fetches a provider manifest and ingests it); when false, all $bulk-submit endpoints return 501. Available on sqlite/postgres (+ -elasticsearch composites) |
HFS_BULK_SUBMIT_OUTPUT_BACKEND | local-fs | Bulk submit status-artifact store: local-fs or s3. See the rest crate README for the full HFS_BULK_SUBMIT_* table |