Interview concept

Offline Sync And Conflict Resolution For Merchant State

Asked of: Software Engineer

Last updated

Architecture diagram showing offline merchant clients syncing versioned operations through an API, with idempotency, optimistic concurrency, conflict resolution, and retry paths.

What's being tested

This topic tests whether you can design a distributed state synchronization system that remains correct under disconnection, retries, concurrent edits, and stale clients. The interviewer is probing your command of versioning, idempotency, conflict detection, and deterministic resolution—not merely whether you can copy records between devices. Affirm cares because merchant configuration can affect checkout behavior, eligibility, pricing, and servicing; silently overwriting valid state can create financial, compliance, or operational incidents.

Core knowledge

  • Define the consistency model before choosing an algorithm. Offline clients usually require eventual consistency, but sensitive merchant fields may require server serialization, explicit approval, or fail-closed behavior rather than last-write-wins.

  • Model a sync unit as an operation or versioned mutation, not just a full snapshot: {entity_id, operation_id, base_version, payload, client_id, timestamp}. Operations enable replay, auditability, selective conflict handling, and efficient delta sync.

  • Use idempotency keys for every upload. The server stores operation_id results or deduplicates through a unique constraint, so retries after timeouts cannot apply the same mutation twice. This is essential because “at least once” delivery is normal.

  • A scalar server version detects stale writes: the client sends base_version = 41, and the server accepts only if the current version is 41, then commits version 42. This is optimistic concurrency control; reject or merge when the precondition fails.

  • Last-write-wins is simple but dangerous. Wall clocks can be skewed, delayed edits can overwrite newer intent, and timestamps do not prove causality. If used, prefer server-assigned ordering and document which fields tolerate data loss.

  • Version vectors represent causality across replicas: each client tracks counters such as {A: 7, B: 3}. Vector x dominates y when every component is at least as large and one is greater; incomparable vectors indicate concurrent updates.

  • CRDTs provide deterministic convergence when the data type supports their merge laws. G-Counters suit monotonic increments, observed-remove sets suit membership, and LWW registers suit simple values; arbitrary business rules often need domain-specific server logic instead.

  • Prefer field-level or entity-level conflict boundaries deliberately. Merging independent fields can preserve more user intent, but may create invalid combinations—for example, a changed currency and unchanged amount. Validate the merged candidate atomically.

  • Maintain tombstones for deletions. Without a durable deletion marker, an old offline client can resurrect a removed merchant record during its next upload. Garbage-collect tombstones only after all relevant replicas have acknowledged a safe synchronization boundary.

  • Use a pull/push protocol with a sync cursor or log sequence number: upload pending mutations, receive accepted results and conflicts, then pull changes after the last acknowledged cursor. Advance the cursor only after durable local application.

  • Separate transport retries from application outcomes. A timeout means “unknown,” not failure; retry with the same idempotency key. Return explicit statuses such as accepted, already_applied, conflict, invalid, and unauthorized.

  • Protect against stale or malicious clients with authorization at apply time, not only at login. Check merchant scope, field permissions, schema version, and business invariants on every mutation; never allow offline mode to bypass server-side policy.

Worked example

Representative design prompt: Design offline sync and conflict resolution for merchant state. In the first 30 seconds, I would clarify which merchant fields are editable offline, whether multiple users or devices can edit concurrently, whether deletion is supported, and which fields are too sensitive to merge automatically. I would state that the server is authoritative, clients may queue mutations while disconnected, delivery is at least once, and the system must never silently lose a valid financial configuration. I would organize the answer around the local mutation queue, the server-side versioned write path, the pull/push synchronization protocol, and conflict resolution plus observability. Each mutation would carry an idempotency key, entity version, client identity, schema version, and operation payload; the server would atomically validate authorization, compare the base version, apply or reject the mutation, and append an audit event. A key design decision is whether to use full-record last-write-wins or field-level merging; I would choose explicit conflict responses for high-risk fields and narrowly scoped merges only where invariants can be checked. Clients would persist accepted changes and unresolved conflicts locally, retry unknown outcomes safely, and use tombstones to prevent deleted state from reappearing. I would close by saying that, with more time, I would specify the wire protocol, migration behavior, compaction rules, and failure-injection tests for duplicate, reordered, and partially applied messages.

A second angle

The same design changes when the state is a merchant catalog or availability set rather than a payment-critical configuration. An observed-remove set or operation-based CRDT may be appropriate because independent additions can merge automatically and temporary divergence is acceptable. The candidate should still define deletion semantics, duplicate operation handling, and what happens when two devices modify the same item concurrently. The key contrast is that the business risk permits more automatic convergence, while sensitive configuration should favor explicit server rejection and human resolution.

Common pitfalls

Pitfall: Treating timestamps as a reliable ordering mechanism is analytically wrong under clock skew and offline delays. Use server versions, causal metadata, or explicitly acknowledge the data-loss tradeoff of last-write-wins.

A tempting implementation answer is “the client retries the request if it times out.” That is incomplete because the server may have committed successfully before the response was lost. Explain idempotency keys, durable deduplication, and the distinction between an unknown outcome and a rejected operation.

Many candidates jump directly to CRDTs as a universal solution. CRDTs solve convergence for suitable data types, not authorization, cross-field invariants, audit requirements, or business-specific conflict semantics; demonstrate where a transactional server-side merge is safer.

Connections

Expect pivots to optimistic concurrency control, event sourcing, message delivery semantics, schema evolution, and disaster recovery. You may also need to discuss how sync state is tested with deterministic replay, fault injection, and property-based convergence checks.

Further reading

Related concepts