wasm-dbms
What is wasm-dbms?
wasm-dbms is an embeddable relational database engine written in Rust, designed to run entirely inside WebAssembly runtimes. Unlike traditional databases that run as external services, wasm-dbms compiles into your WASM module and manages data directly in linear memory — no network calls, no external dependencies.
You define your schema as Rust structs with derive macros, and wasm-dbms provides full CRUD operations, ACID transactions, foreign key integrity, validation, and sanitization — all running within the sandbox of your WASM module.
wasm-dbms supports any WASM runtime (Wasmtime, Wasmer, WasmEdge). For the Internet Computer, see the ic-dbms project.
Why wasm-dbms?
A WASM module is a sandbox with a linear memory and little else. Most embedded databases expect a filesystem and a C toolchain, so using them from WASM means porting a native engine, depending on storage provided by one specific host, or building tables by hand on a key-value store. wasm-dbms is a relational engine designed for the sandbox instead:
- Runs wherever WASM runs: pure Rust, builds for
wasm32-unknown-unknown, no C toolchain, WASI or JavaScript glue required - Storage is a trait: the engine works on 64 KiB pages behind
MemoryProvider, so the same database runs on the heap, on a file, on Internet Computer stable memory, or on your own storage - The schema is Rust code: tables are structs, queries are typed, and mistakes are compile errors
- Relational, not key-value: foreign keys, joins, transactions, indexes and migrations are built in
- Ships inside your module: no connection, no network round trip, no service to operate
Read Why wasm-dbms? for the full reasoning and a comparison with SQLite on WASM, Turso, GlueSQL, DuckDB-Wasm, PGlite, key-value stores and host-provided storage.
Documentation
Guides
Step-by-step guides for building databases with wasm-dbms:
- Getting Started - Set up your first wasm-dbms database
- CRUD Operations - Insert, select, update, and delete records
- Querying - Filters, ordering, pagination, and field selection
- Transactions - ACID transactions with commit/rollback
- SQL - Query and modify data with SQL statements
- Relationships - Foreign keys, delete behaviors, and eager loading
- Custom Data Types - Define your own data types (enums, structs)
- Schema Migrations - Evolve your schema across releases without losing data
- Wasmtime Example - Using wasm-dbms with the WIT Component Model and Wasmtime
- Embedding wasm-dbms - Build an application layer: memory provider, context lifetime, transactions across calls, and ownership
Reference
API and type reference documentation:
- Data Types - All supported column types
- Schema Definition - Table attributes and generated types
- Migrations - Schema migration lifecycle, ops, and policy
- Validation - Built-in and custom validators
- Sanitization - Built-in and custom sanitizers
- JSON - JSON data type and filtering
- SQL - SQL syntax, statements, type conversion, and reserved words
- Errors - Error types and handling
Internet Computer
Internet Computer support lives in the dedicated ic-dbms project. Read its documentation at https://ic.wasm-dbms.cc.
WASI Integration
For deploying wasm-dbms on WASI runtimes (Wasmer, Wasmtime, WasmEdge):
- WASI Memory Provider - File-backed persistent storage for WASI
- WASI Key-Value Memory Provider - Draft2 host-bucket storage with explicit checkpoints
Technical Documentation
For advanced users and contributors:
- Architecture - Three-layer system overview
- Memory Management - Stable memory internals
- Join Engine - Cross-table join query internals
Quick Example
Define your schema:
#![allow(unused)]
fn main() {
use wasm_dbms_api::prelude::*;
#[derive(Debug, Table, Clone, PartialEq, Eq)]
#[table = "users"]
pub struct User {
#[primary_key]
pub id: Uint32,
#[sanitizer(TrimSanitizer)]
#[validate(MaxStrlenValidator(100))]
pub name: Text,
#[validate(EmailValidator)]
pub email: Text,
}
}
Use the Database trait for CRUD operations:
#![allow(unused)]
fn main() {
use wasm_dbms_api::prelude::*;
// Insert
let user = UserInsertRequest {
id: 1.into(),
name: "Alice".into(),
email: "alice@example.com".into(),
};
database.insert::<User>(user)?;
// Query
let query = Query::builder()
.filter(Filter::eq("name", Value::Text("Alice".into())))
.build();
let users = database.select::<User>(query)?;
}
Features
- Schema-driven: Define tables as Rust structs with derive macros
- Runtime-agnostic: Works on any WASM runtime, not tied to a specific platform
- CRUD operations: Full insert, select, update, delete support
- ACID transactions: Commit/rollback with isolation
- Foreign keys: Referential integrity with cascade/restrict behaviors
- Validation & Sanitization: Built-in validators and sanitizers
- JSON support: Store and query semi-structured data