Prompt
Implement a G-Counter (Grow-only Counter) CRDT for an offline-first Expo/React Native app.
A G-Counter is a Conflict-free Replicated Data Type where each replica (e.g. a device with an Expo SecureStore-assigned replicaId) tracks its own increments in a private slot. Counters are persisted locally (AsyncStorage / expo-sqlite) and merged whenever the device reconnects — taking element-wise max guarantees the replicas converge without a server or consensus. The total value is the sum of all slots.
Write four functions:
createGCounter(replicaCount)— return an array ofreplicaCountzerosincrement(counter, replicaId)— return a new counter with slotreplicaIdincremented by 1merge(counterA, counterB)— return a new counter where each slot is Math.max of the twovalue(counter)— return the sum of all slots
Solution
Offline-first is the real interview topic here: a phone increments a counter on the subway, another device increments the same counter elsewhere, and when both come back online the app must converge without a server deciding who wins. The G-Counter's answer is structural: each replica writes only its own slot, so concurrent increments never touch the same data, and "conflict resolution" stops being a thing that can fail.
Why merge is element-wise Math.max and not addition: each slot is a monotonic counter owned by one writer, so the max of two observations of that slot is simply the most recent one. Max is commutative, associative, and idempotent — merge in any order, any number of times, through any gossip path, and every replica lands on the same state. The tests pin exactly those algebraic properties, because they are the correctness argument. Sum-merge fails idempotence: sync the same state twice and the count double-books.
value is the sum across slots — derived on read, never stored. In an Expo app the counter array lives in AsyncStorage keyed by a SecureStore-assigned replicaId; reconnect = exchange arrays, merge, persist. Note the trade-off honestly: grow-only means no decrement — the standard fix is a PN-Counter, two G-Counters (increments minus decrements).
Red flag: merging by summing, or incrementing another replica's slot "to correct it." Both destroy the single-writer invariant that makes convergence provable.
Say it: "Each replica owns one slot and merge is element-wise max — commutative, associative, idempotent — so replicas converge no matter how many times or in what order they sync."