C.W.K.
Stream
Lesson 02 of 04 · published

The Network Is Never on the Save Path

~10 min · local-first, outbox, state-machine, idempotent

Level 0Cold Hearth
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Neither Office reachability nor Pippa availability may stand between Dad and a captured thought."

Save Locally First, Always

The strongest promise Vesta makes is that a thought is never lost to a dead network. That promise has a precise engineering shape: local write precedes network sync, always. When you capture a crumb, it commits to a device-local outbox first and confirms immediately — before any request leaves the phone. Only later, when the engine is reachable, does the outbox drain the crumb up to the server. The network is not on the critical path to 'saved'; it's on the path to 'synced', which is a different, later thing.

This is the Switzerland lesson, inherited from Waystone: a hotel network that half-works, a tunnel with no signal, an engine that's asleep — none of them may sit between you and a captured thought. If saving required the server, then every weak-signal moment would be a moment you couldn't journal, which is exactly the moments most worth capturing. Local-first turns the network from a precondition into an afterthought.

Put durability before delivery. A capture system must make the write durable on the device before it attempts to deliver it anywhere. Delivery can be retried; a thought you didn't save is gone. Confirm locally, queue for sync, and never let a network round-trip stand between the user and 'it's safe'.

The Outbox State Machine

The outbox makes that promise concrete with a small state machine. A crumb moves LOCAL_ONLY (written on device, not yet queued) to QUEUED (waiting to sync) to SYNCING (in flight) to SYNCED (the server acknowledged) — and if a drain fails, to FAILED_NEEDS_ATTENTION, surfaced plainly so nothing fails silently. The critical rule: the local payload is never deleted before an idempotent server acknowledgement. The crumb only leaves the device once the server has provably taken it, and because the acknowledgement is idempotent (keyed by a client-generated request id), a retry after an ambiguous failure can't create a duplicate.

Two more details make it trustworthy under real outages. Capture order survives: while the queue is non-empty, a new crumb joins the back of it rather than racing ahead, so your morning note can't sync after your afternoon one. And a server 4xx — a genuinely invalid payload — surfaces inline instead of queueing forever, because the outbox exists to defeat flaky networks, not to hide a bug the user needs to see.

Synced Is Not the Same as Saved

The mental shift this forces is healthy: 'saved' and 'synced' are two different states, and the UI must be honest about which one you're in. A crumb that's LOCAL_ONLY or QUEUED is already safe on the device — the thought is not going to be lost — but it hasn't reached the server yet. The stream surfaces that unsynced count openly, treating device storage as a staging area rather than the final archive. You're never left guessing whether a thought made it; the honest answer is always visible, and the safe state is reached the instant you finish typing.

Code

The outbox state machine·text
capture ─▶ LOCAL_ONLY ─▶ QUEUED ─▶ SYNCING ─▶ SYNCED
            (safe now)             │              (server ack'd,
                                   │               idempotent)
                                   └─▶ FAILED_NEEDS_ATTENTION
                                       (drain failed, shown plainly)

rules:
  * confirm at LOCAL_ONLY — the thought is safe before any request
  * local payload is NOT deleted until an idempotent SYNCED ack
  * new crumbs join the BACK of a non-empty queue (order survives)
  * a 4xx invalid payload surfaces inline — never queues forever
  * request id keys the ack -> a retry can't create a duplicate

External links

Exercise

Sketch the states a captured item passes through in a local-first system, from 'written on device' to 'confirmed by server'. Mark exactly which state means 'the user's data is safe' and which means 'delivered'. Then decide two things: when is it safe to delete the local copy, and what happens to a payload the server rejects as invalid. Those two decisions are where most offline systems quietly lose or duplicate data.
Hint
Safe-on-device must come strictly before delivered, and the local copy must survive until an idempotent acknowledgement — otherwise an ambiguous network failure either loses the item or duplicates it on retry. And a permanently-invalid payload must exit the retry loop, or it hides a real error behind an infinite 'syncing'.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.