Chuyển đến nội dung chính

Lesson 9: Bundle, Transaction and Batch - Handling multiple Resources

Resource Bundle and types (searchset, transaction, batch, document, message, collection, history). Transaction processing rules, atomic operations, conditional references, batch processing, practice creating transaction bundles.

🏗️ Architecture — Lesson 9 Lesson 9: Bundle, Transaction and Batch - Processing Manage many Resources

HL7 FHIR - Basic to Advanced Healthcare Data Standard

Part 3: FHIR RESTful API and Data Exchange

xdev.asia

1. Bundle Resources

Bundle is a container containing many Resources. It is how FHIR handles multiple resources in one request, packages documents, and returns search results.

Bundle Types

TypeDescriptionUse cases
searchsetSearch resultsResponse of GET search
transaction. transactionAtomic operations groupCreate many related resources
batch. batchOperations independent groupBulk operations, each entry processed independently
document. documentFHIR DocumentClinical document (Composition + resources)
message. messageFHIR MessageMessaging paradigm (MessageHeader + payload)
collectionCollectionPool resources without specific interactions
history. historyHistory changesResponse of _history
subscription-notificationSubscription noticeReal-time notifications

2. Transaction Bundle

Transaction Bundle handling atomic — all successful entries or all rollbacks.

For example: Create Patient + Encounter + Observation at the same time

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:patient-temp-1",
      "resource": {
        "resourceType": "Patient",
        "name": [
          {
            "family": "Nguyễn",
            "given": ["Văn", "A"],
            "text": "Nguyễn Văn A"
          }
        ],
        "gender": "male",
        "birthDate": "1990-05-15",
        "identifier": [
          {
            "system": "http://hospital.vn/mrn",
            "value": "MRN-2025-001"
          }
        ]
      },
      "request": {
        "method": "POST",
        "url": "Patient",
        "ifNoneExist": "identifier=http://hospital.vn/mrn|MRN-2025-001"
      }
    },
    {
      "fullUrl": "urn:uuid:encounter-temp-1",
      "resource": {
        "resourceType": "Encounter",
        "status": "in-progress",
        "class": [
          {
            "coding": [
              {
                "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
                "code": "AMB"
              }
            ]
          }
        ],
        "subject": {
          "reference": "urn:uuid:patient-temp-1"
        },
        "period": {
          "start": "2025-01-15T08:00:00+07:00"
        }
      },
      "request": {
        "method": "POST",
        "url": "Encounter"
      }
    },
    {
      "fullUrl": "urn:uuid:obs-temp-1",
      "resource": {
        "resourceType": "Observation",
        "status": "final",
        "category": [
          {
            "coding": [
              {
                "system": "http://terminology.hl7.org/CodeSystem/observation-category",
                "code": "vital-signs"
              }
            ]
          }
        ],
        "code": {
          "coding": [
            {
              "system": "http://loinc.org",
              "code": "8310-5",
              "display": "Body temperature"
            }
          ]
        },
        "subject": {
          "reference": "urn:uuid:patient-temp-1"
        },
        "encounter": {
          "reference": "urn:uuid:encounter-temp-1"
        },
        "valueQuantity": {
          "value": 37.2,
          "unit": "°C",
          "system": "http://unitsofmeasure.org",
          "code": "Cel"
        }
      },
      "request": {
        "method": "POST",
        "url": "Observation"
      }
    }
  ]
}

Conditional References in Transaction

Use urn:uuid: Make a temporary ID so that entries in the same transaction refer to each other. The server will replace it with the actual ID after creation.

Transaction Response

{
  "resourceType": "Bundle",
  "type": "transaction-response",
  "entry": [
    {
      "response": {
        "status": "201 Created",
        "location": "Patient/patient-001/_history/1",
        "etag": "W/\"1\"",
        "lastModified": "2025-01-15T08:00:00Z"
      }
    },
    {
      "response": {
        "status": "201 Created",
        "location": "Encounter/encounter-001/_history/1",
        "etag": "W/\"1\""
      }
    },
    {
      "response": {
        "status": "201 Created",
        "location": "Observation/obs-001/_history/1",
        "etag": "W/\"1\""
      }
    }
  ]
}

Transaction Processing Rules

  1. Server processes in order: DELETE → POST → PUT/PATCH → GET (conditional)
  2. All entries must succeed → atomic
  3. If any entry fails → All transaction rollbacks
  4. urn:uuid: references are resolved before processing

3. Batch Bundle

Batch processing independent — Each entry is processed separately, a failed entry does not affect other entries.

{
  "resourceType": "Bundle",
  "type": "batch",
  "entry": [
    {
      "request": {
        "method": "GET",
        "url": "Patient/patient-001"
      }
    },
    {
      "request": {
        "method": "GET",
        "url": "Observation?subject=Patient/patient-001&category=vital-signs&_sort=-date&_count=5"
      }
    },
    {
      "request": {
        "method": "GET",
        "url": "Condition?subject=Patient/patient-001&clinical-status=active"
      }
    },
    {
      "request": {
        "method": "GET",
        "url": "MedicationRequest?subject=Patient/patient-001&status=active"
      }
    }
  ]
}

Use case: Get all patient information in one API call instead of 4 separate calls.

Batch Response

{
  "resourceType": "Bundle",
  "type": "batch-response",
  "entry": [
    {
      "resource": {"resourceType": "Patient", "id": "patient-001", "...": "..."},
      "response": {"status": "200 OK"}
    },
    {
      "resource": {"resourceType": "Bundle", "type": "searchset", "...": "..."},
      "response": {"status": "200 OK"}
    },
    {
      "resource": {"resourceType": "Bundle", "type": "searchset", "...": "..."},
      "response": {"status": "200 OK"}
    },
    {
      "resource": {"resourceType": "OperationOutcome", "...": "..."},
      "response": {"status": "404 Not Found"}
    }
  ]
}

4. Compare Transaction vs Batch

CharacteristicsTransactionBatch
Atomicity✅ All-or-nothing❌ Independent
Internal references✅ urn:uuid: resolved❌ Not supported
Failure handlingFull rollbackEach entry returns its own status
PerformanceSlower (transaction boundary)Faster (parallel possible)
Use casesRelated data, needs consistencyBatch reads, independent writes

5. Mixed Operations in Transaction

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "request": {
        "method": "PUT",
        "url": "Patient/patient-001"
      },
      "resource": {"resourceType": "Patient", "id": "patient-001", "active": true}
    },
    {
      "request": {
        "method": "DELETE",
        "url": "Observation/obs-old-001"
      }
    },
    {
      "request": {
        "method": "POST",
        "url": "Observation"
      },
      "resource": {"resourceType": "Observation", "status": "final"}
    },
    {
      "request": {
        "method": "GET",
        "url": "Condition?subject=Patient/patient-001",
        "ifNoneMatch": "W/\"5\""
      }
    }
  ]
}

6. Summary

  • Bundle — Container for many resources, 8 different types

  • Transaction — Atomic, all-or-nothing, use urn:uuid: for internal references

  • Batch — Independent processing, parallel, each entry returns its own status

  • Transaction is suitable for data integrity, Batch is suitable for performance. performance