Skip to content
Published on

WebAssembly Complete Guide 2025: Beyond the Browser — WASI, Component Model, Server-Side Wasm

Authors

Table of Contents

1. What is WebAssembly

WebAssembly (Wasm) is a binary instruction format for a stack-based virtual machine. Originally designed to provide near-native performance in web browsers, it has now expanded beyond the browser to servers, edge computing, and IoT.

1.1 Core Characteristics of Wasm

CharacteristicDescriptionSignificance
Binary FormatCompact binary encodingFast transmission, fast decoding
Stack MachineStack-based instruction executionSimple and efficient execution model
Linear MemoryContiguous byte arraySafe memory access, sandboxing
Type SafetyStrong type systemCompile-time verification, runtime safety
PortabilityArchitecture independentRuns on x86, ARM, RISC-V anywhere
SandboxIsolated execution environmentHost system protection

1.2 History of Wasm

2015: WebAssembly project announced (W3C)
2017: Wasm 1.0 supported in all 4 major browsers
2019: WASI initial proposal (non-browser Wasm)
2020: Wasm 1.0 becomes W3C official recommendation
2021: Component Model proposal, Fermyon founded
2022: Docker+Wasm tech preview, WASI Preview 1
2023: WASI 0.2 stabilized, Component Model matures
2024: GC proposal implemented, major runtime optimizations
2025: WASI 0.2 production-ready, server-side Wasm adoption accelerates

1.3 Wasm Binary Structure

Wasm Module Structure:
+------------------+
| Magic Number     |  0x00 0x61 0x73 0x6D ("\0asm")
| Version          |  0x01 0x00 0x00 0x00 (v1)
+------------------+
| Type Section     |  Function signature definitions
| Import Section   |  External function/memory imports
| Function Section |  Function indices
| Table Section    |  Indirect call tables
| Memory Section   |  Linear memory definition
| Global Section   |  Global variables
| Export Section   |  Publicly exposed functions/memory
| Start Section    |  Auto-execution function
| Element Section  |  Table initialization
| Code Section     |  Function bodies (bytecode)
| Data Section     |  Initial memory data
+------------------+

1.4 WAT (WebAssembly Text Format)

Understanding WAT, the text representation of Wasm, helps grasp its internal workings.

;; A simple Wasm module that adds two numbers
(module
  ;; Function type definition
  (type $add_type (func (param i32 i32) (result i32)))

  ;; Function implementation
  (func $add (type $add_type) (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add
  )

  ;; Linear memory (1 page = 64KB)
  (memory (export "memory") 1)

  ;; Export function
  (export "add" (func $add))
)

2. Browser Wasm

2.1 Compiling to Wasm from Various Languages

Rust - First-Class Wasm Citizen

// lib.rs - Rust to Wasm
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
    if n <= 1 {
        return n as u64;
    }
    let mut a: u64 = 0;
    let mut b: u64 = 1;
    for _ in 2..=n {
        let temp = a + b;
        a = b;
        b = temp;
    }
    b
}

#[wasm_bindgen]
pub struct ImageProcessor {
    width: u32,
    height: u32,
    pixels: Vec<u8>,
}

#[wasm_bindgen]
impl ImageProcessor {
    #[wasm_bindgen(constructor)]
    pub fn new(width: u32, height: u32) -> ImageProcessor {
        ImageProcessor {
            width,
            height,
            pixels: vec![0; (width * height * 4) as usize],
        }
    }

    pub fn grayscale(&mut self) {
        for chunk in self.pixels.chunks_exact_mut(4) {
            let gray = (0.299 * chunk[0] as f64
                + 0.587 * chunk[1] as f64
                + 0.114 * chunk[2] as f64) as u8;
            chunk[0] = gray;
            chunk[1] = gray;
            chunk[2] = gray;
        }
    }

    pub fn pixels_ptr(&self) -> *const u8 {
        self.pixels.as_ptr()
    }
}
# Rust -> Wasm build
wasm-pack build --target web

C/C++ - Emscripten

// image_filter.c - C to Wasm
#include <emscripten.h>
#include <stdint.h>

EMSCRIPTEN_KEEPALIVE
void apply_blur(uint8_t* pixels, int width, int height) {
    uint8_t* temp = (uint8_t*)malloc(width * height * 4);

    for (int y = 1; y < height - 1; y++) {
        for (int x = 1; x < width - 1; x++) {
            for (int c = 0; c < 3; c++) {
                int sum = 0;
                for (int dy = -1; dy <= 1; dy++) {
                    for (int dx = -1; dx <= 1; dx++) {
                        sum += pixels[((y+dy)*width + (x+dx))*4 + c];
                    }
                }
                temp[(y*width + x)*4 + c] = sum / 9;
            }
            temp[(y*width + x)*4 + 3] = pixels[(y*width + x)*4 + 3];
        }
    }

    memcpy(pixels, temp, width * height * 4);
    free(temp);
}
# C -> Wasm build
emcc image_filter.c -O3 -s WASM=1 \
  -s EXPORTED_FUNCTIONS='["_apply_blur"]' \
  -s EXPORTED_RUNTIME_METHODS='["cwrap"]' \
  -o image_filter.js

2.2 JavaScript Interop

// Loading and using Wasm modules
async function initWasm() {
  // Method 1: fetch + instantiate
  const response = await fetch('module.wasm');
  const bytes = await response.arrayBuffer();
  const { instance } = await WebAssembly.instantiate(bytes, {
    env: {
      // Provide host functions to Wasm
      log_value: (value) => console.log('Wasm says:', value),
      get_time: () => Date.now(),
    }
  });

  // Call Wasm function
  const result = instance.exports.add(10, 20);
  console.log('Result:', result); // 30

  // Access linear memory
  const memory = new Uint8Array(instance.exports.memory.buffer);
  // Read/write data in memory

  return instance;
}

// Method 2: wasm-bindgen (Rust)
import init, { fibonacci, ImageProcessor } from './pkg/my_wasm.js';

async function main() {
  await init();

  console.log('fib(40):', fibonacci(40));

  const processor = new ImageProcessor(800, 600);
  processor.grayscale();
}

2.3 Key Browser Wasm Use Cases

Use CaseExamplesPerformance Gain
Image/Video ProcessingPhotoshop Web, FFmpeg.wasm10-50x vs JS
Game EnginesUnity WebGL, Unreal Engine70-90% of native
Codecs/CompressionAV1 decoding, Brotli compression5-20x vs JS
CryptographySHA-256, AES operations3-10x vs JS
CAD/3D ModelingAutoCAD Web, SketchUpNear-native
Scientific ComputingSimulations, data analysis10-100x vs JS
PDF Processingpdf.js acceleration, rendering3-5x improvement

3. WASI 0.2: System Interface

WASI (WebAssembly System Interface) is a standard for Wasm to safely access system resources like filesystems and networks outside the browser.

3.1 WASI 0.2 Interfaces

WASI 0.2 Structure:
+----------------------------------+
| wasi:cli        (CLI app support)|
| wasi:http       (HTTP client/server) |
| wasi:filesystem (Filesystem access)  |
| wasi:sockets    (Network sockets)    |
| wasi:clocks     (Time-related)       |
| wasi:random     (Random generation)  |
| wasi:io         (Stream I/O)         |
+----------------------------------+
| Component Model (Foundation layer)   |
+----------------------------------+
| Wasm Core (Execution engine)         |
+----------------------------------+

3.2 WASI HTTP Server (Rust)

// Rust + WASI HTTP Server
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct TodoItem {
    id: u32,
    title: String,
    completed: bool,
}

#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
    let method = req.method().as_str();
    let path = req.path();

    match (method, path) {
        ("GET", "/api/todos") => {
            let todos = vec![
                TodoItem { id: 1, title: "Learn WASI".into(), completed: false },
                TodoItem { id: 2, title: "Build Wasm app".into(), completed: false },
            ];
            Ok(Response::builder()
                .status(200)
                .header("content-type", "application/json")
                .body(serde_json::to_string(&todos)?)
                .build())
        },
        ("POST", "/api/todos") => {
            let body: TodoItem = serde_json::from_slice(req.body())?;
            Ok(Response::builder()
                .status(201)
                .header("content-type", "application/json")
                .body(serde_json::to_string(&body)?)
                .build())
        },
        _ => Ok(Response::builder()
            .status(404)
            .body("Not Found")
            .build())
    }
}

3.3 Capability-Based Security Model

WASI's core security model is capability-based. Programs can only use permissions explicitly granted to them.

# WASI runtime capability examples
# Allow read-only access to specific directory
wasmtime run --dir /data::/data:readonly my-app.wasm

# Allow network access
wasmtime run --tcplisten 0.0.0.0:8080 my-server.wasm

# Pass environment variables
wasmtime run --env KEY=VALUE my-app.wasm
Traditional Security Model (Ambient Authority):
  Process -> [Full filesystem access]
          -> [All network access]
          -> [All env variables readable]

WASI Security Model (Capability-Based):
  Wasm Module -> [Only /data directory, read-only]
              -> [Only listen on localhost:8080]
              -> [Only specified env variables accessible]

4. Component Model: Module Composition

The Component Model is a standard for composing Wasm modules into complex applications.

4.1 WIT (Wasm Interface Type)

// todo.wit - Interface definition
package example:todo@0.1.0;

interface types {
    record todo-item {
        id: u32,
        title: string,
        completed: bool,
    }

    variant todo-error {
        not-found(string),
        validation-error(string),
        storage-error(string),
    }
}

interface todo-store {
    use types.{todo-item, todo-error};

    list-todos: func() -> result<list<todo-item>, todo-error>;
    get-todo: func(id: u32) -> result<todo-item, todo-error>;
    create-todo: func(title: string) -> result<todo-item, todo-error>;
    update-todo: func(id: u32, title: string, completed: bool) -> result<todo-item, todo-error>;
    delete-todo: func(id: u32) -> result<_, todo-error>;
}

world todo-app {
    import wasi:http/outgoing-handler@0.2.0;
    import wasi:logging/logging;

    export todo-store;
}

4.2 Component Composition

# Compose multiple components into a single app
# 1. Build each component
cargo component build --release  # Rust component
componentize-py -d todo.wit -w todo-app app.py  # Python component

# 2. Compose components
wasm-tools compose \
  --definitions auth-component.wasm \
  --definitions db-component.wasm \
  app-component.wasm \
  -o composed-app.wasm

# 3. Run composed component
wasmtime serve composed-app.wasm

4.3 Benefits of the Component Model

BenefitDescription
Language-Independent CompositionCombine Rust + Python + Go modules into one
Type-Safe InterfacesContracts guaranteed by WIT definitions
Sandbox IsolationMemory isolation between components
LightweightTens of times lighter than containers
Fast StartupMicrosecond-level initialization
PortabilityRuns anywhere

5. Server-Side Wasm Frameworks

5.1 Fermyon Spin

Spin is a framework for building Wasm-based microservices.

# spin.toml - Spin app configuration
spin_manifest_version = 2

[application]
name = "my-api"
version = "1.0.0"
description = "Wasm-based API server"

[[trigger.http]]
route = "/api/hello"
component = "hello"

[[trigger.http]]
route = "/api/users/..."
component = "users"

[component.hello]
source = "target/wasm32-wasi/release/hello.wasm"
allowed_outbound_hosts = []

[component.users]
source = "target/wasm32-wasi/release/users.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
key_value_stores = ["default"]
sqlite_databases = ["default"]
// Spin HTTP handler (Rust)
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use spin_sdk::key_value::Store;

#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
    // Use Key-Value store
    let store = Store::open_default()?;

    match req.method().as_str() {
        "GET" => {
            let key = req.path().trim_start_matches("/api/users/");
            match store.get(key)? {
                Some(value) => Ok(Response::builder()
                    .status(200)
                    .header("content-type", "application/json")
                    .body(value)
                    .build()),
                None => Ok(Response::builder()
                    .status(404)
                    .body("Not found")
                    .build()),
            }
        },
        "POST" => {
            let body = req.body().to_vec();
            let key = format!("user:{}", uuid::Uuid::new_v4());
            store.set(&key, &body)?;

            Ok(Response::builder()
                .status(201)
                .header("content-type", "application/json")
                .body(body)
                .build())
        },
        _ => Ok(Response::builder()
            .status(405)
            .body("Method not allowed")
            .build()),
    }
}
# Build and run Spin app
spin build
spin up  # Local run (port 3000)

# Deploy to Fermyon Cloud
spin deploy

5.2 wasmCloud

wasmCloud is a distributed Wasm application platform.

# wadm.yaml - wasmCloud app manifest
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: my-api
  annotations:
    description: "wasmCloud HTTP API"
spec:
  components:
    - name: api-handler
      type: component
      properties:
        image: ghcr.io/myorg/api-handler:0.1.0
      traits:
        - type: spreadscaler
          properties:
            instances: 5
        - type: link
          properties:
            target: httpserver
            namespace: wasi
            package: http
            interfaces: [incoming-handler]

    - name: httpserver
      type: capability
      properties:
        image: ghcr.io/wasmcloud/http-server:0.22.0
      traits:
        - type: link
          properties:
            target: api-handler
            namespace: wasi
            package: http
            interfaces: [incoming-handler]
            source_config:
              - name: default-http
                properties:
                  address: 0.0.0.0:8080

5.3 Server-Side Wasm Framework Comparison

FeatureFermyon SpinwasmCloudLunatic
FocusHTTP microservicesDistributed applicationsActor model
Deploy ModelSingle node / CloudDistributed latticeCluster
StorageKV, SQLite, RedisCapability ProvidersBuilt-in
Language SupportRust, Go, JS, PythonRust, Go, AssemblyScriptRust, AssemblyScript
Cold StartSub-1msSub-1msFew ms
MaturityGAGAEarly
Cloud ServiceFermyon CloudCosmonicNone

6. Docker + Wasm

Docker Desktop natively supports Wasm containers.

6.1 Docker Wasm Architecture

Traditional Linux Container:
  Docker Engine -> containerd -> runc -> Linux Container
                                         (full OS, tens-hundreds MB)

Wasm Container:
  Docker Engine -> containerd -> runwasi -> Wasm Runtime (wasmtime/wasmedge)
                                            (Wasm module, few MB)

6.2 Building Wasm Docker Images

# Dockerfile.wasm - Wasm container image
FROM scratch
COPY target/wasm32-wasi/release/my-app.wasm /my-app.wasm
ENTRYPOINT ["/my-app.wasm"]
# Build and run Wasm image
docker buildx build --platform wasi/wasm -t my-wasm-app .
docker run --runtime=io.containerd.wasmtime.v1 \
  --platform wasi/wasm \
  -p 8080:8080 \
  my-wasm-app

6.3 Docker Compose with Wasm

# docker-compose.yml - Mixed Wasm + Linux containers
version: "3"

services:
  # Wasm service (ultra-lightweight)
  api:
    image: my-wasm-api:latest
    runtime: io.containerd.wasmtime.v1
    platform: wasi/wasm
    ports:
      - "8080:8080"
    environment:
      - DB_HOST=postgres

  # Traditional Linux container
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data

  # Wasm worker service
  worker:
    image: my-wasm-worker:latest
    runtime: io.containerd.wasmtime.v1
    platform: wasi/wasm
    environment:
      - QUEUE_URL=redis://redis:6379

  redis:
    image: redis:7-alpine

volumes:
  pgdata:

6.4 Wasm vs Linux Container Comparison

FeatureLinux ContainerWasm Container
Image Size50MB-1GB1-10MB
Startup Time100ms-secondsSub-1ms
Memory Usage50MB-GBs1-50MB
Security ModelNamespaces/cgroupsSandbox/Capability
PortabilityRequires Linux kernelArchitecture independent
Process IsolationOS levelLanguage level
NetworkingFull supportWASI sockets (limited)
FilesystemFull supportWASI FS (limited)

7. Edge Wasm

7.1 Cloudflare Workers

// Cloudflare Worker (Wasm-based)
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.pathname === '/api/compute') {
      // Perform heavy computation with Wasm module
      const wasmModule = await import('./compute.wasm');
      const result = wasmModule.heavy_computation(42);

      return new Response(JSON.stringify({ result }), {
        headers: { 'Content-Type': 'application/json' }
      });
    }

    // Use KV store
    if (url.pathname.startsWith('/api/cache/')) {
      const key = url.pathname.split('/').pop();

      if (request.method === 'GET') {
        const value = await env.MY_KV.get(key);
        return new Response(value || 'Not found', {
          status: value ? 200 : 404
        });
      }

      if (request.method === 'PUT') {
        const body = await request.text();
        await env.MY_KV.put(key, body, { expirationTtl: 3600 });
        return new Response('OK');
      }
    }

    return new Response('Not found', { status: 404 });
  }
};

7.2 Fastly Compute

// Fastly Compute (Rust + Wasm)
use fastly::{Error, Request, Response};
use fastly::http::StatusCode;

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    let path = req.get_path().to_string();

    match path.as_str() {
        "/api/hello" => {
            Ok(Response::from_status(StatusCode::OK)
                .with_body_text_plain("Hello from Fastly Compute!"))
        },
        path if path.starts_with("/api/proxy/") => {
            // Proxy to backend
            let backend_path = path.trim_start_matches("/api/proxy");
            let mut backend_req = req;
            backend_req.set_path(backend_path);
            backend_req.send("origin_backend")
        },
        _ => {
            Ok(Response::from_status(StatusCode::NOT_FOUND)
                .with_body_text_plain("Not found"))
        }
    }
}

7.3 Edge Wasm Platform Comparison

PlatformRuntimeLanguagesCold StartFree Tier
Cloudflare WorkersV8 + WasmJS, Rust, C++0ms (always loaded)100K req/day
Fastly ComputeWasmtimeRust, Go, JSFew msNone
Vercel Edge FunctionsV8 + WasmJS, TS0ms (always loaded)1M exec/month
Deno DeployV8 + WasmJS, TS, Wasm0ms100K req/day
Fermyon CloudSpinRust, Go, JS, PythonSub-1msFree beta

8. Language Support for Wasm

8.1 Rust - First-Class Citizen

Rust provides the strongest language support for Wasm.

// Cargo.toml
[package]
name = "my-wasm-app"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wit-bindgen = "0.25"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# Build targets
rustup target add wasm32-wasi     # WASI target
rustup target add wasm32-unknown-unknown  # Browser target

# Build
cargo build --target wasm32-wasi --release

# Convert to Component
wasm-tools component new target/wasm32-wasi/release/my_app.wasm \
  -o my_app.component.wasm

8.2 Go - TinyGo

// main.go - TinyGo Wasm
package main

import (
    "encoding/json"
    "net/http"

    spinhttp "github.com/fermyon/spin/sdk/go/v2/http"
)

type Response struct {
    Message string `json:"message"`
    Count   int    `json:"count"`
}

func init() {
    spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) {
        resp := Response{
            Message: "Hello from Go Wasm!",
            Count:   42,
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    })
}

func main() {}
# Build Wasm with TinyGo
tinygo build -target=wasi -o main.wasm main.go

8.3 Python - componentize-py

# app.py - Python Wasm (Spin)
from spin_sdk.http import IncomingHandler, Request, Response
import json

class IncomingHandler(IncomingHandler):
    def handle_request(self, request: Request) -> Response:
        if request.method == "GET" and request.uri == "/api/hello":
            body = json.dumps({
                "message": "Hello from Python Wasm!",
                "path": request.uri,
            })
            return Response(
                200,
                {"content-type": "application/json"},
                bytes(body, "utf-8")
            )

        return Response(404, {}, b"Not found")
# Python -> Wasm component
componentize-py -d spin-http.wit -w spin-http-trigger app -o app.wasm

8.4 JavaScript - jco

// app.js - JavaScript Wasm Component
import { handle } from 'wasi:http/incoming-handler@0.2.0';

export const incomingHandler = {
  handle(request, responseOut) {
    const headers = new Headers();
    headers.set('Content-Type', 'application/json');

    const body = JSON.stringify({
      message: 'Hello from JS Wasm!',
      method: request.method(),
      path: request.pathWithQuery(),
    });

    const response = new OutgoingResponse(headers);
    response.setStatusCode(200);

    const bodyStream = response.body();
    bodyStream.write(new TextEncoder().encode(body));
    bodyStream.close();

    responseOut.set(response);
  }
};
# JavaScript -> Wasm Component
jco componentize app.js -w wasi-http.wit -o app.wasm

8.5 Language Support Comparison

LanguageWasm MaturityWASI SupportComponent ModelBinary SizeNotes
RustVery HighFullFull1-5MBFirst-class citizen
C/C++HighFullPartial0.5-3MBEmscripten
Go (TinyGo)MediumFullFull2-10MBSome std Go unsupported
PythonMediumFullFull10-30MBcomponentize-py
JavaScriptMediumFullFull5-15MBjco
C# (.NET)MediumPartialEarly10-50MBNativeAOT-LLVM
SwiftEarlyPartialEarly5-20MBSwiftWasm
KotlinEarlyPartialEarly10-30MBKotlin/Wasm

9. Performance Comparison

9.1 Cold Start Comparison

PlatformCold StartMemory UsageNotes
Wasm (Spin)0.5-1ms2-10MBMicrosecond level
Wasm (wasmtime)1-5ms5-20MBGeneral purpose
Lambda (Python)150-300ms50-128MBSlower with VPC
Lambda (Java)800-3000ms128-512MBImprovable with SnapStart
Docker Container500-5000ms50MB-1GBImage size dependent
Cloud Run300-2000ms128MB-8GBInstance type dependent

9.2 Throughput Comparison

HTTP "Hello World" benchmark (single instance):

Spin (Rust/Wasm):     ~150,000 req/s
Native Rust (Actix):  ~200,000 req/s
Go (net/http):        ~120,000 req/s
Node.js (Express):    ~30,000 req/s
Python (FastAPI):     ~10,000 req/s

Wasm achieves 70-90% of native performance

9.3 Memory Efficiency

Single HTTP service memory usage:

Wasm (Spin):          2-5 MB
Wasm (wasmtime):      5-15 MB
Node.js:              30-80 MB
Python:               30-60 MB
Java (JVM):           100-300 MB
.NET:                 50-150 MB
Go:                   10-30 MB

Concurrent services in 1GB memory:
Wasm: ~200 services
Node.js: ~15 services
Java: ~5 services

10. Security Model

10.1 Wasm Sandbox

Traditional Process:
+------------------------------------------+
| Process                                  |
|  - Full filesystem access                |
|  - All network access                    |
|  - Unlimited system calls                |
|  - Other process memory (via exploit)    |
+------------------------------------------+

Wasm Sandbox:
+------------------------------------------+
| Wasm Module                              |
|  +------------------------------------+  |
|  | Linear Memory (module-private)      |  |
|  | - Bounds checking                   |  |
|  | - No host memory access             |  |
|  +------------------------------------+  |
|  | Only permitted system interfaces    |  |
|  | - wasi:filesystem (specific paths)  |  |
|  | - wasi:sockets (specific addresses) |  |
|  +------------------------------------+  |
+------------------------------------------+

10.2 Capability-Based Security Principles

PrincipleDescriptionExample
No Ambient AuthorityNo default permissionsNo filesystem or network access
Principle of Least PrivilegeGrant only minimal permissionsOnly specific directory access
Explicit Capability PassingExplicit permission transferHost passes handles
RevocablePermissions can be revokedRuntime permission removal

10.3 Security Comparison

Security AspectContainersWasm
Isolation LevelOS level (cgroup/namespace)Language level (bytecode verification)
Memory SafetyDepends on kernelBuilt-in bounds checking
System CallsFiltered via seccompLimited via WASI
Escape PotentialPossible via kernel vulnerabilityExtremely difficult
Permission ModelUser/group basedCapability based
Code VerificationNoneVerified at load time

11. Real-World Use Cases

11.1 Plugin Systems

// Host application - plugin loader
use wasmtime::*;
use wasmtime_wasi::WasiCtxBuilder;

fn load_plugin(plugin_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    let engine = Engine::default();
    let mut linker = Linker::new(&engine);
    wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;

    // Grant minimal permissions to plugin
    let wasi = WasiCtxBuilder::new()
        .inherit_stdout()  // Only stdout allowed
        // No filesystem access
        // No network access
        .build();

    let mut store = Store::new(&engine, wasi);
    let module = Module::from_file(&engine, plugin_path)?;
    let instance = linker.instantiate(&mut store, &module)?;

    // Call plugin function
    let process = instance
        .get_typed_func::<(i32,), i32>(&mut store, "process")?;
    let result = process.call(&mut store, (42,))?;

    println!("Plugin result: {}", result);
    Ok(())
}

11.2 Edge Computing

Edge Wasm Architecture:

User Request -> [CDN Edge (300+ PoPs)]
                  |
                  v
               [Wasm Worker]
                  |
                  +-> Cache Hit: Instant response (0ms)
                  |
                  +-> Cache Miss: Request to origin server
                  |               |
                  |               v
                  |          [Origin Server]
                  |               |
                  v               v
               [Response + Cache Store]

Benefits:
- Executes at the location closest to the user
- Nearly zero cold start
- Automatic global distributed deployment

11.3 Serverless Functions

Lambda vs Wasm Serverless:

AWS Lambda:
  Request -> API Gateway -> Lambda Runtime -> Function Execution
  Cold Start: 100ms-8s
  Memory: 128MB-10GB
  Billing: Per 1ms

Wasm Serverless (Spin/Fermyon):
  Request -> Spin Runtime -> Wasm Module Execution
  Cold Start: Sub-0.5ms
  Memory: 2-50MB
  Billing: Per request

11.4 Blockchain Smart Contracts

Multiple blockchains have adopted Wasm as their smart contract execution engine.

BlockchainWasm RuntimeLanguage Support
PolkadotSubstrateRust (ink!)
NearWasmerRust, AssemblyScript
Cosmos (CosmWasm)WasmerRust
Dfinity (ICP)CustomRust, Motoko

12. Wasm vs Containers

12.1 Comprehensive Comparison

FeatureWasmContainers
Startup TimeMicroseconds-millisecondsMilliseconds-seconds
Image Size1-50MB50MB-GBs
Memory Usage1-50MB50MB-GBs
CPU Overhead0-30%0-5%
SecurityStrong sandboxOS-level isolation
NetworkingWASI (limited)Full support
FilesystemWASI (limited)Full support
GPU SupportExperimentalFull support
EcosystemGrowingVery mature
DebuggingEvolvingMature
State ManagementStateless recommendedStateful possible

12.2 When to Choose Wasm

Choose Wasm when:

  • Sub-millisecond cold starts needed
  • Ultra-lightweight services required
  • Building plugin/extension systems
  • Edge computing
  • Multi-language module composition
  • Strong sandbox isolation needed
  • Resource-constrained environments (IoT)

Choose Containers when:

  • Complex networking required
  • GPU usage needed
  • Legacy application support
  • Rich ecosystem needed
  • State preservation required
  • Large memory/storage needs

13. Future Outlook

13.1 In-Progress Wasm Proposals

ProposalStatusDescription
GC (Garbage Collection)Phase 4Support for Java, Kotlin, Dart GC languages
ThreadsPhase 3Shared memory multithreading
SIMDPhase 4 (Complete)128-bit SIMD operations
Exception HandlingPhase 4Native try/catch support
Stack SwitchingPhase 2Coroutines, async/await support
Memory64Phase 364-bit memory addressing
Branch HintingPhase 3Branch prediction hints
Tail CallPhase 4 (Complete)Tail call optimization

13.2 Wasm Future Roadmap

2025-2026 Outlook:
- WASI 0.2 fully stabilized and adopted by major clouds
- Component Model ecosystem matures
- Docker Wasm production-ready
- GC proposal implemented in major runtimes
- Threads proposal stabilized

2027+ Outlook:
- Wasm reaches parity with containers
- Default runtime for edge-first architectures
- Standard execution environment for IoT/embedded
- Multi-language component ecosystem established

14. Quiz

Q1. What is the core security model of WASI?

Answer: Capability-Based Security

WASI follows the "No Ambient Authority" principle. Wasm modules have no permissions by default, and can only use capabilities (file handles, network sockets, etc.) explicitly granted by the host. This contrasts with the traditional Unix ambient authority model.

Q2. What are the advantages of the Wasm Component Model?

Answer:

  • Language-independent composition: Combine modules written in Rust, Python, Go, etc. into one application
  • WIT interfaces: Type-safe contracts for inter-module communication
  • Sandbox isolation: Each component has its own memory space
  • Lightweight: Tens of times lighter than containers
Q3. Why are Wasm cold starts faster than Lambda?

Answer:

  • Wasm binaries are very small (1-10MB), making loading fast
  • Runtime initialization is at the microsecond level (no heavy initialization like JVM or Python interpreter)
  • AOT-compiled binaries execute directly
  • Linear memory model allows simple memory setup
  • No process/container creation overhead
Q4. How does Docker + Wasm work?

Answer:

Docker Desktop uses containerd's runwasi shim to run Wasm containers. Instead of the traditional runc, Wasm runtimes like wasmtime or wasmedge execute the container. Ultra-lightweight images can be built with a FROM scratch base containing only the .wasm file, and docker-compose can mix Linux containers and Wasm containers.

Q5. Why can Wasm not yet replace containers?

Answer:

  • WASI system interfaces are still limited (GPU, complex networking, etc.)
  • Ecosystem is immature compared to containers
  • Migrating legacy applications is difficult
  • State management is fundamentally stateless
  • Debugging tools are still evolving
  • Some languages have only early-stage Wasm support

However, Wasm is not meant to "replace" containers but rather to "complement" them, coexisting with containers in edge and lightweight service domains.


15. References

  1. WebAssembly Official Site - https://webassembly.org/
  2. WASI Official Documentation - https://wasi.dev/
  3. Component Model Specification - https://component-model.bytecodealliance.org/
  4. Fermyon Spin Documentation - https://developer.fermyon.com/spin/
  5. wasmCloud Documentation - https://wasmcloud.com/docs/
  6. Bytecode Alliance - https://bytecodealliance.org/
  7. wasmtime Runtime - https://wasmtime.dev/
  8. Docker Wasm Guide - https://docs.docker.com/desktop/wasm/
  9. Cloudflare Workers - https://developers.cloudflare.com/workers/
  10. Fastly Compute - https://developer.fastly.com/learning/compute/
  11. wasm-tools - https://github.com/bytecodealliance/wasm-tools
  12. WIT Specification - https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
  13. componentize-py - https://github.com/bytecodealliance/componentize-py