Built Different · 01

Why Linear feels instant

The same tiny issue tracker, built two ways. The left one asks the server before it changes the screen. The right one changes the screen first and syncs in the background, the idea at the core of Linear's sync engine. Drag the latency and click around.

Classic

click → request → wait → re-render
last click → screen
click a card to move it →
idlepolls every 5 s

Local-first

click → local store → re-render → sync later
last click → screen
C new · click to move
syncedlastSyncId 0

1. The screen never waits

A click updates an in-memory model and the UI re-renders in the same frame. The change goes into a transaction queue that talks to the server afterwards.

2. The data is already here

Everything lives in IndexedDB. Hit "Reload test": the right side paints from disk instantly, the left side has to ask the server again.

3. Changes arrive as deltas

The server stamps every change with a growing lastSyncId and pushes it to every client. Your teammate's edits just appear. If the server says no, the local change rolls back.