WebAssembly Beyond the Browser: Edge Computing and Serverless
WasmHub Team
February 26, 2025 · 9 min read
The browser is no longer WebAssembly's primary home. A growing number of cloud platforms have adopted Wasm as their preferred execution model for serverless and edge computing — and for good reasons that go beyond raw performance. This post explores why Wasm is a compelling fit for these environments and how the major platforms are using it today.
Why Wasm Works So Well at the Edge
Serverless and edge computing have a fundamental tension: you want to run arbitrary user code close to end users, with strong isolation between tenants, with startup times measured in microseconds rather than seconds, and at a cost that makes running thousands of tiny functions economical.
Traditional containers solve isolation but carry a Linux kernel's worth of overhead. Language-specific runtimes (Node.js, Python, JVM) solve developer experience but leak abstractions across tenant boundaries. Wasm solves all three:
- Isolation: each module has its own linear memory space with no access to the host filesystem, network, or other modules' memory unless explicitly granted
- Cold start: a Wasm module can be compiled and instantiated in under a millisecond — orders of magnitude faster than spinning up a container or even a Node.js process
- Size: Wasm binaries are typically 100 KB–5 MB, not hundreds of megabytes; they distribute and cache trivially
The WASI capability model adds a fourth property that's crucial for multi-tenant platforms: principle of least privilege by default. A module that doesn't need network access simply doesn't receive a socket capability — no firewall rules required.
Cloudflare Workers
Cloudflare Workers was one of the first platforms to bet heavily on Wasm. It runs on V8 isolates across Cloudflare's 300+ edge locations, and every Worker can execute Wasm modules at the same edge node that serves the HTTP request. As of 2026, Workers also runs Wasm components built with the Component Model — jco transpiles a component into a form V8 can host, so the same component binary you ship to Node or a Spin app can run unmodified on Workers.
Workers are written in JavaScript or TypeScript, but you can load Wasm modules alongside the JS glue:
// worker.js — loaded at the edge node nearest to the request
import wasmBytes from './image-resizer.wasm'
const { instance } = await WebAssembly.instantiate(wasmBytes)
const { resize, alloc, dealloc, memory } = instance.exports
export default {
async fetch(request) {
if (request.method !== 'POST') {
return new Response('Expected POST', { status: 405 })
}
const buffer = await request.arrayBuffer()
const input = new Uint8Array(buffer)
const ptr = alloc(input.byteLength)
new Uint8Array(memory.buffer, ptr, input.byteLength).set(input)
const outPtr = resize(ptr, input.byteLength, 400, 300)
const outLen = /* read from Wasm */ instance.exports.last_output_size()
const output = new Uint8Array(memory.buffer, outPtr, outLen).slice()
dealloc(ptr, input.byteLength)
return new Response(output, {
headers: { 'Content-Type': 'image/webp' },
})
},
}Cloudflare also ships Workers written in Rust using the worker crate, which compiles to Wasm under the hood. Their internal Wasm-native products — like Cloudflare R2's storage layer — are built entirely this way. On the AI side, Workers AI reached GA with 50+ open-source models (image classification, text generation, object detection) running on Cloudflare's GPUs — reachable from any Worker with a binding, not a separate Wasm runtime.
Fastly Compute
Fastly's Compute platform takes a more opinionated approach: your entire function is a Wasm module, not a Wasm module called from JavaScript. You write in Rust, Go, AssemblyScript, or any WASI-compatible language, compile to Wasm, and deploy via the Fastly CLI.
// src/main.rs — a Fastly Compute handler in Rust
use fastly::http::{HeaderValue, Method, StatusCode};
use fastly::{Error, Request, Response};
#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
match req.get_method() {
&Method::GET => {
let mut resp = Response::from_status(StatusCode::OK);
resp.set_body("Hello from the edge!");
Ok(resp)
}
_ => Ok(Response::from_status(StatusCode::METHOD_NOT_ALLOWED)),
}
}fastly compute build # compiles to .wasm
fastly compute deploy # ships to Fastly's edgeFastly's viceroy tool lets you run the same Wasm binary locally for development — same runtime, same WASI environment, same behavior. No "works on my machine" problems. On the performance side, the original 2019 Lucet benchmarks claimed sub-50 µs instantiation per module; Fastly's current Compute product still bills "duration" as wall-clock time rounded up to 50 ms, but a current 2026 cold-start headline number is hard to pin down from public docs. Plan on "very fast, sub-millisecond" rather than a specific microsecond figure.
One notable 2026 change: customers who purchased Compute on or before March 17 2026 are still on duration-based billing; new customers appear to be migrated off it. If you're starting a new project, double-check the current pricing model on the Fastly docs before designing around it.
Fermyon Spin
Spin from Fermyon is the most Wasm-native of the major frameworks. It's built entirely around the WASI Component Model: your application is a set of composable Wasm components wired together by a Spin manifest. The current line is Spin 4.x (4.0.1 as of June 2026), and the manifest format is now v3 — the v2 manifest shown in older tutorials is legacy.
# spin.toml (manifest v3 — Spin 3.x and 4.x)
spin_manifest_version = 3
[application]
name = "api-service"
version = "1.0.0"
[[trigger.http]]
route = "/api/..."
component = "handler"
[component.handler]
source = "target/wasm32-wasip2/release/handler.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
[component.handler.build]
command = "cargo component build --release"The allowed_outbound_hosts line is a perfect example of the capability model in action: the component can only make HTTP requests to the listed hosts — nothing else. You add capabilities in the manifest; you don't subtract them with firewall rules. Spin 4.0 (April 2026) added fine-grained capability inheritance, build profiles, and async APIs for PostgreSQL, MySQL, KV, SQLite, and Redis, on top of Wasmtime 43.
Spin runs on Fermyon Cloud, on any Kubernetes cluster (via SpinKube), on bare metal with Wasmtime, and locally with spin up. The same .wasm binary works everywhere. Note that Fermyon was acquired by Akamai in May 2026, so the project's long-term home is now inside Akamai's edge platform portfolio alongside EdgeWorkers.
Docker + Wasm
Docker shipped native Wasm support in Docker Desktop 4.15 (late 2023) and has continued expanding it. The key piece is a containerd shim — containerd-shim-wasmtime-v1 — that lets the container runtime launch a Wasm module instead of a Linux process when the image's platform is wasi/wasm.
# Build stage — compile Rust to WASI
FROM rust:1.78 AS builder
WORKDIR /app
COPY . .
RUN rustup target add wasm32-wasip1
RUN cargo build --release --target wasm32-wasip1
# Runtime — a scratch image with the Wasm binary only
FROM scratch
COPY --from=builder /app/target/wasm32-wasip1/release/myapp.wasm /myapp.wasm
ENTRYPOINT ["/myapp.wasm"]docker buildx build --platform wasi/wasm -t myapp .
docker run --runtime=io.containerd.wasmtime.v1 --platform=wasi/wasm myappThe resulting image is tiny (often under 5 MB), starts instantly, and runs on any architecture — the Wasm binary is the same on x86-64 and ARM64. Kubernetes clusters running the WasmEdge or Wasmtime shim can schedule Wasm workloads alongside regular containers with no special node configuration beyond installing the shim.
AWS Lambda and Spin-based Serverless
AWS Lambda doesn't natively run Wasm today, but several deployment patterns exist. The most common is running a Wasm runtime (Wasmtime or Wasmer) as the Lambda function itself, which then loads and executes Wasm modules from S3 or bundled in the Lambda package. This gives you the isolation and cold-start benefits of Wasm inside Lambda's billing model.
Fermyon Cloud's managed offering is the most turnkey option for Spin-based serverless: deploy a component, get an HTTPS endpoint, pay per request. No infrastructure to manage.
Shopify Functions
Shopify Functions is one of the most compelling public "Wasm in production at scale" stories. Every Shopify Function — discount, payment, delivery, cart/checkout validation, fulfillment constraints — compiles to a WebAssembly module that Shopify loads in response to a GraphQL query. The runtime is built on a Rust "Wasm Engine" service that wraps a WebAssembly runtime, with end-to-end p99 in the low single-digit milliseconds and module execution around ~100 µs p99 (2020 figures, still representative).
Rust is the recommended language for performance (especially with large carts); JavaScript/AssemblyScript is also supported. As of 2026, Functions is GA and handles hundreds of thousands of module executions per minute under load — a useful data point for anyone wondering whether Wasm is "ready" for serious production traffic.
wasmCloud, Cosmonic, and Deno Deploy
A few more platforms worth knowing about in 2026:
- wasmCloud (CNCF Incubating, co-led by Cosmonic and Microsoft) is a distributed application runtime that treats each capability — HTTP, messaging, key-value, blob storage — as an interchangeable Wasm component. American Express, Adobe, and Machine Metrics are among the named production users. Cosmonic's managed control plane reached Technical Preview in July 2025 and is the easiest way to try wasmCloud without standing it up yourself; SandboxMCP, Cosmonic's 2026 bet, positions Wasm as a security boundary for sandboxed AI agent execution and MCP server generation.
- Deno Deploy has had native Wasm module imports (with TypeScript type checking) since Deno 2.1, plus the official
wasmbuildtool for generating Rust-to-Wasm components with TS bindings. If you're already in the Deno ecosystem, Wasm "just works" via the standardWebAssembly.*API. - Vercel Functions added an explicit Wasm runtime alongside Node, Bun, and Edge — pre-compiled
.wasmmodules can be imported with a?modulesuffix and instantiated fromWebAssembly.instantiate(). Wasm is not the headline runtime here, but it's a first-class option. - Akamai EdgeWorkers runs on V8 isolates (not Wasm-first) and can call out to Wasm modules for compute-heavy work. With Fermyon now part of Akamai, expect the EdgeWorkers and Spin worlds to converge over the next 12–18 months.
The Emerging Pattern
Across all these platforms, a common pattern is emerging: Wasm as the universal unit of deployment. One binary, compiled once, runs on Cloudflare's V8 isolates, Fastly's AOT-compiled edge nodes, Fermyon's Spin runtime, a Kubernetes pod via the WasmEdge shim, or a developer's laptop via wasmtime run. The same isolation guarantees, the same security model, the same binary.
This is the promise that containers made in 2013 — "build once, run anywhere" — but delivered at a finer granularity, with stronger security boundaries, and with startup times that make even the smallest functions economically viable. If you're building the next generation of serverless infrastructure, Wasm deserves a serious look.