WASI 0.3 retires the async workaround and speaks the Component Model's language
The WebAssembly system interface stops emulating async through pollables and streams, and starts returning futures directly from calls.
The WebAssembly system interface stops emulating async through pollables and streams, and starts returning futures directly from calls.
The WebAssembly system interface has spent two minor versions emulating async through a workaround. WASI 0.3.0, ratified by the WASI Subgroup on 2026-06-11, is the release that retires that workaround.
The change is architectural, not cosmetic. WASI is now rebased onto the WebAssembly Component Model's async primitives, which means async is native to WebAssembly components for the first time. The wasi:io machinery that components have been juggling — input-stream, output-stream, and poll(list<pollable>) — is being replaced by stream<u8> values and future<result<_, error-code>> returned directly from calls. The old subscribe() plus start-foo plus finish-foo pattern gives way to a single awaited future per call.
The release notes enumerate the transformation across every affected package:
wasi:cli (stdio) — The stdin interface shifts from get-stdin: func() -> input-stream to read-via-stream: func() -> tuple<stream<u8>, future<result<_, error-code>>>. The stdout direction flips: where WASI 0.2 handed you an output-stream you wrote into imperatively, WASI 0.3 has you pass in a stream<u8> and get back a future that resolves when the write completes.
wasi:sockets — The network resource is gone entirely. Every start/finish pair (start-bind/finish-bind, start-connect/finish-connect, start-listen/finish-listen) became one async function. The in-progress intermediate states — bind-in-progress, connect-in-progress, listen-in-progress — and the subscribe() -> pollable that drove them are gone.
wasi:http — The most visible reorganization. Resources collapsed from eight to two. The incoming-handler with its response-outparam workaround (the pattern WASI 0.2 used because it couldn't return an async result) becomes a plain handle: async func(request) -> result<response, error-code>. The outgoing client side mirrors it. A new service world replaces the old proxy world, and a middleware world gives first-class support to components sitting in a request path.
wasi:filesystem — Streaming reads and writes switched to the same stream-plus-future shape. Directory iteration moved from a resource-based iterator to a stream.
wasi:clocks — Deliberately mostly renames, but the churn is real: wall-clock became system-clock, datetime became instant, and monotonic-clock dropped its pollable-returning subscribe calls in favor of the same host-provided timer future pattern used everywhere else.
The release itself is correspondingly small. It follows one commit to main since the prior release, and the maintainer describes the changes as entirely mechanical. The release notes' framing is consolidation, not revolution.
That framing is the story. WASI 0.2 was the right intermediate step: it bought time for the Component Model's async-ABI to land. WASI 0.3 is the moment the system interface stops being a special case inside its own ecosystem. Components no longer carry a separate async emulation layer; they speak the same async language as the runtime that hosts them.
What to watch next is implementation. The release is a spec milestone, not a deployment metric. Runtime vendors — Wasmtime, Jco, Wasmer, WasmEdge — and existing wasi:io callers will need migration paths before the new shape reaches production code. The Subgroup has done the architectural reconciliation; the work of carrying it through the ecosystem is just beginning.