Prevent FHIR resource conflicts using ETags

This page explains how to use entity tags (ETags) for concurrency management with FHIR resources in the Cloud Healthcare API. ETags help prevent data loss and improve application performance by enabling optimistic concurrency control and client-side caching.

Understand ETags

An ETag serves as a unique identifier for the current state of a FHIR resource on the server, similar to a version number. Each time a FHIR resource is created or modified, a new ETag value is generated.

You can use ETags to ensure data integrity and optimize performance in the following situations:

  • To ensure optimistic concurrency control: When you include an ETag in a request to modify a FHIR resource, the Cloud Healthcare API verifies if the ETag matches the latest version of the FHIR resource on the server. This helps prevent one client from accidentally overwriting changes made by another client, also called a write-write conflict or the "lost update problem".

  • Sending conditional requests: ETags allow clients to conditionally send requests only when specific conditions are met. This optimizes data retrieval and reduces unnecessary network traffic. For example, you can send conditional requests using the following HTTP headers:

    • If-Match: The request only succeeds if the provided ETag matches the current ETag on the server. This ensures you're updating the expected version of the FHIR resource.
    • If-None-Match: The request only succeeds if the provided ETag doesn't match the current ETag on the server. This lets you know if your locally cached version of a resource is still current, reducing the need to fetch the full resource from the server each time. This is commonly used for efficient caching.

FHIR ETags use weak validation, meaning they might not be identical across different server instances, but they still effectively track resource changes.

Get an ETag

The following samples show how to get the ETag of a FHIR resource.

The ETag is included in the full HTTP response header when you get the contents of a FHIR resource. The ETag matches the Meta.versionId in the FHIR resource.

Before using any of the request data, make the following replacements:

  • PROJECT_ID: the ID of your Google Cloud project
  • LOCATION: the dataset location
  • DATASET_ID: the FHIR store's parent dataset
  • FHIR_STORE_ID: the FHIR store ID
  • FHIR_RESOURCE_TYPE: the FHIR resource type
  • FHIR_RESOURCE_ID: the FHIR resource ID

curl

Use the fhir.read method. The -verbose flag returns the HTTP headers in the response, which contain the ETag.

curl -X GET \
    -verbose \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID"

The response contains the following:

< etag: W/"ETAG_VALUE"

PowerShell

Use the fhir.read method. The -Headers flag returns the HTTP headers in the response, which contain the ETag.

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
    -Method GET `
    -Headers $headers `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID" | Select-Object -Expand Headers

The response contains the following:

ETag                   {W/"ETAG_VALUE"}

Manage concurrency when updating a FHIR resource

The following samples show how to include an ETag when updating a FHIR resource.

The samples use If-Match, which has the following behavior:

  • If the ETag matches the current ETag of the FHIR resource on the server, the update succeeds, and the server generates a new ETag for the updated resource. This ensures you're updating the expected version of the FHIR resource.

  • If the ETag doesn't match, the update fails with a 412 Precondition Failed error, indicating another client has modified the resource since the original ETag was fetched. This prevents data loss from accidental overwrites.

Before using any of the request data, make the following replacements:

  • ETAG_VALUE: the ETag value of the FHIR resource
  • PROJECT_ID: the ID of your Google Cloud project
  • LOCATION: the dataset location
  • DATASET_ID: the FHIR store's parent dataset
  • FHIR_STORE_ID: the FHIR store ID
  • FHIR_RESOURCE_TYPE: the FHIR resource type
  • FHIR_RESOURCE_ID: the FHIR resource ID

curl

Use the fhir.update method.

curl -X PUT \
    -H "If-Match: W/\"ETAG_VALUE\"" \
    -H "Content-Type: application/json; charset=utf-8" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -d @request.json \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID"

The response contains the updated FHIR resource.

PowerShell

Use the fhir.update method.

$cred = gcloud auth print-access-token
$etag = W/\"ETAG_VALUE\""
$headers = @{
  "Authorization" = "Bearer $cred"
  "If-Match"      = "$etag"}

Invoke-WebRequest `
    -Method PUT `
    -Headers $headers `
    -InFile request.json `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID" | Select-Object -Expand Content

The response contains the updated FHIR resource.

Implement client-side caching

You can use ETags to implement client-side caching, which accelerates data retrieval and contributes to a smoother, more responsive user experience.

To retrieve a previously cached FHIR resource, you can include the cached ETag in the If-None-Match header, which has the following behavior:

  • If the ETags match, the server responds with 304 Not Modified, and the client uses its cached copy. This saves bandwidth and reduces the server load.

  • If the ETags don't match, the server sends the updated FHIR resource and its new ETag, allowing the client to refresh its cache.

The following samples show how to get the contents of a FHIR resource using an ETag that matches the ETag on the server.

Before using any of the request data, make the following replacements:

  • ETAG_VALUE: the ETag value of the FHIR resource
  • PROJECT_ID: the ID of your Google Cloud project
  • LOCATION: the dataset location
  • DATASET_ID: the FHIR store's parent dataset
  • FHIR_STORE_ID: the FHIR store ID
  • FHIR_RESOURCE_TYPE: the FHIR resource type
  • FHIR_RESOURCE_ID: the FHIR resource ID

curl

Use the fhir.read method. The -verbose flag returns the HTTP headers in the response, otherwise no response is returned.

curl -X GET \
    -H "If-None-Match: W/\"ETAG_VALUE\"" \
    -v \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID"

The response contains a 304 Not Modified status code.

PowerShell

Use the fhir.read method. The -Headers flag returns the HTTP headers in the response, otherwise no response is returned.

$cred = gcloud auth print-access-token
$etag = W/\"ETAG_VALUE\""
$headers = @{
"Authorization" = "Bearer $cred"
  "If-None-Match"      = "$etag"}

Invoke-WebRequest `
    -Method GET `
    -Headers $headers `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID" | Select-Object -Expand Headers

The response contains a 304 Not Modified status code.