/concepts
Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions.
$ npx -y skills add clockworklabs/spacetimedb --skill concepts --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/concepts
Context preview
The summary Claude sees to decide when to auto-load this skill.
Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions.
SKILL.md
concepts.SKILL.mdname: concepts
description: Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions.
license: Apache-2.0
metadata:
author: clockworklabs
version: "2.0"
role: shared
language: all
cursor_globs: "**/*"
cursor_always_apply: true
SpacetimeDB Core Concepts
SpacetimeDB is a relational database that is also a server. It lets you upload application logic directly into the database as modules, eliminating the traditional web/game server layer entirely. Rust, C#, and C++ modules compile to WebAssembly, while TypeScript modules run on V8.
---
Critical Rules
1. **Reducers are transactional.** They do not return data to callers. Use subscriptions to read data. 2. **Reducers must be deterministic.** Do not use filesystem, network, external clocks, or external random sources in reducers. Use the reducer context (`ctx`) for SpacetimeDB-provided timestamp and deterministic random values. 3. **Read data via tables/subscriptions**, not reducer return values. Clients get data through subscribed queries. 4. **Auto-increment IDs are not sequential.** Gaps are normal, do not use for ordering. Use timestamps or explicit sequence columns. 5. **`ctx.sender` is the authenticated principal.** Never trust identity passed as arguments.
---
Feature Implementation Checklist
1. **Backend:** Define table(s) to store the data 2. **Backend:** Define reducer(s) to mutate the data 3. **Client:** Subscribe to the table(s) 4. **Client:** Call the reducer(s) from UI 5. **Client:** Render the data from the table(s)
---
Debugging Checklist
1. Is SpacetimeDB server running? (`spacetime start`) 2. Is the module published? (`spacetime publish`) 3. Are client bindings generated? (`spacetime generate`) 4. Check server logs for errors (`spacetime logs <db-name>`) 5. Is the reducer actually being called from the client?
---
Tables
- **Private tables** (default): Only accessible by reducers and the database owner.
- **Public tables**: Exposed for client read access through subscriptions. Writes still require reducers.
Organize data by access pattern, not by entity:
Player PlayerState PlayerStats
id <-- player_id player_id
name position_x total_kills
position_y total_deaths
velocity_x play_timeReducers
Reducers are transactional functions that modify database state. They run atomically, cannot interact with the outside world, and do not return data to callers. See the language-specific server skills for syntax.
Event Tables
Event tables broadcast reducer-specific data to clients. Rows are never stored in the client cache (`count()` returns 0, `iter()` yields nothing); only `onInsert` callbacks fire.
Subscriptions
Subscriptions replicate database rows to clients in real-time.
1. **Subscribe**: Register SQL queries describing needed data 2. **Receive initial data**: All matching rows are sent immediately 3. **Receive updates**: Real-time updates when subscribed rows change 4. **React to changes**: Use callbacks (`onInsert`, `onDelete`, `onUpdate`)
Best practices:
- Group subscriptions by lifetime
- Subscribe before unsubscribing when updating subscriptions
- Avoid overlapping queries
- Use indexes for efficient queries
Modules
Modules contain application logic that runs inside the database.
- **Tables**: Define the data schema
- **Reducers**: Define callable functions that modify state
- **Event Tables**: Broadcast reducer-specific data to clients
- **Views**: Read-only functions that expose computed subsets of data to clients
- **Procedures**: (Unstable) Functions that can have side effects (HTTP requests, `ctx.withTx`)
Server-side modules can be written in: Rust, C#, TypeScript, C++
Lifecycle: Write → Compile → Publish (`spacetime publish`) → Hot-swap (republish without disconnecting clients)
Identity
- **Identity**: A long-lived, globally unique identifier for a user.
- **ConnectionId**: Identifies a specific client connection.
- Always use `ctx.sender` / `ctx.Sender` / `ctx.sender()` for authorization.
SpacetimeDB works with many OIDC providers, including SpacetimeAuth (built-in), Auth0, Clerk, Keycloak, Google, and GitHub.
Read more
name: concepts description: Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions. license: Apache-2.0 metadata: author: clockworklabs version: "2.0" role: shared language: all cursor_globs: "**/*" cursor_always_apply: true
SpacetimeDB Core Concepts
SpacetimeDB is a relational database that is also a server. It lets you upload application logic directly into the database as modules, eliminating the traditional web/game server layer entirely. Rust, C#, and C++ modules compile to WebAssembly, while TypeScript modules run on V8.
---
Critical Rules
1. **Reducers are transactional.** They do not return data to callers. Use subscriptions to read data. 2. **Reducers must be deterministic.** Do not use filesystem, network, external clocks, or external random sources in reducers. Use the reducer context (`ctx`) for SpacetimeDB-provided timestamp and deterministic random values. 3. **Read data via tables/subscriptions**, not reducer return values. Clients get data through subscribed queries. 4. **Auto-increment IDs are not sequential.** Gaps are normal, do not use for ordering. Use timestamps or explicit sequence columns. 5. **`ctx.sender` is the authenticated principal.** Never trust identity passed as arguments.
---
Feature Implementation Checklist
1. **Backend:** Define table(s) to store the data 2. **Backend:** Define reducer(s) to mutate the data 3. **Client:** Subscribe to the table(s) 4. **Client:** Call the reducer(s) from UI 5. **Client:** Render the data from the table(s)
---
Debugging Checklist
1. Is SpacetimeDB server running? (`spacetime start`) 2. Is the module published? (`spacetime publish`) 3. Are client bindings generated? (`spacetime generate`) 4. Check server logs for errors (`spacetime logs <db-name>`) 5. Is the reducer actually being called from the client?
---
Tables
- **Private tables** (default): Only accessible by reducers and the database owner.
- **Public tables**: Exposed for client read access through subscriptions. Writes still require reducers.
Organize data by access pattern, not by entity:
Player PlayerState PlayerStats
id <-- player_id player_id
name position_x total_kills
position_y total_deaths
velocity_x play_timeReducers
Reducers are transactional functions that modify database state. They run atomically, cannot interact with the outside world, and do not return data to callers. See the language-specific server skills for syntax.
Event Tables
Event tables broadcast reducer-specific data to clients. Rows are never stored in the client cache (`count()` returns 0, `iter()` yields nothing); only `onInsert` callbacks fire.
Subscriptions
Subscriptions replicate database rows to clients in real-time.
1. **Subscribe**: Register SQL queries describing needed data 2. **Receive initial data**: All matching rows are sent immediately 3. **Receive updates**: Real-time updates when subscribed rows change 4. **React to changes**: Use callbacks (`onInsert`, `onDelete`, `onUpdate`)
Best practices:
- Group subscriptions by lifetime
- Subscribe before unsubscribing when updating subscriptions
- Avoid overlapping queries
- Use indexes for efficient queries
Modules
Modules contain application logic that runs inside the database.
- **Tables**: Define the data schema
- **Reducers**: Define callable functions that modify state
- **Event Tables**: Broadcast reducer-specific data to clients
- **Views**: Read-only functions that expose computed subsets of data to clients
- **Procedures**: (Unstable) Functions that can have side effects (HTTP requests, `ctx.withTx`)
Server-side modules can be written in: Rust, C#, TypeScript, C++
Lifecycle: Write → Compile → Publish (`spacetime publish`) → Hot-swap (republish without disconnecting clients)
Identity
- **Identity**: A long-lived, globally unique identifier for a user.
- **ConnectionId**: Identifies a specific client connection.
- Always use `ctx.sender` / `ctx.Sender` / `ctx.sender()` for authorization.
SpacetimeDB works with many OIDC providers, including SpacetimeAuth (built-in), Auth0, Clerk, Keycloak, Google, and GitHub.
Repo: clockworklabs/spacetimedb
Other skills on spacetimedb.
- /cli
SpacetimeDB CLI reference for initializing projects, building modules, publishing databases, querying data, and managing servers
Open skill - /cpp-server
SpacetimeDB C++ server module SDK reference. Use when writing tables, reducers, or module logic in C++.
Open skill - /csharp-client
SpacetimeDB C#/.NET client SDK reference. Use when building C# clients that connect to SpacetimeDB (console, desktop, or any .NET app).
Open skill - /csharp-server
SpacetimeDB C# server module SDK reference. Use when writing tables, reducers, or module logic in C#.
Open skill - /mcp
Operate a running SpacetimeDB database through MCP tools rather than the CLI - list databases, read schemas, run SQL, and call reducers. Use when the client exposes spacetimedb MCP tools and the task is to inspect or change data in a live database.
Open skill - /rust-server
SpacetimeDB Rust server module SDK reference. Use when writing tables, reducers, or module logic in Rust.
Open skill

