Skip to content

Migrating From Native SDK Shape

The native module and the equivalent effect-spacetimedb contract — declare the shape, then implement handlers behind the typed group:

import { schema, table, t } from "spacetimedb/server"
const spacetime = schema({
user: table(
{ public: true },
{ id: t.string().primaryKey(), name: t.string() },
),
})
export const user_upsert = spacetime.reducer(
"user_upsert",
{ id: t.string(), name: t.string() },
(ctx, { id, name }) => {
ctx.db.user.insert({ id, name })
},
)
export default spacetime
Native concepteffect-spacetimedb concept
reducer function exportStdbFn.reducer(...) in a callable group
procedure function exportStdbFn.procedure(...) in a callable group
table builderStdb.table(...) bound to a variable
scheduled table callbackStdbFn.scheduledReducer(...) or scheduledProcedure(...)
HTTP handler exportStdbHttpGroup plus StdbBuilder.group(...)
  1. Move schemas and table declarations into leaf files.
  2. Declare groups without changing runtime behavior.
  3. Assemble a module and destructure the typed accessors.
  4. Port handlers one group at a time.
  5. Generate the client and replace ad hoc call sites with projected clients.

Keep the runtime constraints in mind: module handlers must remain synchronous, deterministic, and transactional. Network calls, timers, and secrets belong outside reducers and are passed in as arguments or handled by external services.