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
| Aggregate | Conflict policy | Resolution rule |
|---|---|---|
ImmunizationRecord | Server-authoritative with offline write buffer | Client submits queued records on reconnect; server deduplicates on clientMutationId; server version wins for amendments |
ImmunizationForecast | Server-authoritative | Forecast is always server-computed; client may cache read-only |
ContraindicationRecord | Server-authoritative | Client cannot create contraindications offline |
3. Offline Scenarios
| Scenario | Behaviour |
|---|---|
| Clinician records vaccination offline | Record stored in device queue with clientMutationId UUID; synced to server on reconnect |
| Same patient gets duplicate offline records on two devices | Server 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 device | Device shows cached forecast with calculatedAt timestamp; server refreshes on sync completion |
| Registry sync attempted while national registry unreachable | Sync 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:
- Push queued
ImmunizationRecordcreates (POST /v1/immunizations) — largest priority. - Push queued
ContraindicationRecordcreates if any. - Pull updated forecast (
GET /v1/immunizations/forecast/:patientId). - Pull any updated patient records that changed since last sync (
GET /v1/immunizations?patientId=&from=<lastSyncAt>).
5. Version Field Usage
- All
ImmunizationRecordmutations (amend, correct) require the currentversionin the request body. - Server increments
versionon each mutation. - If client
versiondoes not match serverversion, server returns 409OPTIMISTIC_LOCK_CONFLICT. - Clients must re-fetch the record, re-apply their change, and resubmit.
6. Idempotency
POST /v1/immunizationsandPOST /v1/immunizations/refusalacceptclientMutationIdin the request body.- Server caches processed
clientMutationIdin Redis for 24 hours. - Duplicate submission returns the original 201 response (idempotent).
- After 24 hours, a new submission with the same
clientMutationIdwill be treated as a new record.