Skip to content

Architecture

mik-sdk uses a two-component architecture for WASI HTTP portability. This guide explains how the components work together.

Your handler contains:

ModuleImplementationPurpose
Business LogicYour codeRequest handling, validation, business rules
JSONPure RustParsing and building JSON (no WASI calls)
Timewasi:clocks/wall-clockUTC timestamps, ISO 8601
Randomwasi:random/randomUUIDs, tokens, secure random
HTTP Clientwasi:http/outgoing-handlerOutbound requests (optional)

The handler exports the mik:core/handler interface.

The bridge handles WASI HTTP translation:

  • Imports mik:core/handler (your handler)
  • Exports wasi:http/incoming-handler (standard WASI HTTP)
  • Converts between WASI HTTP types and mik types
  • Enforces body size limits (configurable via MIK_MAX_BODY_SIZE)

The two components are composed using WAC:

Terminal window
wac plug mik-bridge.wasm --plug handler.wasm -o service.wasm

The resulting component:

  • Exports wasi:http/incoming-handler
  • Can run on any WASI HTTP runtime
  • Size: ~230KB (release build)

The handler interface is defined in WIT:

package mik:core@0.1.0;
interface handler {
enum method { get, post, put, patch, delete, head, options }
record request-data {
method: method,
path: string,
headers: list<tuple<string, string>>,
body: option<list<u8>>,
}
record response {
status: u16,
headers: list<tuple<string, string>>,
body: option<list<u8>>,
}
handle: func(req: request-data) -> response;
}
world handler-world {
import wasi:clocks/wall-clock@0.2.0;
import wasi:random/random@0.2.0;
import wasi:cli/environment@0.2.0;
import wasi:cli/stderr@0.2.0;
export handler;
}
Terminal window
# Build your handler
cargo component build --release
# Compose with bridge
wac plug mik-bridge.wasm \
--plug target/wasm32-wasip2/release/my_handler.wasm \
-o service.wasm
# Run
wasmtime serve -S cli=y service.wasm
ComponentDebugRelease
Handler (basic)~500KB~158KB
Handler (with http-client)~700KB~236KB
Bridge~100KB~72KB
Composed (basic)~600KB~230KB
Composed (http-client)~800KB~308KB
  1. Use release builds: cargo component build --release

  2. Enable LTO:

    [profile.release]
    lto = true
  3. Disable unused features:

    mik-sdk = { version = "0.1", default-features = false }

The handler component imports these WASI interfaces:

InterfacePurposeUsed By
wasi:clocks/wall-clockCurrent timetime::now(), time::now_iso()
wasi:random/randomSecure randomrandom::uuid(), random::bytes()
wasi:cli/environmentEnvironment varsenv::get(), env::require()
wasi:cli/stderrLogging outputlog::info!(), log!()
wasi:http/outgoing-handlerHTTP clientfetch!().send() (optional)

These modules require no WASI calls:

ModuleDescription
jsonJSON parsing and building
requestRequest wrapper and parsing
typedDerive macro implementations
querySQL query builder

This design means JSON operations are fast and don’t cross the component boundary.

The composed component runs on any WASI HTTP runtime:

RuntimeCommand
wasmtimewasmtime serve -S cli=y service.wasm

The WASM sandbox provides:

  • Memory isolation: No access to host memory
  • Capability-based security: Only granted WASI interfaces
  • No filesystem access: By default (unless granted)
  • Controlled networking: Only via wasi:http