# Qwik: Resumability That Feels Like React

> I joined Miško Hevery's team and helped turn Qwik from a resumable-but-painful prototype into a framework that feels like React, backed by a Rust compiler that extracts closures and serializes app state into HTML, so the fast path is the default one.

[View on manualmeida.dev](https://manualmeida.dev/articles/qwik-resumability)

## Performance is a human problem, not a technology one

The thing I came to believe working on Qwik is that the web's performance problem isn't a
technology problem. It's a design and developer-experience problem. Developers, like water, follow the
path of least resistance, and in most frameworks the easy way to build something is also the way that
ships a slow site. We then tell people to go optimize it afterward, as a chore, trading off
capabilities or DX or their weekend to claw the performance back.

I find it more honest to stop blaming developers and fix the path instead. A framework should be
designed so the path of least resistance lands you on a fast site by default. You shouldn't have to be
a performance expert to ship a fast page; you should have to work to ship a slow one.

And the thing worth optimizing is almost always JavaScript. Most sites already handle their images and
CSS reasonably well, so there's little left on the table there. JavaScript is where the big wins hide.
The difference between a sluggish page and a snappy one is often tens of points of Lighthouse score, and
for anyone running an e-commerce or consumer site, that gap is revenue. Resumability is the lever Qwik
pulls on exactly that.

## The idea: resume, don't rebuild

Every mainstream framework hydrates. The server renders HTML, then the browser downloads the whole
component tree as JavaScript, re-executes it, and reattaches event listeners to reconstruct state the
server already had. You pay, in bytes and CPU, to rebuild something you were handed seconds ago.

Islands and partial hydration, the approach Astro popularized, make this better by only hydrating
the interactive bits. But each island still has to download and execute its JavaScript before it's
ready, and someone has to draw and maintain those island boundaries by hand.

Resumability skips the rebuild entirely. The server serializes the application's state and its event
wiring into the HTML itself. The browser ships almost no JavaScript up front. Conceptually the app
becomes a hashmap: an event on an element points at the one chunk of code that handles it. When you
click a button, Qwik reads an attribute on that element, fetches that small chunk, restores the state
it captured, and runs it. There's no global "boot the app" step, because there's no app to boot.

There's a neat way to see the flip. In a hydrated app, event handlers are the _last_ thing to become
ready, after the whole tree has downloaded and executed. In a resumable app they're the _first_. The
page is interactive the moment it arrives.

> *[Interactive figure — view it at https://manualmeida.dev/articles/qwik-resumability]*

## The first version worked; writing it was the hard part

Proving resumability was one thing. The developer experience was another. In [that early version](https://github.com/QwikDev/qwik/tree/a64a648e6b12ec5acd1e55decd734cb3b474b7af/integration/todo/ui/Header)
the philosophy leaked all the way into the API. You split your code into many small files by hand, you
referenced lazy-loadable symbols by name, and you wrote a lot of ceremony to tell the runtime how the
pieces fit together. It worked, and it asked too much of the person typing.

My bet was that all of that ceremony could become the compiler's job. A developer should write
something that looks like ordinary [React](https://react.dev/), with components, event handlers, and local state, and the
build step should do the hard work of making it resumable. The point of the whole project, after all,
was to make the fast path the easy path, and an API that demanded this much manual wiring was the
opposite of that.

## Making it feel like React

In the design I led, you write a component with handlers and hooks, the way you already think. The
magic lives in the compiler.

```tsx
export const Counter = component$(() => {
  const count = useSignal(0);
  // looks like an ordinary closure; the compiler will extract it
  return <button onClick$={() => count.value++}>{count.value}</button>;
});
```

The compiler reads the AST, finds every `$`-marked boundary (a `component$`, an `onClick$`), and
pulls that closure out into its own module with no dependencies except the variables it closed over.
Those captured variables get serialized straight into the HTML. When the user clicks, the runtime
loads that one module, restores the state it captured, and runs the handler. Nothing else downloads.

The captured state can be a live signal, so the handler reads and updates a reactive `count` and the
DOM follows along. `useSignal` lets the runtime make a surgical update to exactly the text node that
changed, with no component re-render in the browser. The signal model drew on Solid's
[reactivity](https://www.solidjs.com/). The result reads like React and behaves like a resumable app,
with none of the manual wiring the first version demanded.

One thing I like about this model over React Server Components: a Qwik component is universal. The same
component runs on the server or the client, and the developer doesn't annotate the boundary. With RSC
it's easy to reach for `use client` everywhere out of convenience and quietly opt back into shipping
everything. In Qwik there's no boundary to get wrong, because the compiler is the one deciding what
crosses it.

## Rust and SWC

The optimizer that does all this is written in Rust, on top of [SWC](https://swc.rs/). It runs on
every build and across large codebases, so it had to stay fast enough to disappear into the dev loop.
Rust kept the AST passes quick as projects grew, which matters when the entire premise is that the
compiler, and not the developer, carries the complexity.

## QwikCity

Later, with Adam Bradley (co-creator of Ionic and Stencil), I worked on the design of QwikCity, the
meta-framework that sits on top: routing, data loading, and the conventions that make Qwik a way to
build whole sites. That part was a close back-and-forth between the two of us.

## Credit where it's due

I want to be precise about this. The resumability concept, and much of how it works under the hood,
including the runtime and the Solid-inspired signals, came from Miško Hevery, the creator of
[Angular](https://angular.dev/).
What I led was the developer-facing redesign and the compiler beneath it: turning closures into
independent, serializable modules and working out the reachability analysis that decides what to ship.

The throughline to the rest of my work is that compiler. Make the source look ordinary, push the hard
analysis to build time, and let the runtime stay lazy, so the path of least resistance is also the
fast one. I'd wired the same instinct into
[Gin's router](/articles/gin-simple-over-easy) years earlier, and I'd reach for it again tomorrow.
If you're designing a framework, that's where I'd spend the effort: on the compiler that lets people
write the easy thing while you quietly ship the simple one.

If you want the longer version of this argument, I gave a
[talk on it](https://www.youtube.com/watch?v=HfEDhuZKH7A).

---

## About the author

Manuel Martínez-Almeida (Manu) is a principal engineer at Builder.io, where he sets the technical direction for the AI agent platform across product, design, and code. He is the creator of Gin (the Go web framework with ~88k GitHub stars and 290k+ dependent projects), helped take Qwik from proof-of-concept to production including its Rust compiler and resumability model, and designed the compiler architecture and virtual DOM for Stencil. His work sits where performance, systems, and developer experience meet — compilers, language runtimes, web frameworks, GPU rendering, and distributed infrastructure serving billions of requests a day. He is based between Lisbon and Budapest.

- **Name:** Manuel Martínez-Almeida (Manu)
- **Role:** Principal Engineer at Builder.io
- **Focus:** compilers, language runtimes, web frameworks, GPU rendering, distributed infrastructure, developer experience, AI agents, open source
- **About:** https://manualmeida.dev/articles/about/
- **GitHub:** https://github.com/manucorporat
- **Twitter/X:** https://x.com/manucorporat
- **dev.to:** https://dev.to/manucorporat
- **Website:** https://manualmeida.dev
