Development covered 2 Aug 2026 to 4 Aug 2026 (commit dates).
An idle game has to run on the player's device. The loop ticks while they are looking at it, keeps ticking while they are not, and cannot wait for a network round for every increment. It also has an economy, which means somewhere there is an authoritative record that the game does not get to argue with.
That combination gives every value two copies, and this stretch was mostly about the moment they disagree.
Reconcile in one direction, and mean it
The rule the project settled on is that reconciliation only ever runs one way. The authoritative record decides what you have; the local state is a mirror of it that is allowed to run ahead optimistically between syncs.
That sounds obviously correct and it has one sharp consequence that took me a while to accept. Anything the local game grants you that never reaches the record disappears at the next sync. Not corrupted, not partially applied: gone, because the mirror was rewritten from the record and the record never heard about it.
The temptation, every single time, is to soften it. Let the local side contribute what it holds. Take the larger of the two. Merge. Every one of those turns the mirror into a second source of truth, and now nothing in the system can say what a player actually owns, which is the exact property the design exists to guarantee.
So the fix is never at the reconciliation. It is at the grant. If an item can be earned on the device, then earning it has to reach the record, and the earning path is what changes.
The rewards that went missing
Three faults this stretch were the same fault in different costumes.
Materials gathered out in the world disappeared at the next sync, because gathering granted them on the device and told nothing else. Output from crafting disappeared while the ingredients stayed spent, which is the worst version, since the player paid. A reward that would not fit in the bag was accepted, marked as claimed, and dropped.
Each of these reads as a different bug and each is one omission: something granted a thing without going through the path that makes it real. Once the reconciliation direction is fixed and enforced, every one of these becomes findable by asking a single question of each faucet, which is a much better position than chasing the symptoms.
A field left out of the payload is a value that reverts
Related and quieter. A ranking board put everybody at the bottom, since the quantity it sorts on never appeared among the fields the game uploads.
Nothing errored. The value existed on the device, it was correct on the device, and it was simply not part of the conversation. This is the least visible way to break a local-first system: not disagreement between two copies, but one copy never being told.
The rule I would give my past self is that the set of fields being sent is itself a design artifact and deserves a list somebody maintains, rather than being whatever accumulated.
The write that undid itself
One good race, worth writing down for anyone with a debounced writer.
Saving is debounced by about a second and a half, which is right: state changes constantly and writing on every change would be silly. A separate routine wanted to set up a particular state and then reload, so it wrote the state and reloaded as two steps.
The pending debounced write from before the setup landed after it, so the reload came back to the old state. Intermittently, depending on timing, which is the worst kind.
Anything that writes on a delay needs a way to be flushed, and every operation that must observe its own write has to flush first. The general form: a delayed writer turns an ordering you assumed into an ordering you have to arrange.
Keep derived data out of the thing you send
Last one, on size. The save is by far the largest payload this game sends, and it goes up regularly, so anything that rides along in it is paid for repeatedly and forever.
A copy of ranking data had ended up inside it. It was not needed there, it could be requested when wanted, and it pushed the whole payload past the ceiling the project sets for itself. Anything derivable, anything presentational, anything that can be asked for on demand does not belong in the thing you write on a schedule.
The live build is Incremental RPG.



Top comments (1)
the crafting case sounds like it needs one recorded operation for both sides: spend ingredients and grant output, or neither. fixing only the missing output write still leaves the player paying if that write fails. does the authoritative record treat crafting as one transaction, or reconcile the two entries by an operation id?