Ic-dbms 0.6 - What's New Since Launch

Hello everyone,

I’m the author of ic-dbms, an open-source Rust framework for building relational databases inside Internet Computer canisters. I released 0.1

Back in December with the core (CRUD, transactions, foreign keys, ACLs, stable memory) and have been shipping fast ever since. Here’s a recap

of the most important features that landed from 0.2 to 0.6.

Just a note: ic-dbms has been refactored and now it is part of a wider project called `wasm-dbms`, which provides an entire DBMS ecosystem for all WebAssembly runtimes, including the Internet Computer. Nothing really changes for IC users, since the library required and the API remain the same, but it opens up a lot of possibilities for cross-platform compatibility and new features in the future.

GitHub: https://github.com/veeso/wasm-dbms

Docs: https://wasm-dbms.cc

Keep Your Data Clean Without Writing a Line of Logic

> Since 0.2, 0.3

ic-dbms now validates and sanitizes fields automatically on every insert and update. Annotate your struct fields and the framework handles the

rest: 14 built-in validators (email, URL, string length, country codes, phone numbers, …) and 12 sanitizers (trim, lowercase, slug, clamp,

UTC normalization, …), plus the ability to write your own custom ones.

pub struct User {

#[primary_key]

pub id: Uint32,

#[sanitizer(TrimSanitizer, LowerCaseSanitizer)]

#[validate(EmailValidator)]

pub email: Text,

#[validate(RangeStrlenValidator(2, 64))]

pub name: Text,

}

No application-level checks needed — bad data gets rejected or cleaned before it ever touches stable memory.

Read more Sanitization Reference | wasm-dbms about the built-in sanitizers.

Read more Validation Reference | wasm-dbms about the built-in validators.

Query JSON Like Postgres

> Since 0.4

JSON columns now support PostgreSQL-inspired filter operators: structural containment (`@>-style`), value extraction at arbitrary paths, and key

existence checks. Paths use dot notation with bracket array indices - `metadata.tags[0].name` just works.

The JSON type has been added as well:

use wasm_dbms_api::prelude::*;

use std::str::FromStr;

#[derive(Debug, Table, Clone, PartialEq, Eq)]

#[table = “products”]

pub struct Product {

#[primary_key]

pub id: Uint32,

pub name: Text,

pub attributes: Json,  // {“color”: “red”, “size”: “M”, “tags”: [“sale”, “new”], “price”: 29.99}

}

fn example_queries(database: &impl Database) → Result<(), Box<dyn std::error::Error>> {

// Find all red products

let filter = Filter::json(“attributes”,

JsonFilter::extract_eq(“color”, Value::Text(“red”.into()))

);

let query = Query::builder().filter(filter).build();

let red_products = database.select::<Product>(query)?;

// Find red products with price > 20

let filter = Filter::json(“attributes”, JsonFilter::extract_eq(“color”, Value::Text(“red”.into())))

.and(Filter::json(“attributes”, JsonFilter::extract_gt(“price”, Value::Decimal(20.0.into()))));

let query = Query::builder().filter(filter).build();

let expensive_red = database.select::<Product>(query)?

Ok(())

}

Read more JSON Reference | wasm-dbms about JSON querying and the supported operators.

JOIN Across Tables on Stable Memory

> Since 0.5

Full INNER, LEFT, RIGHT, and FULL join support with qualified column resolution and NULL padding for outer joins. Combined with the existing

filter, ordering, and pagination, queries now feel like a real database.

let query = Query::default()

.join(Join::inner(“posts”, “users.id”, “posts.author_id”))

.order_by(“created_at”, Order::Desc)

.limit(10);

This release also replaced the N+1 pattern on foreign key eager loading with batch fetching. This has increased select performance with eager loading by up to **11.3x when selecting more than 1000 rows**.

Read more Join Engine | wasm-dbms about how joins work under the hood and the optimizations involved.

Define Your Own Column Types

> Since 0.6

`#[derive(CustomDataType)]` lets you create arbitrary column types beyond the built-in set.

#[derive(CustomDataType)]

pub struct Coordinate {

pub lat: f64,

pub lng: f64,

}

#[derive(Table, CandidType, Deserialize, Clone, PartialEq, Eq)]

#[table = “locations”]

pub struct Location {

#[primary_key]

pub id: Uint32,

#[custom_type]

pub position: Coordinate,

}

```

Read more Custom Data Types | wasm-dbms about how to implement your own custom types and the capabilities of the extension system.

Transactions That Don’t Depend on Trap-Revert

> Since 0.6

Transaction rollback is now powered by a write-ahead journal that tracks byte-level changes to stable memory. Rollback is a deterministic

replay of the journal. This makes ic-dbms no more relying on the canister trap mechanism.

Read more Atomicity | wasm-dbms about how the write-ahead journal works and the implications for transaction design.

Thanks for sharing what’s new in IC DBMS 0.6. I’m excited to see the improvements since launch. It would be great to know more about performance and real-world use cases. Has anyone tested the latest features yet? I appreciate everyone’s insights and feedback

Congrats — guess you may be backed by the DFINITY developer grant! So lucky.