Hey everyone,
I’m working on a project called ore-node-std, and I thought this might be relevant to people here working with Wasmtime/WASI.
I’m trying to run QuickJS under Wasmtime + WASI Preview 1 while providing a useful subset of Node.js APIs (fs, crypto, http, stream, buffer, process, etc.) without relying on custom WASM host imports, such as C/C++ implemented host functions (_node:os, _node:crypto) or non-standard socket extensions.
One of the problems I ran into is that WASI P1 doesn't provide outbound TCP sockets. Instead of extending the host ABI, I’m currently experimenting with a VFS-based approach where the QuickJS guest writes requests to temporary files, and the Rust host handles things like native crypto/network I/O and writes the results back.
ore-node-std is actually one layer of a larger system I’m building called ORE. The core system is ore-kernel, which acts as the root sandbox/runtime layer. It manages the execution environment and launches isolated workloads through Wasmtime, with the goal of keeping the guest environment constrained to standard WASI interfaces.
The idea is to have the kernel provide the isolation and resource boundary, while ore-node-std provides the higher-level Node-compatible environment inside the sandbox.
Architecture-wise, I’m roughly working toward:
ORE Kernel → Wasmtime → WASI P1 → QuickJS → ore-node-std
with the kernel acting as the root sandbox rather than exposing arbitrary host capabilities directly to the JavaScript runtime.
The projects are here:
I’d especially appreciate feedback from anyone familiar with Wasmtime/WASI sandboxing, guest/host boundaries, or whether there’s a more idiomatic WASI-native way to approach this.
Not trying to solve everything with the current design, but I’m mainly looking for a sanity check from people who know the Wasmtime side much better than I do. :slight_smile:
Have you seen https://github.com/bytecodealliance/jco and https://bytecodealliance.github.io/jco/interop/nodejs-builtins.html
Thanks for sharing these links, @Bailey Hayes !
I’ve looked closely into jco and the preview2-shim / jco-std work mapping Node.js built-ins to WASI 0.2. The coverage on the compatibility matrix is really impressive.
The reason I’m experimenting with WASI P1 + QuickJS rather than the full WASI 0.2 Component Model via jco comes down to three specific design constraints for ORE:
wasi:sockets). Outbound I/O is mediated at Layer 7 by the ore-kernel, streaming responses directly to an ephemeral VFS mount to protect the guest's linear memory from OOMs on large payloads..wit authoring, code generation, or component composition steps before execution.That said, jco's pure JS implementations for modules like node:buffer, node:events, and node:stream are great references that I can definitely study for the non-I/O built-ins.
Given your work around sandboxing and guest/host boundaries in the Wasm / WASI ecosystem, I'd be curious to hear your perspective on using an ephemeral VFS as the primary I/O bridge for untrusted workloads versus exposing finer-grained host imports.
Minimal Engine Footprint & Cold Starts: Keeping the runtime embedded within lightweight QuickJS keeps instantiation latency sub-millisecond with minimal memory overhead, avoiding heavier engine payloads like SpiderMonkey.
FWIW, we worked pretty hard on instantiation times in Wasmtime; we use virtual memory tricks so even a full SpiderMonkey component can instantiate in ~a few microseconds.
Heap size and compiled code size are still likely smaller with QuickJS but I'd encourage you to measure (and we're curious if you find any overheads you don't expect).
That makes a lot of sense regarding how the pooling allocator and CoW page-table remapping keep instantiation down to microseconds regardless of binary size.
Currently, ORE's execution pipeline is built around core Wasm modules and WASI P1 (wasmtime::Module / Instance), so testing a componentize-js artifact directly would require standing up a separate wasmtime::component harness outside our kernel.
For context on my side, my QuickJS module (system-js.wasm) is ~4.2MB, but Cranelift compiles it into a ~19MB .cwasm artifact. Given the code expansion factor during AOT compilation, a heavier engine embedding starting at 8MB–13MB+ raw Wasm creates substantially more cache pressure when scaling to dozens of distinct tool cartridges on constrained edge nodes.
Circling back to the guest-host I/O boundary and the other design constraints, I'd still love to hear your perspective on using an ephemeral VFS to pass dynamic payloads back and forth in Wasmtime P1.
Are there hidden performance or lifecycle pitfalls with treating the filesystem as a universal transport like that, compared to exposing dedicated host function imports?
one note on the .cwasm size and duplicated artifacts: we have a plan for making it so that runtimes, such as JS engines, can be reused across multiple components. That'd mean you'd only have a single .wasm per version of the engine.
That doesn't help you in the short term, of course, and I can't give you a good estimate for when this will be available.
In the meantime, most of us are focused on component model use, so I'm not sure how much engagement you'll get on the VFS usage. Superficially it seems plausible to me, but this being a very security sensitive part to get right, I wouldn't rely on a quick reply like that all that much
Thanks for the transparent context, @Till Schneidereit !
That context on sharing runtimes across components makes a lot of sense, good to know it's an active area of exploration on your end, even if that timeline is still further out.
Understood on the team's focus being squarely on the Component Model right now. And I appreciate the word of caution on the VFS bridge, definitely agree that filesystem-mediated IPC carries plenty of security sensitivity around capability leaks, symlink resolution, and traversal. I am relying heavily on cap-std handles and strict UUID-scoped ephemeral mounts precisely to keep those boundaries tight.
Really appreciate you, @Bailey Hayes , and @Chris Fallin taking the time to share your perspectives and context. It's been super helpful for grounding my architecture!
Last updated: Oct 11 2026 at 02:20 UTC