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.

Use Bulk Data Export in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add Bulk Data Export and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the Bulk Data Export skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Bulk Data ExportStart free

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_MAX_ATTEMPTS3Claims allowed per job; a job reclaimed past this is failed as abandoned
HFS_BULK_EXPORT_BATCH_SIZE1000Resources per fetch_export_batch
HFS_BULK_EXPORT_LEASE_DURATION60Initial lease length in seconds; must exceed heartbeat interval
HFS_WORKER_SHUTDOWN_TIMEOUT20Seconds a graceful shutdown waits for the bulk export and submit workers to stop and release their leases (#1531). A released export is claimable by another instance at once, without spending one of its HFS_BULK_EXPORT_MAX_ATTEMPTS, and restarts from scratch. Past the deadline, leases lapse after the lease duration as before
HFS_BULK_EXPORT_HEARTBEAT_INTERVAL20Lease-keeper renewal cadence in seconds; a background task renews the lease at this cadence while a job runs; must be below the lease duration
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
53
Forks
21
Last commit
Oct 2026
Advanced
Item type
skill
Key
bulk-data-export
Source
github.com/heliossoftware/hfs