Island Architecture: Ship Less JavaScript
Ship HTML first, hydrate only the interactive parts — and why this pattern is older than it looks and more relevant than ever.
There's a talk from Addy Osmani that's been floating around for years — The Real Cost of JavaScript. The core point: 500KB of images and 500KB of JavaScript are not equivalent. Images are decoded. JavaScript is parsed, compiled, and executed by the V8 engine before any of it does anything for the user.
When that talk was written, the dominant frontend pattern was the SPA — a <body> tag, a <script> tag, and 3MB of JavaScript that assembled everything in the browser. The point needed making.
Island architecture is the response to that pattern, applied to a specific class of problem: content-heavy sites where most of the page is static, with a few interactive regions.
The Concept
ExpandIsland architecture pattern
The idea is simple: ship HTML and CSS first. The page is readable and mostly functional before any JavaScript loads. Then, for the specific interactive regions — a search bar, a shopping cart, a chat widget, an "add to comment" section — load the JavaScript needed to hydrate just that piece.
Most of the page: static HTML, no JavaScript cost. Interactive regions: load JavaScript on demand, in parallel, only when needed.
Frameworks like Astro and Deno's Fresh implement this natively. But the underlying concept is implementable with any toolchain — it's really just careful code splitting applied to the page layout.
When It Makes Sense
Content sites and storefronts are the clearest fit. A news article, a product page, a documentation site — most of the content is text and images. The user is reading. A handful of regions (search, cart, comment form) need interactivity.
Loading 3MB of JavaScript to display mostly-static content is wasteful. Loading 50KB of JavaScript specifically for the checkout button is not.
The other case is compliance-constrained applications. I've worked on banking products where certain customers were on private AWS networking — server-side rendering through Vercel or any external edge service was off the table, not because of preference but because of infrastructure constraints. Static generation was the only viable option. Island architecture fits naturally into that constraint.
When It Doesn't
If your application is fundamentally interactive — think Figma, a data visualization dashboard, a real-time collaborative tool — island architecture offers little. The user is waiting for the JavaScript to load anyway. You're not saving them from a JavaScript cost; you're just reorganizing how it loads.
The metaphor helps: islands work when most of your page is ocean (static content). If the whole page is interactive, you don't have ocean to save.
The Framework Ecosystem
Astro is the most prominent island architecture framework right now. It supports React, Vue, Svelte, and vanilla components as islands — each one loads only when that island is rendered. You can mix frameworks within a single page, which sounds exotic but is genuinely useful for gradual migrations.
SvelteKit does something adjacent with its form actions: an HTML form that submits a POST request and works without JavaScript, progressively enhanced when JavaScript is available. The page is usable before JavaScript loads. That's the progressive enhancement spirit applied to interactions.
Next.js's React Server Components are pulling in the same direction from the other side — defaulting to server rendering, opting in to client JavaScript per component.
The pattern is converging across frameworks. Whether you call it island architecture, server components, or progressive enhancement, the underlying idea is the same: don't send JavaScript you don't need.
The Connection to Microfrontends
Island architecture and microfrontends share a structural similarity that's worth naming: both involve composing a page from independently managed pieces, with clear boundaries between them.
The key difference is the layer at which composition happens. Microfrontends compose at the application layer — teams own features, which get assembled into a shell. Islands compose at the page layer — regions of a page are independently hydrated based on what they need.
The isolation metaphor also carries: islands communicate poorly with each other, just like microfrontends have the shared-state problem. An island thinks about itself. Cross-island communication requires the same patterns as cross-microfrontend communication — global events, shared state objects.
Understanding the parallels makes it easier to evaluate both patterns against the same set of trade-offs: what's the page/app trying to deliver, who's responsible for each part, and what level of isolation is worth the coordination cost?
Keep reading
Enjoyed this? Get more like it.
Deep dives on system design, React, web development, and personal finance — straight to your inbox. Free, always.