User types "android" into your search box. That's 7 API calls if you wired it the way I did the first time. A few months later I shipped a pagination bug where every infinite-scroll fetch flashed a full-screen loader for half a second. And then there was the Settings screen that needed to refresh the Dashboard when the user changed theme — but Settings couldn't import Dashboard without a circular dependency. These are the three problems I run into on every non-trivial Compose app. Below is the MVVM pattern I've landed on after making each of these mistakes in production. (If you're new to MVVM with Compose, I covered the basics with a login screen separately . This article assumes you already know the StateFlow + ViewModel shape and goes one layer up.) The Search Problem Everyone Gets Wrong Here's how I used to implement search: // Don't do this searchTextField . addTextChangedListener { text -> viewModel . search ( text . toString ()) // API call on every keystroke!…