Notion Android
The Bridge Bottleneck
Notion's Android app was unanimously voted worst-in-class by power users. Opening a single page took 3 seconds. React Native was blamed — but was it really?
The Incident
By 2022, Notion's Android app had become a running joke in productivity circles. Simple operations felt sluggish on even flagship devices. The app bundle weighed in heavier than most mobile games. Offline mode worked inconsistently. Notion engineers eventually acknowledged a full rewrite was necessary — but the problems ran deeper than just the framework choice.
Evidence from the Scene
- Opening any page took 3+ seconds regardless of content length
- Scrolling long documents played out at a choppy 20fps on flagship devices
- App install size was 180MB — larger than most 3D mobile games
- Offline mode was unreliable — some pages loaded, others showed network errors with no obvious pattern
- Every navigation transition caused a visible white flash before content appeared
The Suspects
3 of these are the real root causes. The others are plausible-sounding distractors.
React Native JS bridge serializing all state updates across the native boundary
Entire workspace graph loaded into memory on startup — no lazy loading
No offline-first architecture — page rendering was server-dependent
Missing ProGuard consumer rules causing runtime crashes after obfuscation
PNG icon assets instead of vector drawables inflating memory on high-DPI screens
RecyclerView not recycling block items — inflating new views on every scroll
The Verdict
Real Root Causes
React Native JS bridge serializing all state updates across the native boundary
Every layout update, scroll event, and state change crossing the React Native bridge requires serialization to JSON and deserialization on the other side. For a complex document editor with rich text, nested blocks, and real-time sync, this overhead on every keystroke and scroll event produced the consistent jank described.
Entire workspace graph loaded into memory on startup — no lazy loading
Notion loaded all of a user's pages and their metadata eagerly at startup rather than lazily fetching them on demand. A workspace with thousands of pages meant the JS heap was saturated before the user saw any content, causing the 3-second cold start.
No offline-first architecture — page rendering was server-dependent
Pages were rendered by fetching fresh data from the server on every open, with no local-first cache. If the server response was slow or the device was offline, the user saw a blank page. A true offline-first design would render from local state immediately and sync in the background.
Plausible But Wrong
Missing ProGuard consumer rules causing runtime crashes after obfuscation
ProGuard misconfig causes crashes after release builds — not the consistent 3-second open time and 20fps scroll described here across all users including those on debug builds.
PNG icon assets instead of vector drawables inflating memory on high-DPI screens
Large PNG assets increase APK size and memory but would not cause the 3-second page open time or consistent scroll jank described here.
RecyclerView not recycling block items — inflating new views on every scroll
Missing RecyclerView recycling causes jank during fast scrolling — but Notion's issue was rooted in the JS bridge and data loading architecture, not the RecyclerView binding layer.
Summary
Notion's Android performance problems were a compounding stack of architectural debts. The React Native bridge added latency to every interaction in a complexity-heavy document editor. The eager workspace loading meant startup was gated on fetching every page title and metadata. And the server-dependent rendering model made offline an afterthought rather than a first-class experience. Notion announced their Android rewrite in 2023, rebuilding in native Kotlin with a local-first architecture, lazy loading, and a dedicated sync engine — the same patterns taught in Chapters 2 and 5.
The Real Decision That Caused This
“Choosing a bridge-based cross-platform framework for a complexity-heavy document editor, then compounding it with eager data loading and server-dependent rendering with no offline-first model.”
Lesson Hint
Chapter 2 (App Architecture) covers why framework choices affect architectural ceilings. Chapter 5 (Offline & Sync) covers local-first architecture and sync engine design.
Want to test yourself before reading the verdict?
Open Interactive Case in Autopsy Lab