Skip to main content
โšก Calmops

WebAssembly (WASM): Production Deployment Patterns

Introduction

WebAssembly enables near-native performance in browsers and is revolutionizing edge computing. From interactive web apps to serverless functions, WASM is becoming ubiquitous.

Key Statistics:

  • WASM executes 1.5-2x slower than native code
  • 60% of major frameworks support WASM
  • Edge WASM functions execute 10x faster than container alternatives
  • WASM module size: 10-100x smaller than Docker images

WASM Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    WebAssembly Runtime                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚              WASM Binary (.wasm)                        โ”‚    โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚ Module  โ”‚  โ”‚ Memory โ”‚  โ”‚ Table  โ”‚  โ”‚ Global  โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ”‚ Code    โ”‚  โ”‚  Linearโ”‚  โ”‚Function  โ”‚   Varโ”‚   โ”‚    โ”‚    โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                              โ”‚                                    โ”‚
โ”‚                              โ–ผ                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚              WASM Runtime                                 โ”‚    โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”‚    โ”‚
โ”‚  โ”‚  โ”‚  Wasmer   โ”‚ โ”‚  Wasmtime โ”‚ โ”‚  Wasmedge โ”‚             โ”‚    โ”‚
โ”‚  โ”‚  โ”‚(General)  โ”‚ โ”‚(Server)   โ”‚ โ”‚ (Edge)    โ”‚             โ”‚    โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                              โ”‚                                    โ”‚
โ”‚                              โ–ผ                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚
โ”‚  โ”‚   Browser    โ”‚   โ”‚   Server     โ”‚   โ”‚    Edge     โ”‚        โ”‚
โ”‚  โ”‚   (JS/WASM)  โ”‚   โ”‚  (WASMtime)  โ”‚   โ”‚ (WASMedge)  โ”‚        โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚
โ”‚                                                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Rust WASM

Compilation

// lib.rs - WASM library
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct VectorProcessor {
    data: Vec<f64>,
}

#[wasm_bindgen]
impl VectorProcessor {
    #[wasm_bindgen(constructor)]
    pub fn new() -> VectorProcessor {
        VectorProcessor { data: Vec::new() }
    }
    
    #[wasm_bindgen]
    pub fn add_value(&mut self, value: f64) {
        self.data.push(value);
    }
    
    #[wasm_bindgen]
    pub fn sum(&self) -> f64 {
        self.data.iter().sum()
    }
    
    #[wasm_bindgen]
    pub fn mean(&self) -> f64 {
        if self.data.is_empty() {
            return 0.0;
        }
        self.data.iter().sum::<f64>() / self.data.len() as f64
    }
    
    #[wasm_bindgen]
    pub fn sort(&mut self) {
        self.data.sort_by(|a, b| a.partial_cmp(b).unwrap());
    }
    
    #[wasm_bindgen]
    pub fn get_sorted_ptr(&self) -> *const f64 {
        self.data.as_ptr()
    }
}
# Cargo.toml
[package]
name = "vector-processor"
version = "0.1.0"
edition = "2021"

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

[dependencies]
wasm-bindgen = "0.2"

[profile.release]
opt-level = "s"
lto = true
# Build WASM
cargo build --release --target wasm32-unknown-unknown
wasm-bindgen --out-dir ./pkg/ --target web ./target/wasm32-unknown-unknown/release/vector_processor.wasm

JavaScript Integration

// main.js - Use WASM in browser
import init, { VectorProcessor } from './pkg/vector_processor.js';

async function run() {
    await init();
    
    const processor = new VectorProcessor();
    
    // Add data
    for (let i = 0; i < 1000000; i++) {
        processor.add_value(Math.random() * 100);
    }
    
    console.log('Processing 1M values...');
    
    // Sort (happens in WASM)
    const sortStart = performance.now();
    processor.sort();
    console.log(`Sort time: ${performance.now() - sortStart}ms`);
    
    // Calculate mean
    const mean = processor.mean();
    console.log(`Mean: ${mean}`);
    
    // Get pointer to sorted data (zero-copy)
    const ptr = processor.get_sorted_ptr();
    const memory = new Float64Array(
        init.memory.buffer, 
        ptr, 
        1000000
    );
    
    console.log(`First 10 sorted values: ${memory.slice(0, 10)}`);
}

run();

Server-Side WASM

WASI Server

// server.rs - WASI server
use std::net::TcpListener;
use std::io::Read;

fn main() {
    let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
    
    println!("WASM Server listening on port 8080");
    
    for stream in listener.incoming() {
        let mut stream = stream.unwrap();
        let mut buffer = [0; 1024];
        
        stream.read(&mut buffer).unwrap();
        
        // Parse HTTP request
        let request = String::from_utf8_lossy(&buffer);
        
        if request.starts_with("GET /compute ") {
            // Execute WASM module
            let result = execute_computation();
            
            let response = format!(
                "HTTP/1.1 200 OK\r\n\
                 Content-Type: application/json\r\n\
                 Content-Length: {}\r\n\
                 \r\n\
                 {{\"result\": {}}}",
                result.to_string().len(),
                result
            );
            
            stream.write(response.as_bytes()).unwrap();
        }
    }
}

#[wasm_bindgen]
pub fn execute_computation() -> f64 {
    // Heavy computation
    let mut sum = 0.0;
    for i in 0..1000000 {
        sum += (i as f64).sin() * (i as f64).cos();
    }
    sum
}

Edge Deployment

// Cloudflare Workers with WASM
import wasm from './compute.wasm';

export default {
    async fetch(request, env, ctx) {
        const module = await WebAssembly.instantiate(wasm);
        const { compute } = module.instance.exports;
        
        const url = new URL(request.url);
        const input = parseFloat(url.searchParams.get('input') || '0');
        
        // Execute WASM function at edge
        const result = compute(input);
        
        return new Response(JSON.stringify({ result }), {
            headers: { 'Content-Type': 'application/json' }
        });
    }
}

Production Patterns

Sandboxing

// Secure WASM execution
use wasmer::{Store, Module, Instance, Memory};
use wasmer::imports;

fn secure_execution(wasm_bytes: &[u8], input: i32) -> Result<i32, String> {
    let store = Store::default();
    
    // Load module
    let module = Module::from_binary(&store, wasm_bytes)
        .map_err(|e| e.to_string())?;
    
    // ImportObject with limited permissions
    let import_object = imports! {
        "env" => {
            // Only allow specific functions
            "print" => Function::new_native(&store, |msg: i32| {
                println!("WASM: {}", msg);
            }),
        }
    };
    
    // Instantiate with limited imports
    let instance = Instance::new(&store, &module, &import_object)
        .map_err(|e| e.to_string())?;
    
    // Get function
    let compute = instance
        .exports
        .get_function("compute")
        .map_err(|e| e.to_string())?;
    
    // Execute with timeout
    let result = compute.call(&[input.into()])
        .map_err(|e| e.to_string())?;
    
    Ok(result[0].i32().unwrap())
}

Component Model

;; wit component definition
(package wasi:[email protected])

interface incoming-handler {
    use wasi:http/[email protected].{incoming-request, response-outparam}

    handle: func(request: incoming-request, response: response-outparam)
}

Performance Comparison

Operation Native WASM JavaScript
Sorting 1M ints 12ms 15ms 85ms
Image processing 45ms 52ms 180ms
Matrix multiplication 8ms 10ms 65ms
Cryptography 5ms 7ms 120ms

External Resources


Comments