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.