The Fastest Network Request Is the One You Never Make
Keeping data and smarts on your own device, and why it changes the design
Open a document in a cloud app on a plane and you get a spinner over text you already had. That is not a bug. It is the app being honest about how it was built. The server owns the truth, and you are just a window looking at it.

In 2019, the researchers at Ink & Switch named the alternative. Local-first software keeps the main copy of your data on your device. It syncs in the background. Syncing means quietly copying your changes to other devices and copying theirs back. The network becomes a bonus, not a requirement. Think of it like this. Local-first is notes in your own notebook, always in your pocket. Cloud-first is notes you can only read when the library is open. They listed seven goals. Among them: it is fast, it works offline, it is your data, and it lasts forever.
In local-first applications, the availability of another computer should never prevent you from working.
What actually changes in the interface
The loading spinner mostly disappears, and that one change spreads further than people expect. Once reads happen on your device, every action lands in under a tenth of a second. That is fast enough to feel instant, like flicking a light switch. Search updates as you type. Filters become play, not a careful request. Undo costs nothing. People start poking at their data instead of questioning it, and that change in behaviour is worth more than the milliseconds.
- In-memory read100 ns~100 ns
- On-disk local1 ms~1 ms SSD
- Same-region server25 ms~25 ms there and back
- Cross-continent150 ms~150 ms there and back
The hard part is merging, and it is a design problem
If two people edit the same thing while offline, something has to decide what the result means. Picture two people editing one shopping list. This is where CRDTs come in. A CRDT is a way to merge two people's edits automatically, with no server picking a winner. It is the technology behind Automerge and Yjs. It promises that every device ends up with the same result. It cannot promise that result is what a person actually wanted.
Text merges nicely. A shared counter merges fine. But say two people each grab the last free room. The merge is mathematically valid and completely wrong in real life. So the interface has to carry the idea of a merge that needs a human. And someone has to design what that looks like, without making people doubt their own data.
- Show the merge, do not hide it. When a background sync changes something in front of the user, mark it. Quietly changing what someone is looking at is the fastest way to lose their trust.
- Keep the intent, not just the bytes. Store enough history to say Priya moved this to Tuesday while you were offline, instead of showing a bare change with no name on it.
- Design for later, not instant. A sync badge should say synced, not saved. In a system spread across devices, saved is a small lie, and people feel it when it breaks.
Now put the model on the device too
The same logic applies to AI. Running a hosted model means a trip to a server and back, which costs several hundred milliseconds before the first word appears. Fine for a big question. Too slow for anything that should feel like typing. WebGPU arrived in Chrome in 2023 and is now widely available. It lets a browser tab run a small model on your own graphics chip, with no server in the loop.
This creates a choice that did not exist three years ago. Fast, constant help belongs on the device: autocomplete, ranking, sorting, search over your own notes. There it is free and private. Slow, high-value thinking belongs in the cloud, where the user has already agreed to wait.
Be honest: local-first is often the wrong choice
The case above is real, but it is only half the ledger. A capable on-device model is big, and it has to live in the device's memory to be fast. Take Phi-3-mini, a small model built to run on a phone. It has 3.8 billion parameters. Squeezed down to four bits it still takes about 1.8 gigabytes, and Microsoft showed it running on an iPhone 14, fully offline, at over twelve words a second. That is a genuine achievement. It is also 1.8 gigabytes sitting in memory, a large slice of a phone that is also running everything else. Switch apps and the system can evict it, so you pay the load again. Anything much bigger than a few billion parameters does not fit at all.
Cold start is the next bill. Before the first word, the device has to download that model, hundreds of megabytes to a couple of gigabytes, and compile it for the local chip. A server never charged the user for this. The first session on a new device does.
Then there is power. A cached read off local disk costs almost nothing. Sustained generation runs the GPU or neural chip hot, drains the battery, and warms the device in your hand. I will not pretend to a single universal number, because it depends on the chip and the model. But a laptop on battery throttles, and a phone gets warm, and users notice both.
Updating is the tradeoff people forget. A hosted model you improve once, for everyone, overnight. An on-device model is thousands of copies scattered across the world. Shipping a better version means every device re-downloads gigabytes, on its own schedule, and you keep supporting the old versions until they catch up. A flaw in the model stops being a deploy and becomes a fleet update.
So the round trip to a server is genuinely right more often than local-first fans admit. Send it away when the model has to be frontier quality, when it needs fresh or shared data the device cannot hold, when the task is rare enough that a short wait is fine, or when the device is too weak or too full to carry the model at all. Crossing the ocean is the correct call whenever what waits on the far side cannot fit on this side.
- Fast, repeated actions on personal data
- Works offline and stays private
- A small model that fits in memory
- The same task, many times a minute
- Frontier quality the device cannot match
- Fresh or shared data the device lacks
- A rare task where a short wait is fine
- A weak or full device that cannot hold the model
One more tradeoff cuts against the privacy story. Putting the model on the device also hands the model to whoever owns the device. The weights ship with the app, and a determined person can pull them out. If the model is the product, on-device means giving away the thing you sell. A hosted model stays behind an interface you control. Local-first protects the user's data and exposes the maker's model. Which one matters more depends on whose secret you are keeping.
It is also worth puncturing the idea that local-first means no server. Most real local-first apps still run one, to relay changes between devices, to hold a backup, to serve people who share a document but are never online at the same time. Ink and Switch call it a sync server, and the honesty is in the name. It syncs, it does not own. But it is still infrastructure you build, pay for, and keep alive. Local-first moves the server off the path of your click. It does not always delete it. Anyone selling local-first as free of servers is selling the poster, not the product.
And building that sync is not a weekend. Merging edits correctly, handling a device that was offline for a month, migrating the data format after you have shipped, these are the hard, unglamorous parts, and they land on you instead of on a database vendor. The instant, offline, private product the user feels is bought with real engineering the user never sees. That is a fair trade for the right app. It is a waste for one that a plain server would have served just fine.
Why I think this becomes the default
| What you compare | Cloud-first | Local-first |
|---|---|---|
| Speed | A trip to the server every time | Reads on device, instant |
| Offline | Spinner or dead | Fully usable |
| Ownership | Server owns the truth | Your device owns the truth |
| Merging edits | Last save on the server wins | CRDT merge, always lines up |
| Cost at scale | Pay per call and per download | Almost nothing per call |
Privacy rules keep getting stricter. AI costs keep mattering as you grow. And people keep learning that software they do not control can vanish. Local-first answers all three at once. The data never leaves. The AI costs nothing per call. And the app keeps working even when the company behind it does not.
That last point is the one that moves me. Almost everything we build today dies the moment a server is switched off. Local-first is the first approach in twenty years that takes one idea seriously: a person's work should outlive the product that made it.
The merge problem does not shrink as you grow. It grows. Two people editing rarely clash. A team of fifty editing one shared space, half of them offline on a train, produces clashes daily, and every clash is a small design problem you now own. The cost of a merge that needs a human is paid by your users, in confusion, unless you have designed the moment it happens. Local-first hands you a better default and a harder edge case in the same box.
What to do on Monday
Do not port your whole app to a local database this week. Take the single interaction people repeat most, a search, a filter, a re-sort, and move just its data onto the device so that one action lands instantly. Leave everything else on the server for now. Then measure whether people use that feature more once it stops asking the network for permission. If they do, you have earned the case to go further. If they do not, you just saved yourself a migration you did not need. Let where the truth lives be a decision you earn per feature, not a religion you adopt all at once.