Skip to content
Dev Tools Release

WASI 0.3.0 Brings Native Async to WebAssembly Components

The WebAssembly System Interface ratifies a major update, replacing complex polling workarounds with native asynchronous primitives.

Lenn Voss
Lenn Voss
Cloud & Infrastructure Writer · Jun 12, 2026 · 4 min read

If you have been wrestling with the asynchronous workarounds in WASI 0.2, there is some very welcome news from the WebAssembly Subgroup. The group has officially voted to ratify WASI 0.3.0, a release that fundamentally rebases the WebAssembly System Interface onto the native asynchronous primitives of the WebAssembly Component Model.

While WASI 0.2 had to perform some complex structural acrobatics to make asynchronous operations work, WASI 0.3.0 introduces native async capabilities directly into the component model. This change makes the interfaces highly ergonomic, eliminating boilerplate and intermediate states across CLI, socket, and HTTP operations.

The Death of Pollable and the Rise of Native Async

In WASI 0.2, asynchronous execution was driven by the wasi:io package, which relied on a manual polling model. Developers had to manage pollable resources, bundle them into lists, and manually trigger polls.

WASI 0.3.0 replaces these patterns with native Component Model async primitives. The mechanical shift simplifies the entire I/O model:

  • pollable is replaced by future<T>.
  • input-stream and output-stream resources are replaced by stream<u8>.
  • poll(list<pollable>) is gone, replaced by a runtime-handled await on a future.
  • subscribe() on a resource is replaced by returning a future<...> directly from the call.
  • start-foo / finish-foo split-phase function pairs are consolidated into a single async func.

Streamlining CLI and I/O

While the structural files for wasi:cli (such as stdin.wit, stdout.wit, stderr.wit, run.wit, exit.wit, terminal.wit, and environment.wit) remain the same, the way standard I/O is handled has changed significantly.

Consider the direction flip on stdout. In WASI 0.2, the runtime handed you an output-stream that you wrote into imperatively. In WASI 0.3.0, you pass a stream<u8> into the runtime and receive a future that resolves when the write operation completes:

// WASI 0.2
interface stdout {
  use wasi:io/streams.{output-stream};
  get-stdout: func() -> output-stream;
}

// WASI 0.3
interface stdout {
  use types.{error-code};
  write-via-stream: func(data: stream<u8>) -> future<result<_, error-code>>;
}

Similarly, stdin has transitioned from get-stdin: func() -> input-stream to a read-via-stream function that returns a tuple containing a stream<u8> and a future for the operation's result. A new, shared wasi:cli/types interface has also been introduced to carry a unified error-code variant covering io, illegal-byte-sequence, and pipe errors.

Advertisement

Sockets: No More Network Resource

Network handling in wasi:sockets has been heavily refactored. In WASI 0.2, network access was modeled as a capability resource that had to be threaded through every single bind, connect, or lookup call. WASI 0.3.0 removes this network resource entirely, opting instead to grant network access directly via world imports.

Additionally, the noisy intermediate states of socket operations—such as bind-in-progress, connect-in-progress, and listen-in-progress—along with the subscribe() -> pollable calls that drove them, have been eliminated. Every start/finish pair has collapsed into a single, clean asynchronous function:

// WASI 0.2
start-connect: func(network: borrow<network>, remote: ip-socket-address) -> result<_, error-code>;
finish-connect: func() -> result<tuple<input-stream, output-stream>, error-code>;

// WASI 0.3
connect: async func(remote-address: ip-socket-address) -> result<_, error-code>;

Where WASI 0.2's finish-connect returned a TCP stream pair inline, WASI 0.3.0's connect returns nothing special; byte I/O now lives directly on the socket resource's own stream methods. UDP has received the same treatment: incoming and outgoing datagram stream resources are gone, replaced by plain async send and receive functions. Error codes across TCP, UDP, and name-lookup have also been unified into a single variant, introducing a new connection-broken case and an open-ended other(option<string>) tail.

HTTP Reorganization: 8 Resources Collapse to 2

The reorganization of wasi:http is perhaps the most dramatic change in this release. In WASI 0.2, developers had to manage a matrix of eight distinct resources to handle requests, responses, bodies, and trailers:

  • incoming-request / outgoing-request
  • incoming-response / outgoing-response
  • incoming-body / outgoing-body
  • future-trailers / future-incoming-response

In WASI 0.3.0, this entire matrix collapses into just two resources: request and response. Bodies are represented directly as a stream<u8>, and trailers are handled via future<result<option<trailers>, error-code>>. Because a plain future<result<response, error-code>> can now handle the response lifecycle, future-incoming-response has been completely eliminated.

Furthermore, handlers are now native async functions. WASI 0.2 had to use an out-parameter workaround (response-outparam) to return responses asynchronously. WASI 0.3.0 handles this cleanly:

// WASI 0.2
interface incoming-handler {
  handle: func(request: incoming-request, response-out: response-outparam);
}

// WASI 0.3
interface handler {
  handle: async func(request: request) -> result<response, error-code>;
}

This release also introduces first-class support for middleware components. The old proxy world has been replaced by a service world, alongside a new middleware world that both imports and exports the handler interface. This allows developers to easily chain components together directly in the request path.

Finally, wasi:filesystem has also been updated, switching its streaming reads and writes to the same stream-plus-future shape seen across the rest of the specification. By aligning the entire system interface around native async primitives, WASI 0.3.0 delivers a much cleaner, more cohesive foundation for building high-performance, asynchronous WebAssembly applications.

Sources & further reading

  1. WASI 0.3.0 Released — github.com
Lenn Voss
Written by
Lenn Voss · Cloud & Infrastructure Writer

Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.

Discussion 0

Join the discussion

Sign in or create an account to comment and vote.

No comments yet

Be the first to weigh in.

Related Reading