Use this skill for module schema and table performance.
Core table patterns
TypeScript tables use table(options, columns) and must be passed to schema() as an object:
import { schema, table, t } from "spacetimedb/server";
const player = table(
{ name: "player", public: true },
{
id: t.u64().primaryKey().autoInc(),
identity: t.identity().unique(),
name: t.string().index("btree"),
},
);
export default schema({ player });
Language-specific table declarations:
- TypeScript:
{ name: "player_score" } creates ctx.db.playerScore.
- C#:
[SpacetimeDB.Table(Accessor = "Player", Public = true)] creates ctx.Db.Player; the type must be partial.
- Rust:
#[spacetimedb::table(accessor = player, public)] creates ctx.db.player(); pub struct does not make a table public.
- C++:
SPACETIMEDB_TABLE(Type, player, Public) creates ctx.db[player].
Design rules
- Organize data by access/update pattern. Split hot, frequently updated state from rarely changed profile, settings, or stats fields.
- Public tables are visible to clients through subscriptions. Keep server-only state private and expose derived subsets through views when needed.
- Primary keys and unique constraints automatically create indexes; do not add duplicate indexes for them.
- Add indexes only for frequent equality, range, subscription, or join paths. Use B-tree by default; direct indexes are for dense unsigned integer keys and are not universally supported in every language.
- New columns in existing published tables need defaults and must be appended at the end. Check database migration rules before changing existing schemas.
- Auto-increment values are generated by the database and can have gaps after failed transactions.
- Use event tables for append-only client notifications; the event flag cannot be changed after publish.
- Schedule tables need a
ScheduleAt column and a linked scheduled reducer. In TypeScript, import ScheduleAt from spacetimedb, not spacetimedb/server.
Reference map
| Need |
Open |
| Table definitions and core patterns |
references/tables.md |
| Access control |
references/tables-access-permissions.md |
| IDs and defaults |
references/tables-auto-increment.md, references/tables-default-values.md |
| Types and constraints |
references/tables-column-types.md, references/tables-constraints.md |
| Index design |
references/tables-indexes.md |
| Event and schedule tables |
references/tables-event-tables.md, references/tables-schedule-tables.md |
| Storage and performance |
references/tables-file-storage.md, references/tables-performance.md |
Guidance
- Check migration implications in spacetimedb-databases before changing existing schemas.
- Favor indexed lookups for reducer paths that run often or touch large tables.
- Use event tables for append-only client notifications, especially when replacing reducer result callback patterns.
1---2name: spacetimedb-tables3description: Use when defining or changing SpacetimeDB tables, columns, constraints, primary keys, unique constraints, indexes, auto-increment fields, default values, event tables, schedule tables, access permissions, file storage, or table performance. Triggers on: table, column, primary key, unique, index, btree, direct index, event table, schedule table.4license: MIT5---67Use this skill for module schema and table performance.89## Core table patterns1011TypeScript tables use `table(options, columns)` and must be passed to `schema()` as an object:1213```typescript14import { schema, table, t } from "spacetimedb/server";1516const player = table(17 { name: "player", public: true },18 {19 id: t.u64().primaryKey().autoInc(),20 identity: t.identity().unique(),21 name: t.string().index("btree"),22 },23);2425export default schema({ player });26```2728Language-specific table declarations:2930- TypeScript: `{ name: "player_score" }` creates `ctx.db.playerScore`.31- C#: `[SpacetimeDB.Table(Accessor = "Player", Public = true)]` creates `ctx.Db.Player`; the type must be `partial`.32- Rust: `#[spacetimedb::table(accessor = player, public)]` creates `ctx.db.player()`; `pub struct` does not make a table public.33- C++: `SPACETIMEDB_TABLE(Type, player, Public)` creates `ctx.db[player]`.3435## Design rules3637- Organize data by access/update pattern. Split hot, frequently updated state from rarely changed profile, settings, or stats fields.38- Public tables are visible to clients through subscriptions. Keep server-only state private and expose derived subsets through views when needed.39- Primary keys and unique constraints automatically create indexes; do not add duplicate indexes for them.40- Add indexes only for frequent equality, range, subscription, or join paths. Use B-tree by default; direct indexes are for dense unsigned integer keys and are not universally supported in every language.41- New columns in existing published tables need defaults and must be appended at the end. Check database migration rules before changing existing schemas.42- Auto-increment values are generated by the database and can have gaps after failed transactions.43- Use event tables for append-only client notifications; the event flag cannot be changed after publish.44- Schedule tables need a `ScheduleAt` column and a linked scheduled reducer. In TypeScript, import `ScheduleAt` from `spacetimedb`, not `spacetimedb/server`.4546## Reference map4748| Need | Open |49| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |50| Table definitions and core patterns | [references/tables.md](references/tables.md) |51| Access control | [references/tables-access-permissions.md](references/tables-access-permissions.md) |52| IDs and defaults | [references/tables-auto-increment.md](references/tables-auto-increment.md), [references/tables-default-values.md](references/tables-default-values.md) |53| Types and constraints | [references/tables-column-types.md](references/tables-column-types.md), [references/tables-constraints.md](references/tables-constraints.md) |54| Index design | [references/tables-indexes.md](references/tables-indexes.md) |55| Event and schedule tables | [references/tables-event-tables.md](references/tables-event-tables.md), [references/tables-schedule-tables.md](references/tables-schedule-tables.md) |56| Storage and performance | [references/tables-file-storage.md](references/tables-file-storage.md), [references/tables-performance.md](references/tables-performance.md) |5758## Guidance5960- Check migration implications in [spacetimedb-databases](../spacetimedb-databases/SKILL.md) before changing existing schemas.61- Favor indexed lookups for reducer paths that run often or touch large tables.62- Use event tables for append-only client notifications, especially when replacing reducer result callback patterns.