Bulk Data Export

SkillFiles & storage

Work on HFS FHIR Bulk Data Access $export. Use for export kick-off, polling, manifests, downloads, job state, output storage, S3/local export configuration, Inferno bulk data workflow, _typeFilter, _elements, and group export behavior.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Bulk Data Export skill

What this skill tells your AI

The instructions your AI receives, as published by heliossoftware/hfs in .agents/skills/bulk-data-export/SKILL.md and read by ahel’s review.

HFS implements the FHIR Bulk Data Access $export family asynchronously: kick-off, poll, manifest, download, delete.

Endpoints

OperationMethodURL
system kick-offGET/POST/$export
patient kick-offGET/POST/Patient/$export
group kick-offGET/POST/Group/{id}/$export
status or manifestGET/export-status/{job_id}
cancel and deleteDELETE/export-status/{job_id}
HFS-served downloadGET/export-file/{job_id}/{type}-{part}

All kick-offs require Prefer: respond-async. The default response is 202 Accepted with a Content-Location status URL.

Environment

VariableDefaultDescription
HFS_BULK_EXPORT_ENABLEDtrueMaster switch; false returns 501 for all export endpoints
HFS_BULK_EXPORT_OUTPUT_BACKENDlocal-fsOutput store: local-fs or s3
HFS_BULK_EXPORT_OUTPUT_DIR${HFS_DATA_DIR}/exportsLocal filesystem output root
HFS_BULK_EXPORT_S3_BUCKETnoneS3 bucket, required when output backend is s3
HFS_BULK_EXPORT_S3_ENDPOINTAWSS3-compatible endpoint URL, such as MinIO
HFS_BULK_EXPORT_S3_FORCE_PATH_STYLEfalsePath-style addressing for S3-compatible providers
HFS_BULK_EXPORT_REQUIRES_ACCESS_TOKENautoManifest posture: auto, true, or false; false is invalid with local-fs
HFS_BULK_EXPORT_FILE_URL_TTL3600Pre-signed download URL lifetime in seconds
HFS_BULK_EXPORT_OUTPUT_TTL86400Output retention after job completion in seconds
HFS_BULK_EXPORT_WORKER_CONCURRENCY2In-process worker pool size
HFS_BULK_EXPORT_DISABLE_LOCAL_WORKERfalseDisable in-pod workers for separate exporter deployments
HFS_BULK_EXPORT_MAX_CONCURRENT_PER_TENANT4Per-tenant active job cap; kick-off returns 429 if exceeded
HFS_BULK_EXPORT_BATCH_SIZE1000Resources per fetch_export_batch
HFS_BULK_EXPORT_LEASE_DURATION60Initial lease length in seconds; must exceed heartbeat interval
HFS_BULK_EXPORT_HEARTBEAT_INTERVAL20Worker heartbeat cadence in seconds
HFS_BULK_EXPORT_CLEANUP_INTERVAL300Cleanup scan interval in seconds
HFS_BULK_EXPORT_SINCE_NEWLY_ADDEDincludeGroup export _since toggle: include or exclude

Job-state storage reuses the same backend and connection pool that holds FHIR resources. SQLite deployments share ./data/hfs.db. PostgreSQL deployments share HFS_DATABASE_URL. There is no separate job-store configuration.

Bulk export is currently available on sqlite, postgres, sqlite-elasticsearch, and postgres-elasticsearch. Other backends return 501 until job-state implementations exist.

Single-instance Recipe

cargo run --bin hfs

This starts HFS with bulk export enabled, job state in the same SQLite database as FHIR resources, NDJSON output under ./data/exports/, and an in-process worker pool.

curl -H 'Prefer: respond-async' http://localhost:8080/Patient/\$export

Multi-instance Recipe

PostgreSQL plus S3 or MinIO:

HFS_STORAGE_BACKEND=postgres \
HFS_DATABASE_URL=postgresql://hfs:hfs@localhost/hfs \
HFS_BULK_EXPORT_OUTPUT_BACKEND=s3 \
HFS_BULK_EXPORT_S3_BUCKET=hfs-export \
HFS_BULK_EXPORT_S3_ENDPOINT=http://localhost:9000 \
HFS_BULK_EXPORT_S3_FORCE_PATH_STYLE=true \
HFS_BULK_EXPORT_REQUIRES_ACCESS_TOKEN=false \
cargo run --bin hfs --features postgres,s3

The full local stack is in docker/bulk-export/docker-compose.yml: HFS, Postgres, MinIO, and Keycloak. GitHub Actions does not use this compose file for bulk export tests. The manual conformance workflow is .github/workflows/inferno-bulk-data.yml.

Behavior Notes

  • _typeFilter is parsed and applied.
  • Unsupported result-control params inside _typeFilter are rejected with 400 regardless of Prefer: handling: _sort, _include, _revinclude, _count, _elements.
  • _elements is implemented: subset to listed paths plus id, resourceType, and meta, with a SUBSETTED meta.tag added.
  • Unsupported parameters includeAssociatedData, organizeOutputBy, and allowPartialManifests return 400 when Prefer: handling=strict is set. Without strict handling, or with lenient handling, they are ignored and a warning is logged.
  • Group export _since late membership uses include by default, returning pre-_since resources for patients added after _since.
  • exclude is reserved for a follow-up that requires group-membership-history tracking.
  • Group export flattens nested Group/ members iteratively with a visited-set cycle guard.

Signals

GitHub stars
51
Forks
19
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
bulk-data-export
Source
github.com/heliossoftware/hfs