Skip to content
fearchitect
Rendering & Hydration

Resumability (Qwik)

Skip hydration by serializing state and listeners directly into HTML.

By Abas TurabliReviewed

Summary

Resumability is Qwik's alternative to hydration. The server serializes component state, subscriptions, and event-listener references into the HTML; the browser picks up exactly where the server left off. No JS executes on load — only the handler for the event the user actually triggers is downloaded.

Jump to the interview angle
On load only qwikloader runs; the handler chunk is fetched only on the first click.

Resume-on-interaction flow

  1. 1

    SSR: serialize everything

    Qwik's server renderer writes application state and component subscriptions into a <script type="qwik/json"> block, and encodes each event listener as a DOM attribute: on:click="./counter-abc123.js#Counter_onClick_0".

  2. 2

    Browser: parse HTML

    The browser receives fully-rendered HTML. No framework JS executes. The page is visually complete and readable the instant the HTML parses.

  3. 3

    qwikloader registers one global listener

    qwikloader.js (~1 KB, inlined) attaches a single event listener to the document. It intercepts every bubbling event and looks up the matching QRL attribute on the target element.

  4. 4

    First user interaction: fetch the handler chunk

    qwikloader reads the QRL attribute, fetches that one JS chunk from the CDN, and executes the handler. State is already deserialized — no component re-execution needed.

  5. 5

    Signal update patches the DOM

    The handler mutates a useSignal value. Qwik's fine-grained reactivity patches only the affected DOM nodes — no full re-render of the component tree.

Counter with component$ and useSignal

Every $-suffixed boundary is split into its own lazy chunk by the optimizer. useSignal(0) creates reactive state that is serialized into the HTML on the server and deserialized transparently on the client.

Counter with useSignal and onClick$tsx
import { component$, useSignal } from "@builder.io/qwik";

export const Counter = component$(() => {
  const count = useSignal(0);

  return (
    <button onClick$={() => count.value++}>
      Count: {count.value}
    </button>
  );
});

useSignal(0) state is serialized into the HTML. The onClick$ handler becomes its own chunk — downloaded only when the button is first clicked.

Tradeoffs

Pros

  • O(1) Time to Interactive regardless of app size — no JS runs on load.
  • Fine-grained lazy loading: only the triggered handler's chunk is downloaded.
  • Eliminates hydration waterfalls common in large SSR apps.
  • Server state is already the source of truth; no double-data problem.

Cons

  • First interaction adds a network round-trip to fetch the handler chunk.
  • The optimizer and dollar-boundary rules add build complexity.
  • Ecosystem is smaller than React/Vue — fewer libraries, less community tooling.
  • Mental model shift: developers must internalize the $ boundary and serialization rules.

$ boundary rules are strict

Passing non-serializable values (closures, class instances) across a $ boundary causes a runtime error. Importing a large library inside a $ callback pulls the whole library into that chunk, defeating lazy loading.

Interview angle

Interviewers probe the replay-vs-resume distinction and what exactly gets serialized. Strong answers name the three serialized pieces (state, tree, listeners as DOM attributes) and explain why startup is O(1). Mention the first-interaction chunk fetch as the real tradeoff.

Soundbite: "Resumability serializes state and listeners into HTML so the browser resumes, not replays — O(1) startup, pay-per-interaction JS cost."

Key terms

Resumability
Skipping hydration by serializing app state and listener references into HTML for instant startup.
QRL (Qwik URL)
A lazy, serializable reference to a code chunk encoded as a URL + exported symbol (e.g. `./chunk.js#Symbol`), stored as a DOM attribute so Qwik lazy-loads code without running JS upfront.
Dollar boundary ($)
The Qwik optimizer marker that splits a function into its own lazy-loaded chunk.
useSignal
A Qwik hook that returns a reactive `Signal<T>` whose `.value` is serialized into HTML.
qwikloader
A ~1 KB global script that intercepts DOM events and fetches the matching handler chunk on demand.

Further reading

Search fearchitect

Jump to a topic, mode, or action.