Skip to main content

Reducers

Reducers are functions that modify database state in response to client requests or system events. They are the only way to mutate tables in SpacetimeDB - all database changes must go through reducers.

Defining Reducers

Reducers are defined in your module code and automatically exposed as callable functions to connected clients.

Use the #[spacetimedb::reducer] macro on a function:

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

#[reducer]
pub fn create_user(ctx: &ReducerContext, name: String, email: String) -> Result<(), String> {
    // Validate input
    if name.is_empty() {
        return Err("Name cannot be empty".to_string());
    }

    // Modify tables
    ctx.db.user().insert(User {
        id: 0, // auto-increment will assign
        name,
        email,
    });

    Ok(())
}

Reducers must take &ReducerContext as their first parameter. Additional parameters must be serializable types. Reducers can return (), Result<(), String>, or Result<(), E> where E: Display.

Transactional Execution

Every reducer runs inside a database transaction. This provides important guarantees:

  • Isolation: Reducers don't see changes from other concurrent reducers
  • Atomicity: Either all changes succeed or all are rolled back
  • Consistency: Failed reducers leave the database unchanged

If a reducer throws an exception or returns an error, all of its changes are automatically rolled back.

Accessing Tables

Reducers can query and modify tables through the ReducerContext:

  • Inserting rows
  • Updating rows by unique columns
  • Deleting rows
  • Querying with indexes
  • Iterating all rows
  • Counting rows

Reducer Isolation

Reducers run in an isolated environment and cannot interact with the outside world:

  • ❌ No network requests
  • ❌ No file system access
  • ❌ No system calls
  • ✅ Only database operations

If you need to interact with external systems, use Procedures instead. Procedures can make network calls and perform other side effects, but they have different execution semantics and limitations.

Next Steps

  • Learn about Tables to understand data storage
  • Explore Procedures for side effects beyond the database
  • Review Subscriptions for real-time client updates