一键导入
spacetimedb-concepts
Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
SpacetimeDB CLI reference for initializing projects, building modules, publishing databases, querying data, and managing servers
Build TypeScript clients for SpacetimeDB. Use when connecting to SpacetimeDB from web apps, Node.js, Deno, Bun, or other JavaScript runtimes.
基于 SOC 职业分类
| name | spacetimedb-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"} |
SpacetimeDB is a relational database that is also a server. It lets you upload application logic directly into the database via WebAssembly modules, eliminating the traditional web/game server layer entirely.
These five rules prevent the most common SpacetimeDB mistakes:
ctx.sender() is the authenticated principal — never trust identity passed as arguments. Always use ctx.sender() for authorization.When implementing a feature that spans backend and client:
Common mistake: Building backend tables/reducers but forgetting to wire up the client to call them.
When things are not working:
spacetime start)spacetime publish)spacetime generate)spacetime logs <db-name>)spacetime start
spacetime publish <db-name> --module-path <module-path>
spacetime publish <db-name> --clear-database -y --module-path <module-path>
spacetime generate --lang <lang> --out-dir <out> --module-path <module-path>
spacetime logs <db-name>
SpacetimeDB combines a database and application server into a single deployable unit. Clients connect directly to the database and execute application logic inside it. The system is optimized for real-time applications requiring maximum speed and minimum latency.
Key characteristics:
Tables store all data in SpacetimeDB. They use the relational model and support SQL queries for subscriptions.
Tables are defined using language-specific attributes. In 2.0, use accessor (not name) for the API name:
Rust:
#[spacetimedb::table(accessor = player, public)]
pub struct Player {
#[primary_key]
#[auto_inc]
id: u32,
#[index(btree)]
name: String,
#[unique]
email: String,
}
C#:
[SpacetimeDB.Table(Accessor = "Player", Public = true)]
public partial struct Player
{
[SpacetimeDB.PrimaryKey]
[SpacetimeDB.AutoInc]
public uint Id;
[SpacetimeDB.Index.BTree]
public string Name;
[SpacetimeDB.Unique]
public string Email;
}
TypeScript:
const players = table(
{ name: 'players', public: true },
{
id: t.u32().primaryKey().autoInc(),
name: t.string().index('btree'),
email: t.string().unique(),
}
);
Organize data by access pattern, not by entity:
Decomposed approach (recommended):
Player PlayerState PlayerStats
id <-- player_id player_id
name position_x total_kills
position_y total_deaths
velocity_x play_time
Benefits: reduced bandwidth, cache efficiency, schema evolution, semantic clarity.
Reducers are transactional functions that modify database state. They are the primary client-invoked mutation path; procedures can also mutate tables by running explicit transactions.
Rust:
#[spacetimedb::reducer]
pub fn create_user(ctx: &ReducerContext, name: String, email: String) -> Result<(), String> {
if name.is_empty() {
return Err("Name cannot be empty".to_string());
}
ctx.db.user().insert(User { id: 0, name, email });
Ok(())
}
C#:
[SpacetimeDB.Reducer]
public static void CreateUser(ReducerContext ctx, string name, string email)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("Name cannot be empty");
ctx.Db.User.Insert(new User { Id = 0, Name = name, Email = email });
}
Every reducer receives a ReducerContext providing:
ctx.db (Rust field, TS property) / ctx.Db (C# property)ctx.sender() (Rust method) / ctx.Sender (C# property) / ctx.sender (TS property)ctx.connection_id() (Rust method) / ctx.ConnectionId (C# property) / ctx.connectionId (TS property)ctx.timestamp (Rust field, TS property) / ctx.Timestamp (C# property)Event tables are the preferred way to broadcast reducer-specific data to clients.
#[table(accessor = damage_event, public, event)]
pub struct DamageEvent {
pub target: Identity,
pub amount: u32,
}
#[reducer]
fn deal_damage(ctx: &ReducerContext, target: Identity, amount: u32) {
ctx.db.damage_event().insert(DamageEvent { target, amount });
}
Clients subscribe to event tables and use on_insert callbacks. Event tables must be subscribed explicitly and are excluded from subscribe_to_all_tables().
Subscriptions replicate database rows to clients in real-time.
onInsert, onDelete, onUpdate)Modules are WebAssembly bundles containing application logic that runs inside the database.
Server-side modules can be written in: Rust, C#, TypeScript (beta)
spacetime publishIdentity is SpacetimeDB's authentication system based on OpenID Connect (OIDC).
#[spacetimedb::reducer]
pub fn do_something(ctx: &ReducerContext) {
let caller_identity = ctx.sender(); // Who is calling?
// NEVER trust identity passed as a reducer argument
}
SpacetimeDB works with many OIDC providers, including SpacetimeAuth (built-in), Auth0, Clerk, Keycloak, Google, and GitHub.
Choose SpacetimeDB when you need:
Authentication check in reducer:
#[spacetimedb::reducer]
fn admin_action(ctx: &ReducerContext) -> Result<(), String> {
let admin = ctx.db.admin().identity().find(&ctx.sender())
.ok_or("Not an admin")?;
Ok(())
}
Scheduled reducer:
#[spacetimedb::table(accessor = reminder, scheduled(send_reminder))]
pub struct Reminder {
#[primary_key]
#[auto_inc]
id: u64,
scheduled_at: ScheduleAt,
message: String,
}
#[spacetimedb::reducer]
fn send_reminder(ctx: &ReducerContext, reminder: Reminder) {
log::info!("Reminder: {}", reminder.message);
}
When modifying SpacetimeDB code: