A New Kind of Web App
Replicache removed the network from the critical path. Jazz removes it from the architecture. Local-first development that feels like Zustand and syncs like magic.
Earlier this year, I wrote about how sync engines like Replicache make web apps instant by removing the network from the critical path. The result was dramatically better UX and DX through simpler UI code.
That exploration changed how I think about what’s possible on the web. It also hinted at a bigger shift: what happens when the network isn’t merely hidden, but optional? This post follows that thread.
From Fighting the Network to Forgetting It
Replicache was my first real glimpse into what happens when you stop waiting for the network. Once the data lived locally, the UI got simpler and faster.
Components subscribed to local data and the UI stayed consistent. Loading states disappeared, invalidation headaches went away, and scattered optimistic updates turned into a single mental model. Technically, the logic still existed, but Replicache centralized it and moved the complexity out of my UI.

I admire Replicache for its sharp scope. It takes the place of React Query and tRPC. Nothing less, nothing more. That swap unlocks major UX and DX improvements, yet the rest of the stack stays intact. Mutations still run on the client for instant (optimistic) feedback and on the server for persistence.
In the end, Replicache is an optimization within the traditional three-tier architecture.
Beyond the Optimization
Local stores like Zustand feel effortless. Until you need that state to span more than one device.
But what if the local copy is the actual database? What if the client-side mutation is all we need?
Those questions led me to Jazz, a true local-first database that I used to build Tilly, my open source relationship journal.
Working with Jazz feels like working with Zustand: I describe the shape of my data, then read or write to it directly. Jazz adds three guarantees:
- Persistent by default
- Syncs between devices through a sync server
- Includes users, permissions, and file/image syncing out of the box
That single shift changes everything. It’s not a drop-in replacement like Replicache. It’s an architecture built around a new fact: the local copy is the database. And the server is optional.
A Horizontal Architecture
Once the database sits on the client, the system stops being vertical. It turns horizontal because every peer talks to the same Jazz database, and the sync server simply keeps those peers aligned. Building Tilly made that shift impossible to ignore: my phone and laptop both behaved like primary sources without any special cases.

A server becomes just another peer. You don’t write a server; you write server logic. You add it only if it has a real job: sending push notifications, calling an AI provider, making updates that need an authority. In Tilly, the server’s entire remit is nudging me to journal and proxying chat prompts to an AI provider. It provides optional functionality on top of an experience that works with or without a server.
If you start with Jazz, you can move fast because it’s a local data store, and enabling multi-device sync is as simple as pointing at a sync server URL. The existing client code keeps running while the server watches the same data model.
You still build features from the button to the database, but now they are much closer.
Where Logic Belongs
Most of my logic now sits next to the UI, right where it happens. A button click updates the database directly. There’s no context switch between client and server. Even when I imagine inviting collaborators, I still call the same helper that I wrote on day one, and Jazz carries the change across devices.
When I do write server logic, it’s minimal and focused only on the parts that belong there. This makes me faster and keeps the boundaries clean: local for interaction, server for capabilities.
A New Kind of Web App
Replicache showed me that UX and DX both improve when data is local. Jazz shows me that the data can live there entirely.
The network becomes a quiet background process, and you end up with a different kind of web app—one that’s a joy to build and a joy to use.