WebAssembly, WASI and Rust: Dreamteam for Microservices​

The WebAssembly System Interface standardizes the interaction of Wasm modules in different programming languages, and Rust is ideally positioned.

listen Print view
A computer standing on a box labeled WASI

(Image: Erstellt mit KI (Dall-E) von iX-Redaktion)

14 min. read
By
  • Rainer Stropek
Contents

Many projects start out small and manageable as elegant, homogeneous monoliths in which all components are developed on a common technical basis. However, as the size and complexity of the project increases, sub-areas emerge that differ in terms of their technical basis. Reasons for this can be changing requirements, preferences of development teams or the integration of third-party software.

Microservices are often the solution: You divide the software into manageable, independent units that communicate with each other via platform-independent network protocols. Each microservice can be written in its own programming language and use suitable libraries and third-party components. Although this resolves the technical heterogeneity, it noticeably increases the overall complexity. Simply calling a function in another microservice becomes an adventure.

It would be nice if there was a technology that made it possible to connect components written in different programming languages without microservices and without compromising on security, performance and portability. This is precisely the aim of the combination of WebAssembly and WASI, the Web Assembly System Interface.

WebAssembly (Wasm) is a binary instruction language for a stack-based virtual machine that was originally developed to run applications at near-native speed in the browser. However, Wasm is much more than just a browser technology: at its core, it provides a standardized way to compile code into a compact and platform-independent form so that the result can be executed on numerous runtime environments beyond the browser. A key advantage of WebAssembly is that it was designed as an assembly language for the cloud and the web that runs securely in a sandbox. Sandbox isolation ensures that code does not gain uncontrolled access to system resources or other connected components.

Developers can write Wasm modules in numerous programming languages. The resulting bytecode is independent of the source language and runs on all common platforms with the help of Wasm runtime environments such as Wasmtime or Wasmer. In practice, however, the implementation of Wasm in different programming languages varies. Some are at the cutting edge and support the latest developments, while others lag somewhat behind. Rust is probably the best programming language for WebAssembly. Almost all important Wasm tools and libraries are written in Rust and the language offers excellent functions for creating Wasm modules. Rust's focus on security, performance and portability fits well with the requirements of WebAssembly.

In addition to Wasm as the foundation for platform-independent, secure and performant code, an interface is required that allows this code to interact securely with the host in the form of the operating system, browser or cloud environment and the resources provided by the host. This is where the WebAssembly System Interface (WASI) comes into play. WASI defines a standardized API for system calls that enables Wasm modules to use basic functions such as file system access or network communication without sacrificing sandbox security.

While Wasm has been available in a stable version for some time, WASI is still under development. The preview 0 and preview 1 versions already enabled basic system calls such as file access. The challenge for WASI is that the interface could not be based on a robust component model. Wasm only recognizes basic data types such as numbers and pointers at the lowest level, but no elements such as structured data types or strings. In order to exchange such data types across the boundaries of Wasm modules or with WASI, the corresponding data must be stored in Wasm's linear memory and pointers must be exchanged. Caller and callee must agree on a common data layout. Wasm does not contain any mechanisms to describe such data structures and the interfaces between Wasm modules.

To change this, the Wasm component model was created as a sub-project. Its aim is to create a standard with associated tools for the efficient interaction of separately compiled Wasm modules, which can be written in different programming languages. The language Wasm Interface Types (WIT for short) is used to describe the interfaces between the components (exports and imports).

At the beginning of the year, WASI reached an important milestone with version 0.2. This was followed in August by the update 0.2.1. The most important feature of the new preview version 0.2 is that it is based on the component model. WASI therefore publishes Wasm Components, which can be used to access the functions of the respective host. WASI 0.2 currently contains two categories of components (such categories are referred to as worlds in WIT):

  1. wasi-cli (Command-Line Interface): This world provides content for CLI programs such as file access, environment variables, random numbers and sockets.
  2. wasi-http: This World contains functions for HTTP around requests and responses.

Further worlds will follow. The upcoming version 0.3 of WASI is themed async, i.e. it will enable asynchronous operations.

If Go is the language in the world of containers, then Rust is the language in the world of Wasm modules. In this respect, it is no wonder that it did not take long for Rust to take its first steps towards supporting WASI 0.2. At the beginning of May, Rust version 1.78 was released with important new features for interaction with WASI.

The first innovation is the renaming of the compile target from wasm32-wasi to wasm32-wasip1. The p1 stands for Preview 1 and indicates that this is WASI version 0.1. So anyone who has already developed Wasm modules with Rust and WASI 0.1 must adapt their projects. There is time for this until the release of Rust version 1.84 in January 2025. Until then, wasm32-wasi will be gradually phased out with warnings from the stable version of Rust 1.81. Warnings or errors will appear earlier in the nightly version. Details can be found in the Rust blog.

A Rust target wasm32-wasip2 to create Wasm components for or with WASI 0.2 does not yet exist. However, there is the cargo parameter cargo component ), which temporarily fills this gap. It already makes it possible to reference Wasm components in Cargo.toml in a similarly to external crates.

cargo component creates Rust bindings automatically based on the definition of the interface. The command is an intermediate step towards the complete integration of Wasm components in Rust until Cargo itself works with them.

Don't miss any news – follow us on Facebook, LinkedIn or Mastodon.

This article was originally published in German. It was translated with technical assistance and editorially reviewed before publication.