← All posts

March 15, 2024

What I learned migrating Nextdoor's feed to Jetpack Compose

Lessons from leading a full Compose migration of a high-traffic Android feed — what worked, what didn't, and what moved the needle.

Migrating a production feed used by millions of people to Jetpack Compose is not something you do in a sprint. Here’s what I learned leading that effort at Nextdoor.

Why we migrated

The Nextdoor Android feed was built on a mix of custom RecyclerView logic and hand-rolled view holders. It worked, but every new feature required touching plumbing that had accumulated years of edge cases. Compose promised declarative UI, better state management, and — critically — easier testing.

The approach that worked

We didn’t do a big bang rewrite. Instead, we used ComposeView inside existing RecyclerView item views, migrating one feed card type at a time. This let us ship incrementally and measure the impact of each change.

The key insight: interop is your friend, not a compromise. Hybrid Compose/View systems run fine in production. Don’t let perfect be the enemy of shipped.

What moved the needle

After full migration, we saw a 4% increase in scroll depth — users were scrolling further into the feed. The smoother rendering from Compose’s optimized diffing and reduced overdraw made the feed feel snappier, which translated to real engagement.

What I’d do differently

Start with the simplest card type, not the most impactful one. We learned the most from low-stakes migrations and applied those lessons to the complex cards. The instinct to start with what matters most is understandable but it’s the wrong call when you’re building new muscle.


More posts on Android architecture and performance coming soon.