Most web apps have a simple loop: user acts → request sent → server responds → UI updates. Every action waits on the network. Linear broke this entirely.
Traditional UIs block until the server responds. Optimistic UIs assume the server will agree and apply changes instantly. If it doesn't, they revert.
React re-renders by default propagate up then down the component tree. MobX observables allow surgical updates: only the components that subscribed to the exact changed property re-render.
status changes, only the status badge component re-renders — not the parent list, not the sidebar, not the header.
Linear migrated through four bundlers — Parcel → Rollup → Vite → Rolldown — optimizing at each step. The key wins:
- Modern-browser targeting — no polyfills for features all modern browsers support
- Aggressive code splitting — routes load only what they need
- Tree shaking — dead code removed at build time
Without preloading, the browser discovers JS chunks sequentially — a waterfall that delays interactivity.
<link rel="modulepreload"> for every critical chunk. The browser fetches all of them in parallel, before the entry script even runs.
- Waterfall collapsed into parallel fetches
- Chunks arrive before they're needed
- Time-to-interactive drops significantly
A service worker pre-caches ~1,200 assets in the background after the first visit.
On subsequent visits, JS and CSS come from cache — no network round-trip needed at all.
Traditional apps block rendering until the session is verified. Linear does the opposite:
- Check
localStoragefor cached workspace data - If found, render immediately
- Verify auth token asynchronously in the sync engine
- If auth fails, redirect — but this is rare
modulepreload primarily solve?Every common action in Linear has a keyboard shortcut. The command palette (⌘K) searches the local data store — no network request required.
Since ⌘K results come from the in-memory store, they appear in under 16ms — faster than a single animation frame.
Linear restricts animations to properties that don't trigger layout recalculation:
translate/scale
(occasional)
margin / padding
Click each box to preview. Transition durations are kept to 100-250ms — below the perceptibility threshold.
width or height?How each layer eliminates latency:
- Local-first data → no loading states for reads
- Optimistic mutations → no waiting for writes
- MobX observables → no cascading re-renders
- Module preloading → no sequential JS waterfalls
- Service worker → no network hits on repeat visits
- Keyboard shortcuts → minimal interaction distance
- Animation discipline → no layout jank