The Stage Manager's First Unscripted Actor: On the Unproductive Haste of an Eagerly Loaded API
The prevailing wisdom of web performance is a gospel of haste. We are told to anticipate, preload, and prefetch. To bring data across the network before the user even knows they need it. The goal is a seamless, instant experience, devoid of spinners and loading bars. This is the logic behind eager loading: fire off that API call the moment the component renders, start fetching that crucial user data as soon as the page loads. It feels proactive, even virtuous. But what if, in our relentless pursuit of speed, we are merely building a faster version of inefficiency? What if this haste is, paradoxically, a form of waste?
Consider the theatre. A stage manager who cues an actor to enter the stage the very second the curtain rises, regardless of the scene’s progression, creates not a seamless drama but a confusing interruption. The actor is ready, yes, but the context for their entrance is absent. Eagerly loading an API can have the same jarring effect. We fetch a payload of data—a user’s profile, a list of recommendations, a complex dashboard state—only to discover that the user never scrolls to that component, never clicks that tab, never has any intention of engaging with the information we so hastily procured. We have traded a potential, on-demand delay for a guaranteed, upfront cost. The user’s device burns cycles parsing JSON it will never use; the network channel we monopolized could have been serving a more immediate need.
The Illusion of Productivity
This practice thrives on an illusion of productivity. A fast Lighthouse score that rewards early loading becomes a siren song, luring us onto the rocks of wasted resources. We conflate “doing something early” with “doing the right thing.” In reality, an eager load is a bet, a prediction about user behavior. And like all bets, it is often wrong. The complexity of modern interfaces, with their tabs, modals, and conditional renders, makes predicting the user’s path a fool’s errand. By loading everything upfront, we optimize for the phantom user who interacts with every feature simultaneously, rather than the real user who meanders, explores, and often abandons a page long before our preloaded data sees the light of day.
The alternative is not sloth, but a more thoughtful, almost conversational approach to data: lazy loading, or more accurately, on-demand loading. It is the stage manager waiting for the precise line of dialogue—the user’s click, the scroll into view, the hover intent—before signaling the actor to make their entrance. This requires a different kind of engineering craftsmanship. It demands that we design components that are resilient to empty states and graceful in their loading. It shifts the performance priority from a raw, often misleading Speed Index to a more meaningful metric: perceived responsiveness. The user perceives an interface as fast not when everything is already there, but when it responds instantly to their explicit commands.
This is not an argument for intentional delay. It is an argument for intentional action. The wasted milliseconds spent fetching an unused user avatar are negligible in isolation. But compounded across dozens of components and thousands of users, they represent a significant squandering of collective capacity—both on the client and the server. By resisting the seductive simplicity of the eager load, we embrace a more nuanced performance philosophy. We stop treating the network as a bottomless well and start treating it as a shared, precious resource. We build not just for the illusion of speed, but for the elegant, efficient reality of an interface that only speaks when spoken to.
Notes & further reading
A few pages I came back to while writing this: