agentsclimarketplace

Conflict resolution backend

Skill almasumdev/awesome-mobile-backend-agent-skills/.github/skills/sync/conflict-resolution-backend

Agent skills for the backend-for-mobile layer: APIs, auth, push, sync, and BaaS integrations.

Install
npx -y skills add almasumdev/awesome-mobile-backend-agent-skills --skill conflict-resolution-backend

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Resolve concurrent writes from multiple mobile devices -- last-write-wins, 3-way merge, and vector clocks. Use when designing server-side merge semantics for offline-capable apps.

SKILL.md

5.6 KB, as published. Nobody here has run it

Conflict Resolution (Backend)

Instructions

Two devices edit the same record offline, then sync. The server must decide which edit wins, or how to combine them. Pick the simplest strategy that meets the domain requirement; complex schemes are expensive and buggy.

1. Conflict Detection

A mutation carries base_rev -- the revision the client saw before editing (see sync-protocols). Conflict exists when the server's current rev > base_rev for that entity.

client_A edits at base_rev=10  -> server rev is now 12  -> CONFLICT

Never auto-resolve silently for domains where silent loss is unacceptable (money, medical, legal).

2. Last-Write-Wins (LWW)

Default for domains where staleness is tolerable (profile bio, preferences, cache-like data).

Mechanism: the incoming mutation overwrites if it is newer by some tie-breaker (server timestamp on arrival, or an HLC). Include a monotonic updated_at so clients can display "last edited on device X".

UPDATE articles
   SET data = $new_data, rev = nextval('article_rev'), updated_at = now()
 WHERE id = $id AND ($base_rev IS NULL OR rev <= $base_rev + GRACE);

Pros: simple. Cons: loses the loser's work without telling anyone.

Mitigations: keep a short audit trail of overwritten versions so a user can recover.

3. Reject-on-Conflict (Optimistic Concurrency)

For domains where losing a write silently is unacceptable (documents, forms, inventory counts).

Server replies 409 CONFLICT with the current entity. The client presents a merge UI or pulls + re-applies its change.

{ "status": "conflict", "current_rev": 4815, "current_entity": { "...": "..." } }

Clients must handle this explicitly -- not a retry loop.

4. Three-Way Merge

Works when entities have independently mergeable fields.

Server stores: base (the common ancestor), theirs (current server state), ours (incoming). For each field:

  • If only ours differs from base -> take ours.
  • If only theirs differs from base -> take theirs.
  • If both differ -> conflict on that field.

Best for structured records with many fields (contact card, settings object).

// Node/TS
function merge<T extends object>(base: T, ours: T, theirs: T): { merged: T; conflicts: string[] } {
  const merged: any = { ...theirs };
  const conflicts: string[] = [];
  for (const k of Object.keys(ours) as (keyof T)[]) {
    const b = base?.[k], o = ours[k], t = theirs[k];
    if (deepEqual(o, b)) continue;            // ours unchanged
    if (deepEqual(t, b)) { merged[k] = o; continue; } // theirs unchanged
    if (deepEqual(o, t)) continue;            // same change
    conflicts.push(k as string);
  }
  return { merged, conflicts };
}

Return conflicts to the client; if empty, commit. Otherwise 409 with the conflicting field names.

5. Vector Clocks and HLC

Useful in multi-region or peer-to-peer systems where no single authoritative clock exists. Each node increments its own counter; the vector {nodeA: 7, nodeB: 3} lets you detect concurrent edits vs causal descendants.

In practice, most mobile backends have one authoritative region at a time (failover is rare). A single monotonic rev plus updated_at is usually enough. Reach for vector clocks only if you need eventual consistency across active regions.

Hybrid Logical Clocks (HLC) sit between wall-clock and logical clocks and tolerate small clock skew; a good choice when you want "mostly wall-clock" with logical tie-breakers.

6. Field-Level Last-Write-Wins

For records with many independent fields (settings), LWW per field reduces false conflicts:

  • Each field stores {value, updated_at, updated_by}.
  • Merges take the field with the highest updated_at.

This is essentially an LWW-map CRDT; see crdt-basics.

7. Append-Only Streams

For activity logs, message histories, and events, avoid in-place edits. Writes are appended; conflicts do not exist (each device's events interleave by server timestamp on arrival).

8. Audit Trail

For any non-trivial strategy, keep a version history table:

CREATE TABLE article_versions (
  id       TEXT,
  rev      BIGINT,
  author   TEXT,
  data     JSONB,
  PRIMARY KEY (id, rev)
);

Enables undo, forensic debugging, and "history" UIs. Prune on a retention policy.

9. Client UX

  • If the resolution is automatic and lossless (CRDT, additive), apply silently.
  • If lossy (LWW), consider a toast: "Your change was merged with an edit from iPad."
  • If reject-on-conflict, show a merge screen with ours vs theirs.

10. Testing

Conflict code is high-risk; test with explicit scenarios:

  • Same field, same value edited twice -> no conflict.
  • Disjoint fields edited -> merged cleanly.
  • Same field, different values -> conflict reported.
  • Delete vs edit -> domain decision (usually delete wins, edit discarded, with audit trail).

Checklist

  • Strategy chosen per entity type and documented (LWW, reject, 3-way, append-only).
  • base_rev flow in place for optimistic concurrency.
  • Audit trail of versions kept for non-trivial strategies.
  • Client UX defined for automatic vs user-visible resolution.
  • No silent data loss for domains that do not tolerate it.
  • Conflict unit tests cover disjoint, overlapping, delete-vs-edit cases.
  • HLC or vector clocks considered and justified (or rejected).
  • Retention / vacuum policy for history tables documented.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.