SDK API Overview
The SpacetimeDB client SDKs provide a comprehensive API for interacting with your database. After generating client bindings and establishing a connection, you can query data, invoke server functions, and observe real-time changes.
This page describes the core concepts and patterns that apply across all client SDKs. For language-specific details and complete API documentation, see the reference pages for Rust, C#, TypeScript, or Unreal Engine.
Prerequisites
Before using the SDK API, you must:
- Generate client bindings using
spacetime generate - Create a connection to your database
Subscriptions
Subscriptions replicate a subset of the database to your client, maintaining a local cache that automatically updates as the server state changes. Clients should subscribe to the data they need, then query the local cache.
Typical flow:
- Create a subscription with the SDK builder API
- Wait for
onApplied/OnAppliedto know initial rows are present - Read from the local cache and register callbacks
- Unsubscribe when the data is no longer needed
For lifecycle guarantees and semantics, see Subscriptions and Subscription Semantics.
Example
- TypeScript
- C#
- Rust
- Unreal
import { tables } from './module_bindings';
const handle = conn
.subscriptionBuilder()
.onApplied(ctx => {
console.log(`Ready with ${ctx.db.user.count()} users`);
})
.onError((ctx, error) => {
console.error(`Subscription failed: ${error}`);
})
.subscribe([tables.user.where(r => r.online.eq(true))]);var handle = conn
.SubscriptionBuilder()
.OnApplied(ctx =>
{
Console.WriteLine($"Ready with {ctx.Db.User.Count} users");
})
.OnError((ctx, error) =>
{
Console.WriteLine($"Subscription failed: {error}");
})
.AddQuery(q => q.From.User())
.Subscribe();let handle = conn
.subscription_builder()
.on_applied(|ctx| {
println!("Ready with {} users", ctx.db().user().count());
})
.on_error(|_ctx, error| {
eprintln!("Subscription failed: {}", error);
})
.add_query(|q| q.from.user())
.subscribe();TArray<FString> Queries = { TEXT("SELECT * FROM user") };
USubscriptionHandle* Handle = Conn->SubscriptionBuilder()
->OnApplied(AppliedDelegate)
->OnError(ErrorDelegate)
->Subscribe(Queries);Querying the Local Cache
After a subscription is applied, reads are local and do not require network round-trips.
- TypeScript
- C#
- Rust
- Unreal
const userCount = conn.db.user.count();
const user = conn.db.user.name.find('Alice');var userCount = conn.Db.User.Count;
var user = conn.Db.User.Name.Find("Alice");let user_count = conn.db().user().count();
let user = conn.db().user().name().find("Alice");int32 UserCount = Conn->Db->User->Count();
FUserType User = Conn->Db->User->Name->Find(TEXT("Alice"));Reacting to Cache Changes
Use row callbacks to react when subscribed rows are inserted, updated, or deleted.
- TypeScript
- C#
- Rust
- Unreal
conn.db.user.onInsert((ctx, row) => {});
conn.db.user.onUpdate((ctx, oldRow, newRow) => {});
conn.db.user.onDelete((ctx, row) => {});conn.Db.User.OnInsert += (ctx, row) => {};
conn.Db.User.OnUpdate += (ctx, oldRow, newRow) => {};
conn.Db.User.OnDelete += (ctx, row) => {};conn.db().user().on_insert(|ctx, row| {});
conn.db().user().on_update(|ctx, old_row, new_row| {});
conn.db().user().on_delete(|ctx, row| {});Conn->Db->User->OnInsert.AddDynamic(this, &AMyActor::OnUserInsert);
Conn->Db->User->OnUpdate.AddDynamic(this, &AMyActor::OnUserUpdate);
Conn->Db->User->OnDelete.AddDynamic(this, &AMyActor::OnUserDelete);Canonical API References
- Subscriptions - Lifecycle, usage patterns, and semantics
- Subscription Semantics - Detailed consistency and ordering behavior
- TypeScript Reference -
SubscriptionBuilder,SubscriptionHandle, query builder API - C# Reference -
SubscriptionBuilder,SubscriptionHandle - C# Query Builder API - Typed subscription query builder
- Rust Reference -
SubscriptionBuilder,SubscriptionHandle - Rust Query Builder API - Typed subscription query builder
- Unreal Reference - Unreal subscription APIs