The SpacetimeDB C++ Module Library provides a modern C++20 API for building SpacetimeDB modules that run inside the database as WebAssembly.
This library provides a production-ready C++ bindings for SpacetimeDB with complete type system support:
- Module compilation and publishing to SpacetimeDB
- All lifecycle reducers (init, client_connected, client_disconnected)
- User-defined reducers with unlimited parameters
- Table registration with constraints (PrimaryKey, Unique, AutoInc)
- Insert, update and delete operations
- All primitive types (u8-u256, i8-i256, bool, f32, f64, string)
- All special types (Identity, ConnectionId, Timestamp, TimeDuration, Uuid, Result<>)
- Vector types for all primitives and special types
- Optional types (std::optional)
- Custom struct serialization via BSATN
- Complex enum support with proper variant names
- Enhanced logging system with file/line info
- Hybrid Compile-Time/Runtime System: C++20 concepts for compile-time validation with preinit runtime registration
- V9 Type Registration System: Unified type registration with comprehensive error detection and circular reference prevention
- Nominal Type System: Types identified by their declared names with explicit registration via SPACETIMEDB_STRUCT macros
- Multi-Layer Validation: Static assertions, runtime constraint checking, and error module replacement strategy
See ARCHITECTURE.md for detailed technical documentation.
- Btree indexes: Full support with
FIELD_Indexmacros and optimized queries - Range queries: Complete range query system with
range_from(),range_to(),range_inclusive(), etc. - Client visibility filters: Row-level security with
SPACETIMEDB_CLIENT_VISIBILITY_FILTERmacro - Scheduled reducers:
SPACETIMEDB_SCHEDULEmacro for time-based execution - Procedures: Pure functions with return values using
SPACETIMEDB_PROCEDUREmacro - Views: Read-only query functions with
SPACETIMEDB_VIEWmacro - Field accessor patterns: Efficient indexed operations with
ctx.db[table_field]
See the working examples in modules/*-cpp/src/lib.cpp for comprehensive feature usage.
- Modern C++20 API: Uses concepts, structured bindings, and other C++20 features
- BSATN Serialization: Binary Serialization And Type Notation for efficient data transfer
- Automatic Field Registration: Tables register their fields using SPACETIMEDB_STRUCT macro
- Unified Reducer System: Single macro for all reducer types with automatic lifecycle detection
- Type-Safe Database Access: Template-based table accessors with compile-time type checking
- Memory Safety: WASI shims for safe memory operations in WebAssembly environment
- Enhanced Logging: Multiple log levels with file/line information
- Namespace Support: Clean namespace qualification for enums with just 2 lines of code
- Emscripten SDK (emsdk)
- CMake 3.16+
- C++20 compatible compiler
# Create a new C++ project
spacetime init --lang cpp my-project
cd my-project
# Build and publish
spacetime build -p ./spacetimedb
spacetime publish -p ./spacetimedb my-databaseFor existing projects, add the following to your C++ module:
#include <spacetimedb.h>
using namespace SpacetimeDB;
// Define a table structure
struct User {
Identity identity;
std::string name;
std::string email;
};
// Register BSATN serialization
SPACETIMEDB_STRUCT(User, identity, name, email)
// Register as a table
SPACETIMEDB_TABLE(User, users, Public)
// Add constraints using FIELD_ macros
FIELD_PrimaryKey(users, identity);
FIELD_Unique(users, email);
// Define an enum with namespace qualification
SPACETIMEDB_ENUM(UserRole, Admin, Moderator, Member)
SPACETIMEDB_NAMESPACE(UserRole, "Auth") // Will be "Auth.UserRole" in client code
// User-defined reducer
SPACETIMEDB_REDUCER(add_user, ReducerContext ctx, std::string name, std::string email) {
User user{ctx.sender, name, email}; // id will be auto-generated
ctx.db[users].insert(user);
LOG_INFO("Added user: " + name);
return Ok();
}
// Delete user by id (using primary key)
SPACETIMEDB_REDUCER(delete_user, ReducerContext ctx) {
ctx.db[users_identity].delete_by_key(ctx.sender);
return Ok();
}
// Lifecycle reducers (optional)
SPACETIMEDB_INIT(init, ReducerContext ctx) {
LOG_INFO("Module initialized");
return Ok();
}
SPACETIMEDB_CLIENT_CONNECTED(on_connect, ReducerContext ctx) {
LOG_INFO("Client connected: " + ctx.sender.to_hex_string());
return Ok();
}
SPACETIMEDB_CLIENT_DISCONNECTED(on_disconnect, ReducerContext ctx) {
LOG_INFO("Client disconnected: " + ctx.sender.to_hex_string());
return Ok();
}
// Define a view for querying data (finds the calling user)
SPACETIMEDB_VIEW(std::optional<User>, find_my_user, Public, ViewContext ctx) {
// Use indexed field to find user by their identity
return ctx.db[users_identity].find(ctx.sender);
}
// Define a procedure (pure function with return value)
SPACETIMEDB_PROCEDURE(uint32_t, add_numbers, ProcedureContext ctx, uint32_t a, uint32_t b) {
return a + b;
}# Navigate to your module directory
cd modules/your-module
# Build the project
spacetime build -p ./spacetimedb
# Publish to SpacetimeDB
spacetime publish --bin-path ./spacetimedb/build/lib.wasm your-database-name
# Or use the directory (auto-detects build/lib.wasm)
spacetime publish ./spacetimedb your-database-nameTo build a different source file:
# Build a specific test module
emcmake cmake -B build -DMODULE_SOURCE=src/test_module.cpp -DOUTPUT_NAME=test_module .
cmake --build build
# This creates build/test_module.wasmSPACETIMEDB_TABLE(Type, table_name, Public/Private)- Register a tableSPACETIMEDB_STRUCT(Type, field1, field2, ...)- Register type for BSATN serialization
SPACETIMEDB_ENUM(EnumName, Value1, Value2, ...)- Define a simple enumSPACETIMEDB_ENUM(EnumName, (Variant1, Type1), (Variant2, Type2), ...)- Define an enum with payloadsSPACETIMEDB_NAMESPACE(EnumName, "Namespace")- Add namespace qualification to an enum
SPACETIMEDB_REDUCER(name, ReducerContext ctx, ...)- User-defined reducer- Returns
ReducerResult(alias forOutcome<void>) - Use
return Ok();for success orreturn Err("message");for errors - Failed reducers (Err) trigger transaction rollback
- Returns
SPACETIMEDB_INIT(name, ReducerContext ctx)- Module initialization reducer (optional)SPACETIMEDB_CLIENT_CONNECTED(name, ReducerContext ctx)- Client connection reducer (optional)SPACETIMEDB_CLIENT_DISCONNECTED(name, ReducerContext ctx)- Client disconnection reducer (optional)
SPACETIMEDB_VIEW(return_type, name, Public/Private, ViewContext ctx)- Read-only query functionSPACETIMEDB_VIEW(return_type, name, Public/Private, AnonymousViewContext ctx)- Anonymous view (no sender identity)- Note: Views currently only support the context parameter (no additional parameters yet)
SPACETIMEDB_PROCEDURE(return_type, name, ProcedureContext ctx, ...)- Pure function that returns a value- Returns the type directly (not wrapped in Outcome)
- Can return any SpacetimeType (primitives, structs, enums, Unit, etc.)
- Database access requires explicit transactions (use
ctx.WithTx()orctx.TryWithTx()) - Always public (no access control)
FIELD_PrimaryKey(table_name, field)- Primary key constraintFIELD_PrimaryKeyAutoInc(table_name, field)- Auto-incrementing primary keyFIELD_Unique(table_name, field)- Unique constraintFIELD_UniqueAutoInc(table_name, field)- Auto-incrementing unique fieldFIELD_Index(table_name, field)- Index for faster queriesFIELD_IndexAutoInc(table_name, field)- Auto-incrementing indexed fieldFIELD_AutoInc(table_name, field)- Auto-increment without other constraints
LOG_DEBUG("Debug message");
LOG_INFO("Info message");
LOG_WARN("Warning message");
LOG_ERROR("Error message");
LOG_PANIC("Fatal error message");
// With timing
{
LogStopwatch timer("Operation name");
// ... code to time ...
} // Automatically logs durationThe library uses a sophisticated hybrid compile-time/runtime architecture:
- Compile-Time Validation (
table_with_constraints.h): C++20 concepts and static assertions for constraint validation - V9 Type Registration System (
internal/v9_type_registration.h): Unified type registration with error detection and circular reference prevention - Priority-Ordered Initialization (
internal/Module.cpp): preinit functions with numbered priorities ensure correct registration order - Error Detection System (
internal/Module.cpp): Multi-layer validation with error module replacement for clear diagnostics - BSATN Serialization (
bsatn/): Binary serialization system with algebraic type support for all data types - Database Interface (
database.h,table_with_constraints.h): Type-safe table access with optimized field accessors - Reducer System (
reducer_macros.h): Unified macro system for all reducer types with parameter type capture - Logging (
logger.h): Comprehensive logging with source location tracking
For detailed technical documentation, see ARCHITECTURE.md.
Note on Architecture Documentation: ARCHITECTURE.md contains references to some legacy implementation details. The current implementation is streamlined and production-ready.
-
Type System
- Very large type combinations may exceed WASM memory limits
- Complex recursive type references require careful ordering
-
Database Operations
- Index-based operations use field accessors:
ctx.db[table_field].delete_by_key(value) - Table constraints are declared and enforced by server
- Supports insert, delete, and update operations through field accessors
- Index-based operations use field accessors:
-
Advanced Features
- Btree indexes:
FIELD_Indexcreates btree indexes for efficient range queries - Range queries: Full support for
range_from(),range_to(),range_inclusive(), etc. - Client visibility filters: Row-level security via
SPACETIMEDB_CLIENT_VISIBILITY_FILTER - Limited migrations: Only adding tables supported automatically
- SQL execution: Available via CLI (
spacetime sql) but not within modules
- Btree indexes:
See the modules/*-cpp/src/ directory for example modules:
lib.cpp- Comprehensive working module with all primitive types, tables, and reducers- Full equivalence with Rust and C# SDK test modules
- Examples of all constraint types and database operations
This library is part of the SpacetimeDB project. Please see the main repository for contribution guidelines.