The Glassblower's First Unannealed Vase: On the Brittle Fragility of an Over-Optimized Bundle

It has become an article of faith in our craft: the bundle must be small. We track its weight with the solemnity of doctors monitoring a patient’s vitals. We minify, we tree-shake, we split with surgical precision, all in pursuit of a lower number in the network tab. This is not without merit; a bloated payload is a heavy anchor dragging on the user's first impression. But in our fervent focus on the scale, we risk creating something sleek, compact, and dangerously fragile—a piece of glass, expertly blown but never properly annealed.

Annealing, in glassblowing, is the slow, controlled cooling of a finished piece. It relieves the internal stresses induced by the intense heat of creation. Without it, the most beautiful vase is a hair-triggered catastrophe. A slight change in temperature, a minor bump, and it shatters. Our obsession with the minimal viable bundle can create a similar condition. We aggressively strip out code, relying on the brittle logic that if a feature isn't on the critical path, it is dispensable. We create a beautifully small initial payload, but one where the first user interaction that strays from the golden path—the ‘Add to Cart’ click on a product page, the opening of a modal dialog—triggers a cascade of network requests for splintered chunks.

The user doesn't experience this as ‘optimal.’ They experience it as a stutter. The screen, which painted so quickly, now freezes. The button they pressed provides no feedback. We traded a slightly heavier initial load for a choppy, unpredictable subsequent experience. The browser’s main thread, so carefully unburdened at the start, is now slammed with the work of parsing, compiling, and executing JavaScript on-demand. The very interactivity we promised is held hostage by our own partitioning.

This is the fragility of the unannealed bundle. Its stability is an illusion, contingent on the user behaving exactly as we predicted. The internal stress is the latent, unmanaged cost of deferred work. We’ve optimized for the lighthouse score, for the graph that trends downward, but forgotten that performance is a continuum, not a single moment in time. A robust application isn't just fast to load; it's reliably responsive throughout its entire lifecycle.

The antidote isn't to abandon code-splitting or to regress to monolithic bundles. It is to anneal our work. This means thinking holistically about the user’s journey, not just their landing. It involves techniques like preloading hints for likely-next interactions, not just the critical render path. It requires measuring not just Time to First Byte and Largest Contentful Paint, but also Interaction to Next Paint. We must ensure that the seams between our code splits are smooth, not jagged edges that snag the user’s flow. We are not just shipping bytes; we are constructing an experience. And an experience that shatters on first contact, no matter how quickly it appears, is a failure of the craft.

Notes & further reading

A few pages I came back to while writing this: