# Getting Started with SpacetimeDB Development: Build Serverless Relational Databases with Rust, C#, or TypeScript

> Start SpacetimeDB development building serverless relational databases. Write Rust C# or TypeScript, compile to WebAssembly. Clients connect directly via SDKs for atomic transactions.

- Repository: [Clockwork Labs/SpacetimeDB](https://github.com/clockworklabs/SpacetimeDB)
- Tags: getting-started
- Published: 2026-03-09

---

**SpacetimeDB is a serverless relational database that merges persistent storage with application logic, allowing developers to write tables and reducers in Rust, C#, or TypeScript that compile to WebAssembly while clients connect directly via generated SDKs to execute atomic transactions.**

Getting started with SpacetimeDB development requires understanding its architecture as a unified database and application server. Instead of managing separate backend infrastructure, developers write **modules**—compiled WebAssembly bundles that define both schema and business logic—while the **Host** handles persistence, transaction enforcement, and real-time client synchronization. This guide explores the core components, CLI workflow, and code patterns from the `clockworklabs/SpacetimeDB` repository to help you build and deploy your first application.

## Understanding the SpacetimeDB Architecture

SpacetimeDB operates through three primary components that eliminate traditional backend boilerplate. According to [`docs/intro/key-architecture.md`](https://github.com/clockworklabs/SpacetimeDB/blob/main/docs/intro/key-architecture.md), the **Host** runs one or many databases, manages storage durability, and handles energy billing for cloud deployments. Each **Database** represents an instance of a **Module**—a compiled WebAssembly (or JavaScript bundle) that exports a small ABI defining tables, reducers, and views.

The **Module** serves as your application layer. When you write code in Rust, C#, or TypeScript, you define **Tables** using SQL-style relational schemas and **Reducers**—server-side functions that mutate state within atomic transactions. The module code lives in your project directory (typically [`spacetimedb/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/spacetimedb/src/lib.rs) for Rust projects) and compiles through the procedural macros defined in [`crates/bindings-macro/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/bindings-macro/src/lib.rs). The **VM** component, implemented in [`crates/vm/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/vm/src/lib.rs), executes these WebAssembly modules, resolves reducer calls, and enforces strict transaction semantics.

**Views** provide read-only derived queries that clients can subscribe to, while **Procedures** (currently in Beta) allow non-transactional work such as external HTTP calls. Client applications interact with these components through **SDKs** generated from your module's metadata, implemented in [`crates/bindings/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/bindings/src/lib.rs), which expose type-safe methods for calling reducers and querying tables.

## Installing the CLI and Bootstrapping Your Project

The `spacetime` CLI orchestrates the entire development workflow, from local testing to cloud deployment. The CLI implementation resides in [`crates/cli/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/cli/src/lib.rs), with the `dev` subcommand specifically located in [`crates/cli/src/tasks/dev.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/cli/src/tasks/dev.rs).

Install the CLI using the official installer:

```bash
curl -sSf https://install.spacetimedb.com | sh

```

Create your first project using a built-in template:

```bash
spacetime dev --template basic-rs my-app

```

This command performs several operations defined in the CLI source: it boots a local **Host**, initializes a new Rust project structure, compiles the starter module, publishes it to the local database, and generates client bindings. The generated project contains a [`spacetimedb/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/spacetimedb/src/lib.rs) file with sample tables and reducers, plus a `client/` directory with SDK bindings.

## Writing Your First Module: Tables and Reducers

A SpacetimeDB module declares tables using procedural macros and implements business logic through reducer functions. The following example from [`docs/quickstarts/rust.md`](https://github.com/clockworklabs/SpacetimeDB/blob/main/docs/quickstarts/rust.md) demonstrates the minimal structure:

```rust
use spacetimedb::{ReducerContext, Table};

#[spacetimedb::table(name = person, public)]
pub struct Person {
    name: String,
}

#[spacetimeib::reducer]
pub fn add(ctx: &ReducerContext, name: String) {
    ctx.db.person().insert(Person { name });
}

#[spacetimedb::reducer]
pub fn say_hello(ctx: &ReducerContext) {
    for person in ctx.db.person().iter() {
        log::info!("Hello, {}!", person.name);
    }
    log::info!("Hello, World!");
}

```

The `#[spacetimedb::table]` macro, processed by the macro crate at [`crates/bindings-macro/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/bindings-macro/src/lib.rs), registers the `Person` struct as a public table accessible to clients. The `#[spacetimedb::reducer]` attribute marks functions that execute within database transactions—every reducer call is atomic, ensuring data consistency.

For TypeScript developers, the equivalent module structure uses:

```typescript
import { table, t, reducer } from "spacetimedb/server";

export const players = table(
  { name: "players", public: true },
  {
    id: t.u64().primaryKey(),
    name: t.string(),
  }
);

reducer("set_name", { id: t.u64(), name: t.string() }, (ctx, { id, name }) => {
  const player = ctx.db.players.id.find(id);
  if (player) player.name = name;
});

```

## Interacting with Your Database

During development, the CLI provides multiple interfaces for testing your module. When running `spacetime dev`, the system watches for file changes and automatically recompiles and pushes updates to your local database.

Invoke reducers directly from the command line:

```bash

# Insert a row via the add reducer

spacetime call my-spacetime-app add Alice

# Query the table using SQL syntax

spacetime sql my-spacetime-app "SELECT * FROM person"

# → name

# → "Alice"

# Execute a reducer that produces logs

spacetime call my-spacetime-app say_hello
spacetime logs my-spacetime-app

# → INFO: Hello, Alice!

# → INFO: Hello, World!

```

For application integration, use the generated client SDKs. After running `spacetime dev`, the bindings appear in `my-app/client/src/module_bindings/`. The following Rust client example connects to the local development server and invokes reducers:

```rust
use my_spacetime_app::module_bindings::SpacetimeDbClient;

#[tokio::main]
async fn main() {
    // Connect to localhost dev server
    let mut client = SpacetimeDbClient::connect().await.unwrap();

    // Call the add reducer with type safety
    client.reducers.add("Bob".into()).await.unwrap();

    // Query the person table directly
    let rows = client.tables.person().await.unwrap();
    println!("People in DB: {:?}", rows);
}

```

The client SDK abstracts the WebSocket communication handled by [`crates/client-api/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/client-api/src/lib.rs), providing native method calls that map directly to your module's reducers and tables.

## Deploying to Production

When your module is ready for production, the CLI handles deployment to SpacetimeDB's cloud infrastructure. The publish command compiles your module in release mode and uploads it to a managed **Host**:

```bash
spacetime publish

```

Cloud-hosted databases scale automatically using SpacetimeDB's energy-based billing model, where the **Host** manages storage persistence and client connection streaming without requiring server configuration. The same module binary runs both locally during development and in production, ensuring consistent behavior across environments.

## Summary

- **SpacetimeDB** eliminates the traditional backend layer by merging database persistence with application logic in WebAssembly modules.
- **Modules** are written in Rust, C#, or TypeScript and define **Tables** (schema) and **Reducers** (transactional business logic) using procedural macros from [`crates/bindings-macro/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/bindings-macro/src/lib.rs).
- The **`spacetime`** CLI provides a complete development workflow: project generation (`spacetime dev`), local testing (`spacetime call`, `spacetime sql`), and cloud deployment (`spacetime publish`).
- **Client SDKs** generated in [`crates/bindings/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/bindings/src/lib.rs) provide type-safe connections to the database, allowing direct reducer invocation and table subscription without REST API boilerplate.
- The **VM** ([`crates/vm/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/vm/src/lib.rs)) enforces atomic transaction semantics for all reducer calls, ensuring data consistency across concurrent client connections.

## Frequently Asked Questions

### What programming languages does SpacetimeDB support for module development?

SpacetimeDB officially supports **Rust**, **C#**, and **TypeScript** for writing modules. The source code includes quick-start guides for each language in `docs/quickstarts/`, with Rust being the most mature implementation. Regardless of the language you choose, the module compiles to WebAssembly (or a JavaScript bundle) and exports the same ABI, allowing interoperability with client SDKs generated for Rust, C#, TypeScript, C++, and Unity.

### What is the difference between a Reducer and a Procedure in SpacetimeDB?

A **Reducer** is an atomic, transactional server-side function that mutates database state—every reducer call operates as a single ACID transaction, and the VM in [`crates/vm/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/vm/src/lib.rs) ensures that either all changes apply or none do. A **Procedure** (currently in Beta) performs non-transactional work such as external HTTP calls or side effects that should not roll back if the transaction fails. Use reducers for data mutations and procedures for external integrations.

### How do client SDKs connect to a SpacetimeDB database?

Client SDKs generated by the CLI provide native bindings that communicate via WebSocket connections managed by [`crates/client-api/src/lib.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/client-api/src/lib.rs). When you run `spacetime dev`, the CLI generates type-safe methods in `client/src/module_bindings/` that map directly to your module's reducers and tables. Clients invoke reducers using `ctx.reducers.name(args)` and subscribe to table updates through the streaming protocol, receiving real-time delta updates without polling.

### Can I run SpacetimeDB locally without a cloud account?

Yes. The **`spacetime dev`** command spins up a local **Host** on your machine, implemented in the CLI tasks at [`crates/cli/src/tasks/dev.rs`](https://github.com/clockworklabs/SpacetimeDB/blob/main/crates/cli/src/tasks/dev.rs). This local host provides the full database functionality—including persistence, transaction management, and client SDK generation—without requiring internet connectivity or cloud credentials. Use this environment for development and testing before deploying with `spacetime publish`.