About spacetimedb-reducers
spacetimedb-reducers is a skill for implementing SpacetimeDB reducers and transactional server logic. It covers table access, rollback behavior, lifecycle reducers, and language-specific patterns for TypeScript, C#, Rust, and C++.
Key features
- 01Reducer patterns for multiple languages
- 02Transactional mutation and rollback guidance
- 03Indexed table access patterns
- 04Lifecycle reducer references
- 05Error handling guidance
Use cases
- 01Implementing transactional table mutations
- 02Validating and updating rows in reducers
- 03Handling lifecycle events
- 04Keeping external I/O out of reducers
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ danmossa/ spacetimedb-skills --skill spacetimedb-reducersAfter installing, type/spacetimedb-reducersin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/functions-reducers-error-handling.mdfunctions-reducers-lifecycle.mdfunctions-reducers-reducer-context.mdfunctions-reducers.mdfunctions.mdDetails
From the project READMEUse this skill for reducer implementation and transactional server logic.
Core reducer patterns
Reducers are the transactional entrypoints for table mutation. A successful reducer commits all table changes; a thrown exception, returned error, or panic rolls all of them back.
TypeScript reducer shape:
export const create_user = spacetimedb.reducer(
{ name: t.string(), email: t.string() },
(ctx, { name, email }) => {
if (name === "") throw new Error("Name cannot be empty");
ctx.db.user.insert({ id: 0n, name, email });
},
);
Language-specific signatures:
- TypeScript:
spacetimedb.reducer(args, (ctx, args) => { ... }), orspacetimedb.reducer((ctx) => { ... })for no args. - C#:
[SpacetimeDB.Reducer] public static void Name(ReducerContext ctx, ...). - Rust:
#[spacetimedb::reducer] pub fn name(ctx: &ReducerContext, ...) -> Result<(), String>; importspacetimedb::Tablefor table methods. - Lifecycle reducers use
init,client_connected, andclient_disconnectedvariants in the language's syntax.
Table access
- Insert rows through the generated table handle; use the trigger value (
0,0n, etc.) for auto-increment fields. - Find one row through a primary key or unique index: TypeScript
ctx.db.user.id.find(id), C#ctx.Db.User.Id.Find(id), Rustctx.db.user().id().find(id). - Filter many rows through indexed columns. Avoid full
iter()scans on hot paths unless the table is known to be small. - Update by finding a row, modifying it, then calling the update method on the same primary-key index.
- Delete by primary key/unique value or indexed filters when possible.
- Use
ctx.senderin TypeScript/C# andctx.sender()in Rust/C++ for the caller identity on SpacetimeDB 2.0.
Transaction guidance
- Keep reducers short and deterministic; move external I/O to procedures.
- Nested reducer calls share the same transaction; they are not separate commits.
- Use sender-facing errors for expected validation failures when the language exposes them; reserve panics or unchecked exceptions for programmer errors.
- Scheduled reducers run from schedule-table rows and may have no client sender.
Reference map
| Need | Open |
|---|---|
| Reducer basics and table access | references/functions-reducers.md |
| Lifecycle reducers | references/functions-reducers-lifecycle.md |
| Reducer context | references/functions-reducers-reducer-context.md |
| Error handling | references/functions-reducers-error-handling.md |
| Function categories | references/functions.md |
Guidance
- Treat reducers as transactions: keep side effects and error behavior aligned with the reference semantics.
- Use
ctx.sender/ctx.sender()according to the project's SpacetimeDB version; load spacetimedb-upgrade for 1.0 to 2.0 migrations. - Route schema questions to spacetimedb-tables.
Comments
Markdown supported