Skip to main content

Implementation Features

Spec: FHIR RESTful API

Conditional References (Search URIs)

Ferrum supports conditional references inside request resources by allowing a search URI in Reference.reference (FHIR “search URIs”):
Behavior:
  • 1 match: Ferrum rewrites the reference to Patient/{id} and persists the rewritten form.
  • 0 matches or 2+ matches: request fails with 412 Precondition Failed and no write occurs.
  • Only filter search parameters are allowed (e.g. _count, _sort, _include, _revinclude, _elements, _summary are rejected).
This applies to POST, PUT, and PATCH (including conditional interactions), and also to bundle processing (batch / transaction).

Create Behavior

Spec: create, conditional create, update-as-create

Server-Assigned IDs

When creating with POST, Ferrum generates UUIDs as resource IDs:

Client-Assigned IDs

The allow_update_create configuration option allows PUT to create resources if they don’t exist (enabled by default).
With this enabled:
Security Consideration: Enabling allow_update_create allows clients to choose IDs. Ensure proper authorization to prevent ID conflicts or predictable ID attacks.

Basic Checks on Create

By default, Ferrum performs basic structural checks on creates:
  1. Resource Type: Validates that resourceType matches the endpoint
  2. Resource Type Name: Ensures the resource type is a known FHIR resource type
FHIR Validation: Full FHIR validation (cardinality, data types, profiles, etc.) is not yet implemented but will be in the future.

Conditional Create

Ferrum’s conditional create follows FHIR spec:
Behavior:
  • 0 matches: Creates new resource → 201 Created
  • 1 match: Returns existing resource → 200 OK with Location header
  • 2+ matches: Rejects as ambiguous → 412 Precondition Failed
Performance: Conditional creates use indexed search, so ensure the search parameter (e.g., identifier) is indexed for fast lookups.

Read Behavior

Spec: read, Concurrency Management (ETag/If-Match), Support for HEAD

ETag Support

Every read returns a weak ETag header for optimistic locking:
Use If-Match on updates to prevent lost updates:

Deleted Resources

Reading a deleted resource behavior depends on delete mode: Soft Delete (default):
  • Returns 410 Gone for deleted resources
  • History remains accessible via GET /Patient/123/_history/5
Hard Delete (hard_delete: true):
  • Returns 404 Not Found (resource completely removed)
  • History is not accessible (all versions deleted)
Access deleted resources via history (soft delete only):

HEAD Requests

Check resource existence without fetching body:

Update Behavior

Spec: update, update-as-create, conditional update, Concurrency Management (If-Match)

Version Tracking

Ferrum uses sequential integer versions starting at 1:
Each update increments the version:

Optimistic Locking

Always use If-Match for safe updates:
Without If-Match:
  • Ferrum accepts the update (no concurrency protection)
  • Last write wins (can lose concurrent changes)
With If-Match:
  • Ferrum rejects if version doesn’t match → 412 Precondition Failed
  • Client must refetch, merge changes, and retry

Conditional Update

Update by search criteria:
Behavior:
  • 0 matches: Creates new resource (if allow_update_create enabled) → 201 Created
  • 1 match: Updates that resource → 200 OK
  • 2+ matches: Rejects as ambiguous → 412 Precondition Failed
Conditional Update + Multiple Matches: Unlike some servers, Ferrum never updates multiple resources in a single request. This prevents accidental mass updates.

Patch Behavior

Spec: patch, JSON Patch (RFC 6902)

JSON Patch Support

Ferrum supports JSON Patch (RFC 6902) format:
Supported operations: add, remove, replace, move, copy, test

Narrative Handling

Ferrum automatically removes text (narrative) after applying patches:
Why? Narrative is auto-generated HTML that describes the resource. After a patch, the narrative no longer matches the data, so Ferrum removes it to prevent confusion.

Patch Result Checks

After applying patch operations, Ferrum performs basic structural checks:
  • Patched resource must remain a valid JSON object
  • Resource type and ID are preserved (cannot be changed via patch)
FHIR Validation: Full FHIR validation of the patched result is not yet implemented. The patched resource is stored as-is after basic structural checks.

Atomic Patches

All operations in a patch are atomic:
  • Either all operations succeed, or none do
  • Failed operation rolls back the entire patch
  • Version number only increments if all operations succeed

Conditional Patch

Same matching rules as conditional update (requires exactly 1 match).

Delete Behavior

Spec: delete, conditional delete

Soft Delete (Default)

Ferrum uses soft delete by default (hard_delete: false):
  • Resource marked as deleted in database
  • History preserved and accessible
  • GET /Patient/123410 Gone
  • GET /Patient/123/_history/5200 OK (still accessible)
  • Creates a new version entry marking the resource as deleted

Hard Delete

When hard_delete: true is configured:
  • Resource physically removed from database
  • All history versions permanently deleted
  • GET /Patient/123404 Not Found (not 410 Gone)
  • History endpoints return 404 Not Found
  • No new version created (complete removal)
  • Enables deletion of history endpoints (DELETE /Patient/123/_history)
Irreversible Operation: Hard delete permanently removes all data and history. This cannot be undone. Use with caution, especially in production environments.

Delete Response

Configure response style with Prefer header:

Idempotent Delete

Deleting an already-deleted resource succeeds:

Conditional Delete

Behavior:
  • 0 matches: No-op, returns 204 No Content
  • 1 match: Deletes that resource → 204 No Content
  • 2+ matches: Rejects as ambiguous → 412 Precondition Failed

Performance Considerations

Spec (Batch/Transaction): batch/transaction

Indexing

Ferrum automatically indexes:
  • Resource ID (primary key)
  • Version ID
  • Last updated timestamp
  • Common search parameters (identifier, name, etc.)
Conditional operations use these indexes for fast lookups.

Batch Creates

For bulk data loading, use Batch/Transaction instead of individual creates:
Benefits:
  • Single database transaction
  • Reduced network overhead
  • Better error handling

Error Handling

Spec: HTTP Status Codes, OperationOutcome All errors return OperationOutcome with details:

Error Responses

Ferrum returns OperationOutcome resources for errors with diagnostic information:

Configuration

Spec (Capability Declaration): CapabilityStatement Key configuration options for CRUD operations:
See Configuration Guide for complete options.

Testing Your Implementation

Spec (Capabilities): capabilities (GET [base]/metadata) Use the interactive API playground to test CRUD operations:

Create

Try creating resources

Read

Test read operations

Update

Practice updates

Delete

Test deletion

Next Steps

Spec: search, batch/transaction, history

Search Operations

Query resources efficiently

Batch & Transaction

Perform multiple operations atomically

Versioning & History

Access resource history