Extending Applications with WebAssembly

Sep 29, 2021

No application can satisfy all use cases. Extensibility is what turns applications into platforms.

We're at a crucial inflection point for program extensibility driven by WebAssembly. (What is WebAssembly?). Applications have historically been extended either at build time – by including functionality in the application package – or at runtime through HTTP APIs or RPC. WebAssembly lets us extend applications at runtime on the client. But it's not just the web where extensibility is getting better.

First, let's look at infrastructure pluggability. What happens when you don't want to expose an API to extend applications? You might be in this situation when either a network call would take too long or the API surface is not well-defined or rapidly changing.

Envoy, the L7 proxy used for service architecture (e.g., service mesh on Kubernetes), uses WebAssembly to extend the proxy. You can read the rationale and specifics on GitHub.

This sort of extension architecture means that users can extend Envoy using a wide variety of languages while continuing to use the official unmodified distribution and images. This also solves some of the maintenance issues with upgrading or building against an unstable Envoy API or ABI.

In the data world, Redpanda (a Kafka-compatible distribution) uses WebAssembly to do real-time transformations on streaming data. This lets users run arbitrary functions written in different languages on streaming data without having to move data around to different servers. You can read their blog post here.

How do you dynamically extend a client application at runtime safely? In the browser, you could always extend an application by including some JavaScript as long as you trust the code. Unfortunately, that rules out the majority of user-generated code or off-the-shelf extensions. You most likely want to run any user code in a sandbox (see: Different Types of Software Containers).

On the front end, Figma is using WebAssembly to sandbox their plugin architecture. Figma uses QuickJS, which is co-authored by Fabrice Bellard, who also wrote the machine emulator QEMU and media toolkit FFmpeg (quite the resume!). This lets Figma run potentially untrusted JavaScript code in the browser, selectively removing access to the DOM or network and running the code in a stack-based virtual machine.

Stackblitz, an online IDE, is using WebAssembly to sandbox Node.js in the browser. This isn't extensibility or plugin architecture per se, but I imagine you could make it into one. They call their technology "WebContainers," and it's pretty interesting because WebAssembly falls short when trying to run something with so many dependencies on non-WebAssembly features (like a filesystem or network stack). I can't imagine how much magic went into making this work. Their announcement post here includes a few details on how it works.

Creating a plugin or extension architecture is more important than ever for both infrastructure and SaaS applications. Customers demand the right to extend and modify software to fit their use cases – and the long tail of use cases continues to grow as more and more workflows become digital. Vendors that can create a true platform enjoy network effects and moats that make their businesses (and products) difficult to copy and beat. And finally, more and more users are becoming technical enough to write a function or two to extend their software, so software should give them that opportunity.