WebAssembly on the server is one of those technologies that’s been “almost ready” for years. In 2026 the picture is finally clear: WASM isn’t replacing containers, but it has carved out specific workloads where it’s genuinely better. This post is the working knowledge of where, when, and how.
What changed in 2024–2026
Three things made WASM-on-server actually deployable:
- WASI 0.2 (the component model) — modules can finally describe their interfaces in a structured way, compose, and use shared types. The “Lego brick” promise.
- runwasi (and Spin’s containerd shim) — Wasm workloads run as first-class pods on Kubernetes via a containerd shim. Same
kubectl, same Helm. - Real adoption at scale — Fermyon Cloud serving 75M+ requests per second, American Express running internal FaaS on wasmCloud. Production scars exist.
WASI 1.0 is the next milestone (expected mid-2026). When it lands, the “experimental” caveat goes away.
The pitch (and the caveats)
WASM modules:
- Start in microseconds. Containers in hundreds of milliseconds.
- Are kilobytes, not megabytes.
- Run with capability-based security — no implicit access to filesystem, network, env vars. You wire what they can do.
- Are portable — same binary runs on Linux, macOS, Windows, ARM, x86, in a browser.
The caveats:
- Limited language support. Rust, Go (via TinyGo), Python (in 2026 via py2wasm — workable but slow), JS (with QuickJS), C/C++. No Java/Kotlin server-side yet that’s production-ready.
- No threads in many runtimes. WASI 0.2 has async, but threads-on-server are still rough.
- Library ecosystem is thin for anything that needs syscalls beyond the WASI ABI.
Translation: great for greenfield, glue, and edge. Not (yet) a Postgres replacement.
The workloads WASM actually wins
1. Edge functions / FaaS
Cold-start time matters most when you cold-start a lot. WASM at the edge starts in <1ms vs ~150ms for a container. At Cloudflare/Fermyon-edge scale, that’s the difference between viable and not.
2. Plugin systems
Want users to extend your service with sandboxed code? WASM modules with a defined component interface are the cleanest way. Envoy plugins, Istio policies, database extension languages are all moving this direction.
3. Multi-tenant request routing / transformations
Hot path code that runs on every request — auth checks, header rewrites, request shaping. Containers are too heavy; lambdas have too much latency. WASM hits the sweet spot.
4. Sandboxed user code
Online IDEs, customer-supplied code (Stripe-style webhooks, Shopify functions), eBPF-like data plane filters. WASM’s capability model gives you “code I don’t trust” with strong containment.
Where containers still win
- Long-running stateful services
- Anything needing the JVM, the Python interpreter (full SciPy stack), Node (most npm)
- DBs, message brokers, anything that wants raw threads + filesystems
- Workloads where the ecosystem isn’t WASM-ready
This isn’t “WASM replaces Kubernetes.” This is “WASM is another shim under your existing Kubernetes.”
How it runs on Kubernetes
Three pieces:
- Containerd shim —
containerd-shim-spinorcontainerd-shim-wasmtime. Tells containerd “this isn’t a container, run it via Wasmtime.” - RuntimeClass — Kubernetes resource that points pods at the Wasm shim instead of the default OCI runtime.
- Your pod — looks like a normal pod, but with
runtimeClassNameset.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: spin
handler: spin # matches the shim binary name on the node
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: hello-spin }
spec:
replicas: 1
selector: { matchLabels: { app: hello-spin } }
template:
metadata: { labels: { app: hello-spin } }
spec:
runtimeClassName: spin
containers:
- name: app
image: ghcr.io/example/hello-spin:1.0.0 # this is a Wasm image, not a Docker image
ports: [{ containerPort: 80 }]
What’s running on the node is a Wasmtime instance loading your Wasm module — milliseconds to start, ~MB of RAM. To Kubernetes, it’s a pod.
Three projects are leading the charge:
- Spin (Fermyon) — opinionated framework, great DX, runs anywhere from your laptop to a containerd-shim on K8s.
- wasmCloud — actor-model, distributed-by-default, lots of compose-able capability providers.
- runwasi — the lower-level shim that you build runtimes on top of. Wasmtime, WasmEdge, Wamr.
For most teams, Spin is the easiest entry point.
A working example with Spin
# spin.toml
spin_manifest_version = "1"
authors = ["you"]
name = "hello-spin"
version = "0.1.0"
[[component]]
id = "hello"
source = "target/wasm32-wasi/release/hello.wasm"
[component.trigger]
route = "/..."
// src/lib.rs
use spin_sdk::{
http::{IntoResponse, Request, Response},
http_component,
};
#[http_component]
fn handle(req: Request) -> impl IntoResponse {
Response::builder()
.status(200)
.header("content-type", "text/plain")
.body(format!("hello from {}", req.uri().path()))
.build()
}
spin build
spin up # local dev, on http://127.0.0.1:3000
spin registry push ghcr.io/me/hello:0.1.0
Deploy that to Kubernetes via the manifest above, and you have a Wasm service in pods. Cold start measured in milliseconds. Image size ~2MB.
Networking, storage, secrets
The capability-based model means you must explicitly wire what your module can do. Spin’s spin.toml declares allowed outbound hosts, key-value stores, sql backends:
[[component]]
id = "api"
source = "target/wasm32-wasi/release/api.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
[component.sqlite_databases]
default = "default"
[component.key_value_stores]
default = "default"
[component.trigger]
route = "/..."
Compare to Docker, where a container has full network namespace by default and is locked down only via NetworkPolicy. WASM is locked down by default and you open holes with intent. Net positive for security.
For storage, the WASI keyvalue and SQLite interfaces give you portable APIs that the runtime maps to backend implementations (in-memory locally, Redis/Postgres in production). The component model means your code doesn’t change.
Observability
The OTel ecosystem hasn’t fully caught up to WASM yet, but the shims expose enough hooks:
runwasiemits spans for module invocations.- Spin has built-in tracing exporters.
- Logs go through
stderrto your usual collector.
Expect this to mature significantly through 2026 with WASI 0.3.
Who’s actually using this
Real cases I’d point at:
- Fermyon Cloud — Spin-based serverless platform.
- Cosmonic / wasmCloud — distributed actors at edge.
- Cloudflare Workers — V8 isolates and Wasm; serving billions of requests.
- American Express — internal FaaS on wasmCloud.
- Envoy Wasm — request-path filters in production at every CDN you’ve heard of.
Greenfield projects in 2026 should genuinely consider WASM for FaaS-shaped workloads. Brownfield migrations: don’t bother.
A pragmatic adoption path
If you’re considering WASM on K8s, here’s the minimum-cost path:
- Pick one workload. A request transformation, a webhook receiver, an internal HTTP utility.
- Build it in Rust or TinyGo with Spin.
- Deploy with a
RuntimeClassto a sub-pool of nodes that have the shim installed. - Measure cold start, memory, throughput. Compare to a same-language container.
- Decide: does it earn the additional toolchain complexity?
For some workloads it won’t. For functions running at high cardinality with low latency budgets, it absolutely will.
Things that aren’t true (yet)
- “WASM is replacing containers.” No. It’s an additional runtime for specific workloads.
- “You don’t need Kubernetes anymore.” You probably do; it’s how you schedule WASM at scale.
- “WASM is faster than native code.” It’s close (within 10–20% for compiled languages), but not faster. Speed wins are about startup, not steady-state.
- “Browser WASM and server WASM are the same.” Different ABIs, different runtimes, different capabilities. The component model bridges them; the gap is closing but not closed.
What I’d watch in 2026
- WASI 1.0 — the moment “experimental” goes away.
- Component composition tooling —
wasm-tools composeis getting good; expect more. - Language support for Python and JS — fully WASI 0.2 compatible runtimes will unlock huge ecosystems.
- Service mesh integration — Istio’s Wasm plugins are real production traffic; expect more.
Read this next
- Kubernetes for App Developers — the runtime layer this builds on.
- Platform Engineering and IDPs — where WASM workloads belong if you adopt them.
- The Spin and wasmCloud docs — both have great tutorials.
If you want a working “Wasm on K8s” example with Spin, a containerd shim, and observability wired up, the repo’s on rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .