Open almost any modern website and you're loading more than you think. Not more images, necessarily, and not more text. More JavaScript. A lot more. The average site today ships several times as much JavaScript as it did a decade ago, and that number keeps climbing every year. Somewhere along the way, "make the page interactive" quietly turned into "download an entire application before the user can click anything," and most of the web's current performance headaches trace straight back to that shift.
This isn't just a developer inconvenience. Rakuten's 24-hour shopping platform ran a well documented case study on exactly this problem, and after tightening up their JavaScript, CSS, and image delivery, the numbers moved in ways that are hard to ignore: revenue per visitor up over 53%, conversion rate up more than 33%, average order value up over 15%, and exit rate down by more than a third. Page speed isn't a nice to have anymore. It's a line item on the balance sheet.
So how did we end up shipping so much JavaScript in the first place, and is there actually a way out? That's where Qwik.js comes in, a framework built around a genuinely different idea called resumability, which claims to sidestep the JavaScript bloat problem rather than just optimizing around it. To find out whether that claim holds up, I built two near identical test applications, one in Qwik and one in Next.js, and ran them both through real network conditions to see what actually happens.
How We Got Here: A Short History of Loading Too Much
In the earliest days of the web, pages were simple documents. A server received a request and sent back plain HTML, nothing more. The arrival of the Document Object Model, paired with the rise of JavaScript and server side languages like PHP, changed that. Suddenly pages could be dynamic, personalized, and responsive to user input, both on the server and in the browser.
As applications grew more complex, developers started bundling reusable functionality into libraries, and those libraries eventually solidified into full frameworks. Then came the big shift: with Angular, React, and Vue, rendering moved almost entirely to the client. In these single page applications, the server's initial response is barely more than an empty shell, a root element and a set of links to JavaScript files. The real page gets built later, in the browser, once all that JavaScript has been downloaded, parsed, and executed.
This approach has real upsides. Once loaded, single page apps feel fast and native. But that first load is rough. Users often stare at a blank screen while the JavaScript bundle downloads, and search engine crawlers, which historically struggle to execute JavaScript reliably, have a hard time indexing content that doesn't exist until a script runs. That second problem hits SEO directly, which is a serious cost for any content driven site.
Meta-Frameworks Tried to Fix This, But Only Halfway
Toward the end of the 2010s, meta-frameworks like Next.js and Nuxt.js arrived to patch the gap. Their pitch: render the HTML on the server again, either per request (server side rendering) or ahead of time as static files (static site generation), so users see real content immediately instead of a blank page.
That solves the visibility problem. Content shows up fast, and crawlers can index it properly. But it doesn't solve interactivity. The HTML that arrives from the server looks complete, but none of the buttons, forms, or dynamic components actually work yet. To fix that, the browser has to run a process called hydration, which attaches event handlers to the existing HTML and restores the application's internal state so it behaves like a fully functioning app again.
Hydration sounds reasonable on paper. In practice, it's expensive. The problem is that event handlers are usually closures, meaning they carry references to application state, variables, and other functions from deep inside the component tree. Since those closures can't simply be exported and reattached from the outside, the entire component tree, top to bottom, effectively needs to be downloaded and re-executed on the client just to figure out where handlers belong and how to wire them up. That process runs in four rough phases: fetch all the JavaScript, parse and execute it, rebuild application state and handlers, then finally attach everything to the actual DOM elements.
For small pages, this barely registers. For larger, more complex applications, it can take several seconds, and on constrained mobile devices, up to ten seconds isn't unheard of. Worse, a meaningful chunk of that work duplicates something the server already did during rendering, just to throw it away and rebuild it client side. Misko Hevery, formerly of the Angular team, has been blunt about this, calling hydration a workaround that ignores how browsers actually function. Ryan Carniato, another prominent voice in the framework world, points out that hydration can sometimes leave an app slower to become interactive than plain client side rendering would have, simply because of the added JavaScript payload.
Resumability: Skipping the Rebuild Entirely
This is the problem Qwik set out to solve. Released in 2021 by the team behind the CMS platform Builder.io, under Hevery's direction, Qwik takes a fundamentally different approach: instead of hydrating the whole application on load, it aims to resume exactly where the server left off, without re-executing any of the component logic that produced the page in the first place.
The mechanism behind this is what Qwik calls resumability. Rather than shipping a full JavaScript bundle and reconstructing state and event bindings from scratch, Qwik serializes everything the browser will eventually need directly into the HTML during server side rendering. Event handlers get encoded as special references called QRLs (Qwik URLs), essentially a path to a code chunk plus a symbol name and any state the handler needs. A single tiny script, the QwikLoader, weighing in at roughly 1kB, acts as a global listener for all browser events. When a user actually interacts with something, the QwikLoader looks up the relevant QRL in the DOM, fetches just that one chunk of code, and runs it. Nothing else gets downloaded until it's needed.
The result is fine grained, automatic lazy loading. Qwik's compiler watches for a dollar sign suffix in the code (think component$ or an inline onClick$ handler), which signals a natural split point. Each of those becomes its own independently loadable chunk. Developers write code that looks a lot like React, functional components and JSX, but the framework quietly breaks it apart behind the scenes so that almost none of it needs to load upfront.
The practical implication is a genuinely different growth curve. In conventional meta-frameworks, the amount of JavaScript needed for hydration scales up roughly in proportion to how complex the application is. More components, more interactive elements, more code shipped on that first load, whether or not the user ever touches most of it. Qwik's initial bundle size, by contrast, stays close to constant regardless of how big or complex the app becomes, because nothing loads until an actual interaction demands it.
Putting It to the Test
Claims about architecture are one thing. Real numbers are another. To see whether resumability translates into a measurable advantage, I built two nearly identical single page applications, one in Qwik and one in Next.js, each including a header with an SVG logo, a landing section with a large WebP image, an interactive counter with local state, a card slider, a list rendering server fetched JSON data, and a footer showing the client rendered current time. Both were deployed to Vercel and tested using WebPageTest under two conditions: a fast desktop connection (Firefox, 5 Mbps LAN, Frankfurt) and a constrained mobile connection (Chrome on a mid-range Motorola phone, 1.6 Mbps 3G, Mumbai, with 300ms latency).
Under good network conditions, the gap was small but consistent. Both apps reached first byte in about 0.18 seconds, but Qwik's First Contentful Paint and Speed Index landed roughly 0.1 seconds ahead of Next.js. The bigger story was in what got downloaded. Next.js needed 149kb across 13 requests to fully load, largely due to the additional component bundles required for hydration. Qwik needed only 38kb across 4 requests, essentially just the initial HTML, the logo, the hero image, and a manifest file, with CSS inlined directly into the page to avoid an extra request entirely. Total load time landed at 0.428 seconds for Qwik versus 0.647 seconds for Next.js. Noticeable in a lab test, but for a real user on a decent connection, probably not something they'd consciously feel.
The constrained mobile test told a sharper story. On the slow 3G connection, every additional request and kilobyte carries real cost, and that showed clearly in the results: First Contentful Paint came in at 2.72 seconds for Qwik versus 3.48 seconds for Next.js, and Speed Index landed at 2.84 seconds versus 3.92 seconds. Total load time favored Qwik by nearly 1.8 seconds, a gap that's genuinely perceptible to an actual person waiting for a page to become usable.
So Does Resumability Actually Win?
Based on this comparison, yes, at least directionally, and the advantage grows precisely in the conditions where it matters most: constrained devices and unreliable networks, which describes a huge share of real world mobile traffic. The mechanism behind it holds up too. By serializing state and event references into the HTML itself, Qwik genuinely avoids the redundant work that hydration requires, rather than just hiding it or deferring it.
That said, it's worth keeping the result in proportion. Both test applications were intentionally simple, a handful of components and a modest interaction surface. Next.js still delivered strong, entirely acceptable performance numbers on its own. The gap that showed up here would almost certainly widen further on larger, more component heavy real world applications, exactly the scenario where Qwik's constant initial bundle size is designed to shine, but that's an extrapolation, not something this specific test directly measured.
What does seem clear is that the broader industry has noticed the same problem this experiment set out to explore. Some developers and researchers, including Juho Vepsalainen and Arto Hellas, have started describing a class of tools as "disappearing frameworks," pointing to approaches like Astro's partial hydration or Next.js's newer Server Components as different attempts at the same underlying goal: ship less JavaScript, without sacrificing interactivity or SEO. Qwik's resumability is the most structurally distinct answer to that question so far, built from the ground up around avoiding the rebuild rather than optimizing it. Whether it becomes the dominant pattern or just one influential idea among several, it's a genuinely useful case study in what happens when a framework questions an assumption, hydration, that the rest of the ecosystem had mostly stopped examining.
