zRun
zRun is a compact JavaScript runtime and source compiler written in Zig. The current implementation is about 11K lines of Zig.
I built it to separate application business logic from systems code in a large open-source project.
The intended model is:
TypeScript business logic
↓
zRun
↓
Zig plugins
↓
performance-critical code
Business rules can stay in TypeScript, while networking, storage, heavy computation and other performance-sensitive operations remain native Zig code.
The motivation came from my previous project, Cruller. Cruller started from Bun, but over time I concluded that stripping down a large general-purpose runtime was the wrong direction for this use case. I wanted a much smaller execution layer that I could fully understand and control.
For comparison:
| Runtime | Approx. source size |
|---|---|
| V8 | ~2,000,000 LOC |
| QuickJS | ~79,871 LOC |
| MQuickJS | ~30,950 LOC |
| zRun | ~11,375 LOC |
zRun supports the JavaScript features needed by the target workloads, including closures, classes, exceptions, async/await suspension and resume, collections, BigInt, regular expressions and common standard APIs.
It can compile JavaScript into a versioned bytecode format and execute that bytecode in a runtime that does not need to include the source compiler.
Async execution is host-driven: await can suspend the VM, return control to Zig, and later resume execution when the host operation completes. There is no built-in event loop that the embedding application has to adopt.
The runtime also supports resident compiled modules so bytecode can remain decoded in memory and functions can be called directly by module and function name.
One useful milestone is that zRun can already run Preact SSR. This means the same small runtime can potentially replace a much heavier Bun-based layer for server-side rendering while keeping the application architecture centered around Zig.
Current benchmark results put zRun in roughly the same performance range as MQuickJS and QuickJS on several workloads:
| Benchmark | Reference / zRun |
|---|---|
| MQuickJS, same bytecode | 0.92x |
| MQuickJS CLI bytecode | 0.87x |
| QuickJS CLI | 0.91x |
Values below 1.0 mean zRun is slower in those tests. Other workloads currently show larger gaps. The repository includes the benchmark code and methodology.
The main thing I learned from the project is that a JavaScript runtime can remain quite small if full JavaScript compatibility is not the goal. For this project JavaScript is primarily an application-level language sitting above native Zig functionality.
zRun is intended to become the runtime foundation for Cruller v2.
Supported Zig versions
- Zig 0.16.0
AI / LLM usage disclosure
I used OpenAI Codex and Luna 6 during development for code generation, refactoring, debugging, tests and implementation experiments.
The runtime architecture, execution model, project direction and benchmark design were defined by me. Generated code was compiled, reviewed, tested and benchmarked as part of the development process.