Skip to main content

Overview

TrailBase includes a powerful WebAssembly (WASM) runtime built on Wasmtime that allows you to extend your backend with custom server-side logic. The runtime supports the WebAssembly Component Model, enabling you to write components in multiple languages including Rust, JavaScript, and TypeScript.

Key Features

Custom HTTP Endpoints

Create custom API endpoints with full request/response control

Scheduled Jobs

Run background tasks on a cron schedule

Database Access

Query and modify your SQLite database directly from WASM

Multi-Language

Write components in Rust, JavaScript, TypeScript, or any language that compiles to WASM

Architecture

The WASM runtime consists of two main parts:

Host Runtime

Located in crates/wasm-runtime-host/, the host runtime:
  • Compiles and loads WASM components using Wasmtime
  • Provides sandboxed execution environment with configurable permissions
  • Manages component lifecycle and hot-reloading
  • Exposes host capabilities through WASI interfaces
let runtime = Runtime::init(
    wasm_component_path,
    store_builder,
    RuntimeOptions {
        fs_root_path: Some(PathBuf::from("/sandbox")),
        use_winch: false,
        tokio_runtime: None,
    },
)?;

Guest Runtime

Located in crates/wasm-runtime-guest/, the guest runtime provides:
  • Type-safe API bindings for Rust, JavaScript, and TypeScript
  • HTTP request/response handling
  • Database query interface
  • Job scheduling primitives
  • Key-value store access
  • Outbound HTTP fetch capabilities

Capabilities

Database Access

Components can query and modify the SQLite database:
use trailbase_wasm::db::{query, execute, Value};

let rows = query(
    "SELECT * FROM users WHERE age > $1",
    [Value::Integer(18)]
).await?;

let affected = execute(
    "UPDATE users SET verified = 1 WHERE id = $1",
    [Value::Integer(user_id)]
).await?;

HTTP Fetch

Make outbound HTTP requests from your components:
use trailbase_wasm::fetch::{get, Request};

let data = get("https://api.example.com/data").await?;

Key-Value Store

Components have access to a shared key-value store:
use trailbase_wasm::kv;

kv::set("counter", vec![0, 0, 0, 42])?;
let value = kv::get("counter")?;

Security & Sandboxing

WASM components run in a secure sandbox with:
  • Memory isolation: Each component has its own linear memory
  • Filesystem restrictions: Optional read-only access to a specified directory
  • Network controls: No raw socket access, only HTTP through WASI interfaces
  • Resource limits: Configurable memory reservation (default 64MB)
pub struct RuntimeOptions {
    /// Optional file-system sandbox root for r/o file access
    pub fs_root_path: Option<PathBuf>,
    
    /// Whether to use the non-optimizing baseline compiler
    pub use_winch: bool,
    
    /// Which tokio runtime handle to execute on
    pub tokio_runtime: Option<tokio::runtime::Handle>,
}

Component Discovery

TrailBase automatically discovers and loads WASM components from the components/ directory in your data directory:
pub fn find_wasm_components(components_path: impl AsRef<Path>) -> Vec<PathBuf> {
    // Finds all .wasm files in the components directory
}

Use Cases

Custom Business Logic

Implement complex validation, calculations, or workflows

Third-Party Integrations

Connect to external APIs and services

Data Processing

Transform and aggregate data before storage or retrieval

Server-Side Rendering

Generate dynamic HTML responses

Performance

The runtime is optimized for production use:
  • Ahead-of-time compilation: Components are compiled once at startup
  • Caching: Compiled components are cached to disk
  • Parallel compilation: Utilizes all available CPU cores during compilation
  • Efficient instantiation: Fast component instantiation for request handling
log::info!("Compiling: {wasm_source_file:?}. May take some time...");

let component = wasmtime::CodeBuilder::new(&engine)
    .wasm_binary_or_text_file(&wasm_source_file)?
    .compile_component()?;

component.initialize_copy_on_write_image()?;

Next Steps

WASM Components

Learn how to create WASM components

Custom Endpoints

Build custom HTTP endpoints

Server-Side Rendering

Render dynamic HTML with WASM

Jobs Scheduler

Schedule background tasks

Build docs developers (and LLMs) love