Skip to main content

Immunizations Service — Sync Contract

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template

1. Sync Philosophy

The immunizations-service is primarily server-authoritative: the server holds the canonical immunization history. Mobile clients (health workers using offline-capable devices) may record immunizations while offline and sync when connectivity is restored. Conflicts are resolved deterministically using administeredAt timestamp and version field.

2. Conflict Policies by Aggregate

AggregateConflict policyResolution rule
ImmunizationRecordServer-authoritative with offline write bufferClient submits queued records on reconnect; server deduplicates on clientMutationId; server version wins for amendments
ImmunizationForecastServer-authoritativeForecast is always server-computed; client may cache read-only
ContraindicationRecordServer-authoritativeClient cannot create contraindications offline

3. Offline Scenarios

ScenarioBehaviour
Clinician records vaccination offlineRecord stored in device queue with clientMutationId UUID; synced to server on reconnect
Same patient gets duplicate offline records on two devicesServer processes both clientMutationId values; first one persisted; second returns 409 DUPLICATE_MUTATION if identical, or creates separate record if different administeredAt
Patient forecast stale on deviceDevice shows cached forecast with calculatedAt timestamp; server refreshes on sync completion
Registry sync attempted while national registry unreachableSync job created and queued; retried with exponential backoff; does not block local recording

4. Sync Sequencing

When a mobile client reconnects, it should follow this order:

  1. Push queued ImmunizationRecord creates (POST /v1/immunizations) — largest priority.
  2. Push queued ContraindicationRecord creates if any.
  3. Pull updated forecast (GET /v1/immunizations/forecast/:patientId).
  4. Pull any updated patient records that changed since last sync (GET /v1/immunizations?patientId=&from=<lastSyncAt>).

5. Version Field Usage

  • All ImmunizationRecord mutations (amend, correct) require the current version in the request body.
  • Server increments version on each mutation.
  • If client version does not match server version, server returns 409 OPTIMISTIC_LOCK_CONFLICT.
  • Clients must re-fetch the record, re-apply their change, and resubmit.

6. Idempotency

  • POST /v1/immunizations and POST /v1/immunizations/refusal accept clientMutationId in the request body.
  • Server caches processed clientMutationId in Redis for 24 hours.
  • Duplicate submission returns the original 201 response (idempotent).
  • After 24 hours, a new submission with the same clientMutationId will be treated as a new record.