SpacetimeDB Data Types Supported: A Complete Guide to SATS and Rust Type Mapping

SpacetimeDB supports all Rust primitives, standard collections like Vec<T> and Option<T>, and user-defined structs or enums by mapping them to the Spacetime Algebraic Type System (SATS) via the SpacetimeType trait.

SpacetimeDB stores Rust values in database tables by translating them into SATS (Spacetime Algebraic Type System) representations. Any Rust type that implements the SpacetimeType trait—whether primitive, generic, or custom—can be used as a table column or reducer argument. This article covers every data type supported by SpacetimeDB based on the implementation in clockworklabs/SpacetimeDB.

Primitive Scalar Types Supported

SpacetimeDB provides first-class support for all standard Rust scalar types, including fixed-width integers, floating-point numbers, and strings. These primitives are implemented in crates/sats/src/typespace.rs through the impl_primitives! macro, which maps each Rust type to its corresponding AlgebraicType variant.

The following primitive types are supported:

  • bool – Maps to AlgebraicType::Bool
  • Unsigned integersu8, u16, u32, u64, u128, and u256 (from the ethnum crate) map to U8 through U256
  • Signed integersi8, i16, i32, i64, i128, and i256 (from ethnum) map to I8 through I256
  • Floating-pointf32 and f64 map to F32 and F64
  • Strings – Both owned String and borrowed &str map to AlgebraicType::String

Each primitive implements the SpacetimeType trait directly, allowing immediate use in table schemas without additional boilerplate.

Compound Collection Types

Beyond scalars, SpacetimeDB supports generic collections and nested types through implementations in crates/sats/src/typespace.rs, specifically via the impl_st! macro and specialized trait blocks.

The supported compound types include:

  • Vec<T> – Represents variable-length arrays of any T that implements SpacetimeType, stored as Array<T> in SATS
  • Option<T> – Represents nullable fields, stored as the SATS Option<T> algebraic type
  • Result<T, E> – Supported through a custom impl<T,E> SpacetimeType for Result<T,E> block, allowing error types to be serialized

These generic implementations recursively resolve the type of their type parameters, enabling arbitrarily deep nesting such as Vec<Option<u64>> or Option<Vec<String>>.

Custom Structs and Enums via Derive Macros

User-defined types become valid SpacetimeDB columns through the #[derive(SpacetimeType)] macro. This procedural macro, defined in crates/bindings-macro/src/sats.rs, inspects your struct or enum definition and generates the corresponding SATS representation.

The macro distinguishes between two algebraic constructs:

  • Product types – Generated for struct definitions, mapping fields to named or unnamed product components
  • Sum types – Generated for enum definitions, mapping variants to sum alternatives with optional payloads

Each variant is represented through the SatsTypeData enum in the macro, distinguishing between Product (struct) and Sum (enum) representations.

SpacetimeDB-Specific Identifier Types

SpacetimeDB defines several domain-specific identifier types that carry special semantic meaning within the database. These are ordinary structs that derive SpacetimeType and are defined in the core library:

  • Identity – Represents a user's public key (defined in crates/lib/src/identity.rs)
  • ConnectionId – A unique session identifier for active connections
  • Timestamp – Logical transaction time for event ordering
  • TimeDuration – Represents elapsed time between events
  • Uuid – A 128-bit universally unique identifier
  • ScheduleAt – Scheduling metadata for timed reducers

These types can be used as primary keys, indexed columns, or reducer arguments just like standard primitives.

Practical Example: Defining Custom Data Types

The following Rust module demonstrates how to combine primitives, collections, and custom types in a SpacetimeDB application:

use spacetimedb::{SpacetimeType, Table, ReducerContext};

/// A point in 2-D space – primitive fields only.
#[derive(SpacetimeType, Clone, Debug)]
pub struct Point {
    x: u64,
    y: u64,
}

/// An enum that can be stored directly as an index key because it has no payload.
#[derive(SpacetimeType, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Direction {
    North,
    South,
    East,
    West,
}

/// A richer enum with payloads – each variant may carry its own data.
#[derive(SpacetimeType, Clone, Debug)]
pub enum Message {
    Ping,
    Pong,
    Move { to: Point },
    Turn { dir: Direction },
}

/// Table that stores a `Message`. The `#[table(..)]` macro automatically derives `SpacetimeType`.
#[spacetimedb::table]
pub struct MsgLog {
    #[primary_key] id: u64,
    payload: Message,
}

/// Simple reducer that inserts a new row.
#[spacetimedb::reducer]
pub fn log_message(ctx: &ReducerContext, msg: Message) {
    ctx.db.msg_log().insert(MsgLog { id: ctx.new_id(), payload: msg });
}

In this example, Point, Direction, and Message are all valid column types because the derive macro expands them to SATS product or sum definitions. The MsgLog table can be queried, indexed, or filtered like any other table.

Summary

  • Primitive coverage – SpacetimeDB supports all Rust scalars from bool to u256/i256, plus String and &str, implemented via impl_primitives! in crates/sats/src/typespace.rs
  • Generic containersVec<T>, Option<T>, and Result<T,E> work out of the box through the impl_st! macro and custom trait implementations
  • User-defined types – Structs and enums derive SpacetimeType to generate SATS product and sum types, processed by crates/bindings-macro/src/sats.rs
  • Specialized identifiersIdentity, Timestamp, Uuid, and related types provide domain-specific semantics for authentication and scheduling
  • Recursive composition – All types can be nested arbitrarily, allowing complex schemas like enums containing structs containing vectors of primitives

Frequently Asked Questions

What primitive data types does SpacetimeDB support?

SpacetimeDB supports the complete set of Rust primitives: bool, u8 through u256, i8 through i256, f32, f64, and both String and &str. The 256-bit integer types come from the ethnum crate. These are mapped to SATS algebraic types in crates/sats/src/typespace.rs using the impl_primitives! macro.

Can I use custom structs and enums as column types in SpacetimeDB?

Yes. Any struct or enum that derives SpacetimeType can be used as a table column or reducer argument. The derive macro, located in crates/bindings-macro/src/sats.rs, automatically generates the SATS representation as either a product type (for structs) or sum type (for enums).

How does SpacetimeDB handle optional or nullable fields?

Use the standard Rust Option<T> type. SpacetimeDB implements SpacetimeType for Option<T> in crates/sats/src/typespace.rs, mapping it to the SATS Option<T> algebraic type. This allows any column to represent nullability without requiring database-specific wrapper types.

What are SpacetimeDB identifier types and when should I use them?

Identifier types like Identity, ConnectionId, Timestamp, TimeDuration, Uuid, and ScheduleAt are domain-specific structs defined in the SpacetimeDB core library. Use Identity for public keys and user identification, ConnectionId for session tracking, and Timestamp or TimeDuration for temporal logic. These types derive SpacetimeType and can be used as primary keys or indexed columns.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →