Beyond Docker: Building Sub-Millisecond Microservices with WebAssembly (Wasm) on Bare Metal (Ubuntu 24.04)

Ditch container bloat and deploy ultra-dense, secure, and lightning-fast APIs using Fermyon Spin on Bare Metal infrastructure.

In 2019, Docker co-founder Solomon Hykes famously tweeted, "If WASM+WASI existed in 2008, we wouldn't have needed to create Docker." Ever since, the Docker vs WebAssembly performance comparison debate has been relentless. Many prematurely declared that "Wasm will kill Docker." However, after years of running both in production, the truth is clear: WebAssembly won’t kill Docker, but it will absolutely dominate the Serverless and API landscape.

To run a simple API today, we typically pack an entire mini-Linux OS into a Docker container. This inherently causes bloat. WebAssembly (Wasm), on the other hand, requires zero OS. Your code runs directly within a highly secure sandbox at the hardware level. In this webassembly on bare metal server tutorial, we will explore how to ditch container bloat and build lightning-fast APIs on your own Ubuntu server.

Wasm and Spin: The Engine and the Steering Wheel

WebAssembly is an ultra-fast, OS-agnostic binary format. Think of Wasm as a powerful "car engine." But you can't just hold an engine in your hands and drive; you need a steering wheel and pedals. That’s where Fermyon Spin comes in.

Much like docker run controls containers, Fermyon Spin acts as the ultimate server-side webassembly spin framework guide, allowing developers to effortlessly build, run, and scale Wasm microservices.

The 3 Core Advantages of Wasm on Bare Metal

Stop paying exorbitant bills for AWS Lambda and build your own serverless platform that is 100x faster on a Dedicated Bare Metal Server. Here is why this architecture is a game-changer:

  • Zero Cold Starts (Microsecond Speed): Starting a Docker container takes seconds. Running Wasm via Fermyon Spin takes mere microseconds. This creates a true zero cold start environment for microservices on Ubuntu infrastructure.
  • Extreme Server Density: While a 128-core bare metal server might comfortably run 1,000 Docker containers, that exact same server can host 10,000 to 50,000 Wasm microservices. When analyzing wasmtime vs docker memory usage, Docker consumes ~100MB per idle instance, whereas Wasm requires just ~2MB.
  • Ironclad Sandbox (Security): A vulnerability in a Docker container can lead to a kernel escape. Wasm is designed with a strict "Default Deny-All" capability-based security model, ensuring unparalleled isolation.

Hidden Gems in Production (What Competitors Miss)

Most tutorials assume Wasm only runs on cloud edge platforms like Cloudflare or Fastly. Here are the real production secrets for your own infrastructure:

  • The containerd-wasm-shim (Peaceful Coexistence): You don't have to rip out Docker to use Wasm. By implementing RuntimeClass: wasmtime-spin (or your specific shim name) in your Kubernetes cluster, Docker containers and Wasm modules can run side-by-side on the same node. Run your heavy PostgreSQL databases in Docker, and your lightning-fast API gateways in Wasm.
    (Note: Never use just wasmtime as the RuntimeClass, as it is merely the engine. You must specify the exact shim like wasmtime-spin to avoid CrashLoopBackOff errors).
  • IoT OTA Updates with Zero Downtime: Pushing a Docker image update to an IoT device requires ~100MB of bandwidth and causes downtime. A Wasm binary update requires just ~400KB and hot-swaps in 8 seconds with absolute zero downtime.

Critical Infrastructure & Security Warnings

When running Wasm on Bare Metal, you must strictly adhere to the following security protocols:

[CRITICAL SECURITY ALERT] Capability-Based Access

Wasm modules are sandboxed with zero ambient authority. If your API needs to access a database or filesystem, you must explicitly grant permissions (WASI Capabilities) in the spin.toml file via allowed_http_hosts or key_value_stores. Otherwise, the network request will be blocked.

[WARNING] Fuel Metering

If you are executing third-party or untrusted Wasm code on your server, malicious actors could write infinite loops to exhaust your CPU. You must implement Wasmtime’s store.set_fuel(10_000) fuel metering to strictly limit execution time per request.

[BEST PRACTICE] Structured Logging

Never leave Wasm stdout/stderr piping directly to the host console in production. Route your logs to a structured system like Journald or Grafana Loki to maintain visibility over high-density microservices.

Step-by-Step Guide: How to Install Fermyon Spin on Ubuntu 24.04

Let's dive into how to run wasm without docker and build serverless api with wasm and rust on a clean Ubuntu 24.04 server.

Step 1: Install Rust and the Wasm Target

Rust is the premier language for compiling WebAssembly microservices. Install Rust and add the standard WASI compilation target (Fermyon Spin will automatically handle the Component Model translation under the hood).

# Install Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://rustup.rs | sh
source $HOME/.cargo/env
# Add the WebAssembly (WASI) target layer
rustup target add wasm32-wasi

Step 2: Install the Fermyon Spin CLI

Fetch and install the Spin CLI directly onto your Ubuntu machine.

# Download and install Spin
curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
sudo mv ./spin /usr/local/bin/spin
# Verify the installation
spin --version

Step 3: Scaffold a New Serverless Wasm Project

To effectively deploy fermyon spin on dedicated server, use Spin's built-in templates to scaffold a new API project.

spin new http-rust my-wasm-api --accept-defaults
cd my-wasm-api

This generates a standard spin.toml (manifest file) and src/lib.rs (your Rust handler).

Step 4: Build and Execute the Wasm API

Compile your code into a .wasm binary and seamlessly run microservices with wasm on linux in a single command. While local testing defaults to 127.0.0.1, a true Bare Metal production deployment requires binding to all network interfaces (0.0.0.0).

# Compile and start the listener for local testing
spin build --up
# For Production Bare Metal: Expose the API to the public internet
spin build --up --listen 0.0.0.0:80

Your Bare Metal server is now running a sub-millisecond API exposed to the world at http://<your-server-ip>, executing with absolute zero container overhead!

Essential FAQs for Modern Architects

Will WebAssembly (Wasm) completely replace Docker in 2026?
No. Wasm and Docker are complementary. Docker remains the gold standard for heavy, stateful applications (like databases and legacy monoliths) that require full Linux OS features. Wasm is the ultimate choice for stateless microservices, edge computing, and API gateways where sub-millisecond cold starts and extreme density are non-negotiable.
How does Fermyon Spin differ from standard WebAssembly?
WebAssembly is merely a compiled binary format. Fermyon Spin is the application framework and runtime. Spin provides the necessary HTTP triggers, routing, and database connections (like Redis/Postgres) needed to turn a raw Wasm module into a production-ready microservice on your Bare Metal server.
Why is Wasm considered more secure than Docker Containers?
Docker containers share the host's Linux kernel, leaving them vulnerable to kernel escape exploits. Wasm operates on a cryptographic, capability-based sandbox. A Wasm module cannot access the filesystem, network, or system clock unless explicitly granted permission by the host runtime, making it exponentially safer for executing untrusted code.