Build log · Month 10 of 12
Where the Data Lives
offline-first vs cloud-first, the decision that shapes every syncing app. Echo's cloud-synced voice journal, Calc+'s local vault, conflict resolution, and privacy as architecture.
- Day 251
This month: where your data lives. The most consequential architecture call in any app that stores something, and I make it per-app. Echo (voice journal) is cloud-synced. Calc+ (vault) is local-only. Same studio, opposite answers. The data model IS the promise.
- Day 252
Calc+ is a calculator with a hidden vault, and its whole value is that your private stuff never leaves the device. So it's local-only, encrypted at rest, no server, no account. The most secure architecture has nothing to breach. Sometimes the best backend is none.
- Day 253
Echo is the opposite: a voice journal you want on every device and never want to lose, so it's cloud-first with sync. The tradeoff I accept: encryption, sync conflicts, and holding your recordings. Convenience has an infrastructure cost, and it's mine.
- Day 254
Offline-first isn't "works offline sometimes." It means the local store is the source of truth and the network is an enhancement. Fully usable on a plane; sync reconciles later. Most apps do it backwards and feel broken the second signal drops.
- Day 255
Conflict resolution is the tax on sync. Edit an entry offline on your phone, edit it on your laptop, both sync. Now what? Last-write-wins is simple and silently destroys data. I merge and flag instead. Never silently delete a user's words.
- Day 256
🧵 Thread: offline-first vs cloud-first, and how I choose per app.
- Ask: what happens with no signal? If it must "fully work," you're offline-first.
- Offline-first = local store is truth. Cloud-first = server is truth, cache is convenience.
- Sync's real cost is conflict resolution. Last-write-wins loses data silently. Merge or flag.
- Privacy-critical (Calc+ vault)? Local-only. No server = nothing to breach.
- Multi-device + loss-averse (Echo)? Cloud-first with E2E. You take the responsibility.
- Day 257
Sync bug of the month: an entry edited offline got overwritten by an older cloud version on reconnect, because I compared timestamps from two skewed device clocks. Never trust device clocks for ordering. I moved to logical version vectors. Wall-clock time is a lie.
- Day 258
Echo's recordings are E2E encrypted before they ever hit my server, so I cannot listen to your journal even if compelled to. A deliberate constraint: make the private thing impossible for me to access, not just against-policy. Architecture beats promises.
- Day 259
The cost of E2E on Echo: no server-side transcription or search, because the server sees ciphertext. So transcription runs on-device. Slower, but the alternative is decrypting your journal on my servers, which defeats the point. I chose privacy loudly.
- Day 260
Local-first has a brutal failure mode: device loss. Calc+ is local-only, so lose the phone with no backup and the vault is gone, by design. I make backup explicit and optional (encrypted export), not a silent sync to a cloud the user opted out of.
- Day 261
Optimistic UI in a sync app is a promise you might break. Show the entry saved instantly (great UX), but if sync fails you reconcile honestly, not leave a phantom "saved" thing that vanishes on the next device. Optimism is fine if you reconcile; a lie if you don't.
- Day 262
Echo syncs metadata eagerly and audio lazily. You see your journal list instantly on a new device; recordings stream on demand. Syncing gigabytes of audio on first launch would feel broken. Sync what they see now; defer what they'll need later.
- Day 263
Opinion: most apps should be more offline-first than they are. Treating the network as always-present is a bug that only shows up when users need the app most — the subway, the flight, the dead zone. Design for disconnection; connection is the bonus.
- Day 264
Migrations are terrifying in a synced app: change the local schema and you must migrate every device independently, some offline for weeks. Schema changes are versioned and backward-compatible for several releases. You can't force-update a phone in a drawer.
- Day 265
🧵 Thread: making data portable, so users trust you with it.
- Echo: one-tap "export everything" — recordings, decrypted, on your device.
- Calc+: encrypted export of the vault. You hold the key, not me.
- No lock-in, no proprietary format they can't read elsewhere.
- Deletion is real: purge server data, revoke tokens, in-app, not via support email.
- If a user can't take their data and leave, they never fully trusted you with it.
- Day 266
The sync-status honesty signal: Echo shows "synced," "syncing," or "offline — will sync later" plainly. Hiding sync state creates "did my entry save??" anxiety. Surface where the data is, even when it's "not backed up yet." Honest status beats silent uncertainty.
- Day 267
CalGym and TracePace (GPS) forced the offline question hardest: you're in the mountains recording a run with no signal. TracePace is offline-first — the GPS track lives locally, synced when back in range. An outdoor app that needs signal is a contradiction.
- Day 268
Battery is a data-architecture concern for TracePace: continuous GPS drains phones. I batch location writes, lower the sample rate when stationary, and never hunt for signal in a dead zone. Offline-first is also battery-first. Defer the sync until it's cheap.
- Day 269
Month 10 lesson: "where does the data live" is the product's core promise about privacy, reliability, ownership. Local-only says "we can't see it." Cloud-sync says "we'll keep it safe everywhere." Pick deliberately, per app, and let the promise drive the architecture.
- Day 270
Next month: procedural and generative content done legally — the engine behind Cipher's puzzles and Vertex's levels, and why "compute it or compose it originally, never scrape it" is both an ethical line and a moat. Infinite content without infinite risk.
- Day 271
A meta-point from data month: every architecture choice is invisible until the moment it isn't — the lost entry, the breach, the dead-zone failure. You engineer for the bad day nobody sees. Good architecture is a promise you keep on the worst day.
- Day 272
The fleet's data architectures are deliberately inconsistent, and correct. A vault, a journal, and a GPS tracker have opposite needs; one-size-fits-all sync would be the mistake. The studio shares code, not blind uniformity. Reuse the engine, tailor the promise.
- Day 273
[N] users now trust the fleet with some form of data — locally or synced — and that number, however small, changes how I sleep. Holding people's recordings and vaults is a responsibility that scales with trust. Better it weigh on me now than surprise me later.
- Day 274
Distribution note, because it never stops: "your data never leaves the device" (Calc+) and "encrypted so even I can't read it" (Echo) are marketing, not just architecture. Privacy done seriously is a story worth telling. The engineering and the pitch are one sentence.
- Day 275
Day 275. Ten months in. The fleet's data foundations are deliberate, per-app, and honest about their tradeoffs. Two months of runway left. Next I harvest the content engine that makes the games sustainable, then close the year with the hardest post: the honest retro.