Updated: 2026-07-12

The promise of WebAssembly as a server-side runtime has gone through several phases since 2019. With stable runwasi, runtimes like WasmEdge and wasmtime integrated without friction, and mature Kubernetes support via RuntimeClass, it’s reasonable to ask whether the moment has arrived to mix Wasm workloads with classical Linux containers in production. The answer is nuanced and depends heavily on use case.

Key takeaways

  • containerd supports alternative shims via runwasi (containerd 2.0, or 1.7.7+ / 1.6.25+ on older branches) without external patches.

  • The most mature production runtimes are WasmEdge (server-oriented, native WASI Preview 2) and wasmtime (Bytecode Alliance technical reference).

  • Real Wasm advantages over Linux containers: startup (<10 ms vs hundreds of ms), image size (1–5 MB vs 20–40 MB), and by-design security (memory sandbox without shared kernel).

  • Real limits: language ecosystem (Rust and C mature, Java and Python experimental), more limited network access than standard Linux, and less mature observability.

  • Adoption makes sense for internal serverless, distributed edge, and untrusted code execution; not for long-running services with mature language ecosystems.

How Wasm integrates into containerd

containerd has a shim architecture: small processes implementing the low-level interface between containerd and the actual container engine. The default shim is runc for Linux containers. The runwasi[1] project, which originated on Microsoft’s Deislabs team and is now integrated as a non-core containerd sub-project, provides alternative shims connecting containerd with WebAssembly runtimes such as WasmEdge, wasmtime, Wasmer, and WAMR.

Per the official runwasi docs[2], the integration needs containerd 2.0, or on older branches 1.7.7+ / 1.6.25+, and requires no patches to the containerd binary itself:

# Install the WasmEdge shim
wget https://github.com/containerd/runwasi/releases/download/v0.4.0/
containerd-shim-wasmedge-v1-linux-amd64.tar.gz
tar -xzf containerd-shim-wasmedge-v1-linux-amd64.tar.gz
sudo mv containerd-shim-wasmedge-v1 /usr/local/bin/

# Restart containerd so it picks up the new shim
sudo systemctl restart containerd

In Kubernetes, the integration mechanism is the RuntimeClass object. The mental model is clean: the node can run Linux containers and Wasm modules simultaneously, the scheduler knows it, and the developer just picks the appropriate class. A node with the WasmEdge shim installed can serve both workload types without reconfiguration. This mixed-runtime model is analogous to the gVisor and alternative runtimes pattern where different isolation levels coexist in the same cluster.

Where the difference is real

Startup. A well-optimized Linux container starts in tens to hundreds of milliseconds from a warm image; an equivalent Wasm module starts in under 10 ms, sometimes in 1 ms. For functions that spin up and tear down on demand, the difference is decisive.

Image size. An OCI Linux image for a Go service runs 20–40 MB; its compiled Wasm equivalent is typically 1–5 MB, with no base-distribution dependencies. CNCF’s WebAssembly on Kubernetes practice guide[3] documents a real case where the Wasm image comes out at roughly a quarter the size of its lightweight Linux-container equivalent. For edge deployments across hundreds of locations, the bandwidth difference is real.

Security by construction. A Wasm module runs inside a memory-safe-by-design VM, with system access only through explicitly granted WASI capabilities. The attack surface is qualitatively smaller than a Linux container’s. For untrusted workloads or third-party code, this posture is superior.

Cross-architecture portability. A compiled Wasm module runs the same on x86_64, arm64, or unusual platforms without recompiling. For heterogeneous fleets of edge nodes, this simplifies the build pipeline.

Limitations to acknowledge

Language ecosystem. Rust compiles to Wasm WASI Preview 2 with very mature support. Go does it with limitations via TinyGo or experimentally with the mainline compiler. C and C++ via wasi-sdk work well. Java, Python, Node.js, and .NET remain hard or experimental. If the primary stack is enterprise Java or Python with native dependencies, migrating to Wasm is not a realistic option.

Network and system access. The wasi-sockets[4] proposal added TCP and UDP socket support to WASI Preview 2 with capability-based security (no open-by-default BSD sockets), but the API is still more limited than standard Linux. Services relying on advanced epoll, specific signals, or ioctl need to be rewritten or avoid those parts. WasmEdge, for its part, documents non-blocking networking support[5] for Rust, C, and JavaScript as one of its cloud-native extensions.

Observability. Standard Kubernetes observability tools (cAdvisor, Prometheus exporters) assume Linux processes with /proc and cgroups. A Wasm module has its own metrics API that must be wired up explicitly. OpenTelemetry has reasonable Wasm support, but maturity doesn’t match the traditional Linux ecosystem. Integrating this from the start with the 2026 observability stack is essential to avoid operating blind.

When it pays off and when it doesn’t

It pays off in three scenarios:

Internal serverless platform: Wasm on containerd delivers minimal cold start, strong isolation, and lower resource cost compared to Knative or OpenFaaS on Linux containers.

Edge and geographically distributed deployment: if you’re shipping logic to hundreds of nodes with limited bandwidth and a need for fast startup, Wasm is clearly better.

Untrusted code execution: marketplaces where customers upload code, data analysis with user scripts, dynamic plugins. Wasm’s by-design isolation is qualitatively superior to Linux containers for this case.

It doesn’t pay off for long-running services with mature language ecosystems (cold start isn’t a problem and native libraries matter), workloads with complex network or system-access requirements, or teams without the operational capacity to maintain two runtime surfaces.

How to evaluate before adopting

My practical recommendation for a team considering introducing Wasm on containerd is to evaluate before adopting:

  • Identify a concrete workload where the Wasm benefit is clear (lambda-like, edge, untrusted code).

  • Stand up a test cluster with runwasi and WasmEdge.

  • Deploy that workload and measure: startup time, memory, latency, and cost compared to the classic container version.

  • If the numbers justify the added complexity, proceed. If not, don’t introduce two surfaces to maintain.

The second principle is don’t migrate existing services just for the sake of migrating. Wasm shines for new workloads designed to take advantage of its characteristics, not as a forced replacement for workloads that already run fine in Linux containers.

The third principle is integrate observability from the start. OpenTelemetry with Wasm support from the first deployment, not bolted on afterward.

This article is also available in Spanish.

Sources

  1. runwasi
  2. official runwasi docs
  3. WebAssembly on Kubernetes practice guide
  4. wasi-sockets
  5. non-blocking networking support