Claims Service — Sync Contract
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: SERVICE_OVERVIEW · Service Template · 02 DDD
Sync Policy Overview
| Aggregate | Policy | Conflict Resolution |
|---|---|---|
ClaimRecord | server_authoritative | Version-based optimistic concurrency |
Coverage | server_authoritative | Last-write-wins with updatedAt |
EligibilityTransaction | append_only | Immutable once created; new inquiry creates new record |
PriorAuthorization | server_authoritative | Version-based |
RemittanceRecord | append_only | Immutable once processed |
DenialCase | server_authoritative | Last-write-wins |
server_authoritative Policy
The claims-service is the sole authority for all claim and coverage state. No offline client may mutate these records. All writes route through the claims-service REST API.
Rationale: Claims and coverage data carry financial and regulatory consequences. Concurrent offline edits could produce duplicate claim submissions or invalid coverage states.
Optimistic Concurrency (ClaimRecord)
ClaimRecord uses an integer version field for optimistic locking on state-transition operations.
Update flow:
1. Client fetches claim: { claimId, version: 3, status: "ready" }
2. Client submits: PATCH /api/v1/claims/:id with X-Version: 3
3. Server checks: claim.version == 3 → proceed
4. Server increments version to 4, saves
5. If version mismatch → 409 CONFLICT with current resource body
Clients must:
- Store the
versionreturned with each GET or mutation response - Include
X-Version: <n>on any state-transition PATCH - On 409, re-fetch the resource, resolve locally, and retry
append_only Policy (EligibilityTransaction, RemittanceRecord)
Once created, these records are immutable:
EligibilityTransaction: A new inquiry always creates a new record. Old results are never updated in place; they expire viaexpiresAt.RemittanceRecord: OnceprocessedAtis set, no mutations are permitted. Corrections require a manual void+repost workflow via admin operations.
Downstream Consumer Guidance
Services consuming claims events (billing-service, patient-portal-service, population-health-service) should:
- Idempotency: Use the CloudEvents
id(outbox record ID) as an idempotency key. Re-processing the same event must be a no-op. - Event ordering: Events are produced in order within a single claim's lifecycle. Consumers that depend on ordering should use the
timefield for sorting within a givenclaimId. - Stale reads: Query projections derived from events may lag the source of truth by the relay latency (typically < 1s). Consumers needing authoritative state must call the claims-service API directly.
FHIR Sync
FHIR R4 resources (Claim, Coverage, ExplanationOfBenefit, etc.) are generated views over the internal data model. They are read-only from external consumers. The canonical state is always the internal Postgres record. FHIR resource IDs are stored in the internal record (fhirClaimId, fhirCoverageId, fhirEobIds) for traceability.