Skip to content

Releases: clockworklabs/SpacetimeDB

Release v2.4.0

03 Jun 18:11
b354744

Choose a tag to compare

2.4.0 brings a headline new capability for Rust modules HTTP handlers alongside meaningful improvements to runtime performance, durability correctness, and server-side observability. The changelog is focused but every entry is production-relevant.

Features

HTTP handlers in Rust modules

This is currently an unstable feature and will need to be enabled to have be available.

  • Rust users can enable unstable features in their Cargo.toml:
[dependencies]
spacetimedb = { version = "1.*", features = ["unstable"] }
  • C# users can enable unstable features by adding #pragma warning disable STDB_UNSTABLE at the top of your file.
  • C++ users can enable unstable features by adding #define SPACETIMEDB_UNSTABLE_FEATURES before including the SpacetimeDB header.

Rust modules can now define custom HTTP routes and serve arbitrary HTTP requests directly from module code (#4636). Annotate a function with #[spacetimedb::http::handler] to create a handler, then wire it into your module's routing table with #[spacetimedb::http::router].

#[spacetimedb::http::handler]
fn insert(ctx: &mut HandlerContext, request: Request) -> Response {
    let body: Vec<u8> = request.into_body().into_bytes().into();
    let id = ctx.with_tx(|tx| tx.db.data().insert(Data { id: 0, body }).id);
    Response::new(Body::from_bytes(format!("{id}")))
}

#[spacetimedb::http::router]
fn router() -> Router {
    Router::new().post("/insert", insert).get("/retrieve", retrieve)
}

All user-defined routes are exposed under /v1/database/:name_or_identity/route/{*path}. Handlers have access to a HandlerContext that can open a database transaction, giving you full read/write access to your tables.

This opens the door to webhook integrations, REST-style APIs for non-realtime clients, and any other HTTP-driven interaction you want to build on top of your SpacetimeDB module.

Faster WASM reducer execution

Reducers now run on a dedicated synchronous WASM runtime backed by a single OS thread, instead of sharing the async runtime that procedures use (#5095). Because reducers never yield, the old async scaffolding was pure overhead. The synchronous path removes that cost from the hot path for every reducer invocation.

Bug Fixes

  • Durability: silent data loss on resume fixed. The commitlog could silently corrupt a segment on restart if trailing bytes shorter than a commit header were left behind. A subsequent append would render the segment corrupt, and anything written after those trailing bytes would become unreachable after the next restart. The segment is now truncated to its validated size before writes resume (#5116).
  • V8 heap metrics now cover procedure workers. Previously V8HeapMetrics were tracked only for reducer workers, leaving memory usage by JavaScript procedure workers invisible. Procedure worker heap usage is now aggregated and reported alongside the reducer worker metrics (#5122).
  • Commitlog decode errors include context. Errors encountered while decoding commits now carry additional context, making it substantially easier to diagnose corrupted or truncated log segments in production (#5129).
  • Reverted energy/execution-time conversion in V8 host. A regression introduced in v2.3.0 in how execution time was converted to energy units for JavaScript modules was reverted (#4927).

Release v2.3.0

27 May 19:32

Choose a tag to compare

This release brings first-party Godot support and major WebSocket performance improvements. We've also landed significant pipeline optimizations, commitlog enhancements, and expanded our framework coverage.

Features

First-party Godot SDK and Blackholio Tutorial

SpacetimeDB now officially supports Godot with a complete C# SDK integration. The new Blackholio tutorial walks through building a multiplayer asteroids-style game, demonstrating best practices for entity replication, player input handling, and game state management in Godot (#4920).

Faster WebSocket Transport with Batched Responses

The WebSocket layer now pipelines and batches responses using the v3 protocol, significantly reducing per-message overhead under high load. Combined with pipelined JavaScript module operations (#4962), WASM module operations (#4973), and a fully pipelined WebSocket send path (#5051), this delivers substantially improved throughput for real-time applications.

HTTP/2 Backend Support

The SpacetimeDB server now supports HTTP/2, enabling more efficient client connections with multiplexed streams and header compression (#5027).

Vue useProcedure Hook

Following the React pattern, Vue developers now have a first-class useProcedure composable for calling SpacetimeDB procedures with full TypeScript support (#4999).

Unity 6 WebGL Compatibility

C# modules and clients now support Unity 6's WebGL runtime, automatically selecting between getWasmTableEntry and dynCall as appropriate for the Unity version (#4961).

Commitlog Performance and Operations

The durability layer gained several improvements:

  • Configurable commitlog compression knobs for operational tuning (#5074)
  • Compression deferred when under write load to prioritize throughput (#4974)
  • Non-blocking compression that doesn't hold locks (#4981)
  • Proper handling of empty tail segments on resumption (#4863)

Rust DbContext Generics

Rust modules can now be generic over DbContext, enabling code reuse between client and server contexts while maintaining type safety (#4707).

API Changes

  • Deprecated: ReducerContext::identity is deprecated in favor of database_identity to clarify that this represents the module's identity, not the caller's (#4843)

Bug Fixes

  • Fixed a segfault in the V8 JavaScript runtime that could crash the server (#4986)
  • Fixed connection lifecycle callbacks not firing correctly in all disconnection scenarios (#4935)
  • Fixed panics during unsubscribe operations (#4938)
  • Fixed view auto-migration when using canonical names (#4985)
  • Eliminated unnecessary msync calls on the entire offset index file, improving write performance (#5018)
  • Fixed directory fsync issues on Windows snapshots (#4939)
  • Fixed auth error details leaking in debug output (#5000)
  • Prepared statements are now properly rolled back on transaction failure (#4979)

Infrastructure

  • Client binaries are now distributed from AWS instead of DigitalOcean for improved reliability (#5077)
  • Internal: cargo ci dlls renamed to cargo regen csharp dlls (#4972)

What's Changed

New Contributors

Full Changelog: https://github.com/cloc...

Read more

Release v2.2.0

02 May 22:48
eb11e2f

Choose a tag to compare

2.2.0 is here, and this one is a meaningful step forward for SpacetimeDB's realtime performance, operational safety, and day-to-day developer workflow. There are plenty of smaller fixes in this release too, but these are the major changes worth calling out.

Features

Faster realtime transport and client throughput

We’ve introduced a new v3 WebSocket transport that batches multiple logical client messages into a single frame, cutting per-message overhead while keeping the existing message model intact (#4761). The TypeScript SDK now uses the new transport by default (#4784). Under the hood, this release also includes a substantial round of hot-path performance work across the TS client, JS module runtime, and durability pipeline to improve throughput and reduce scheduler overhead under load.

Safer production database operations

We added spacetime lock and spacetime unlock to protect databases from accidental deletion (#4502). On top of that, spacetime delete now asks for confirmation by default (#4770), spacetime list shows database names alongside identities (#4769), and spacetime publish --yes can now skip only the prompts you intend to skip instead of skipping all of them (#4885).

Better TypeScript app ergonomics

Web developers get two nice upgrades in 2.2.0. There’s now a first-party Astro + TypeScript template with SSR and a live React island for realtime updates (#4688), and the TypeScript React bindings now include a typed useProcedure hook so procedures fit the same ergonomic pattern as reducers (#4752).

Smoother schema evolution

Publishing schema changes is less brittle now. Empty tables can be dropped during auto-migration (#4593), and changing or removing a primary key no longer leaves stale schema state behind that breaks future publishes (#4666).

More powerful table and index APIs

Modules can now clear tables directly from Rust, C#, C++, and TypeScript (#4729), and the index layer gained bytes-key B-tree support for more capable multi-column range scans (#4733).

Bug Fixes

  • Improved crash resistance for JavaScript modules by preventing V8 near-heap-limit failures from taking down the server, and by rotating isolates when heap growth or fragmentation gets out of hand (#4777, #4684).
  • Fixed a schema migration bug where changing or removing a primary key could leave stale schema state behind and break a later publish (#4666).
  • Fixed table migration sequence persistence so autoinc values no longer reset after restart when a table has been migrated (#4902).
  • Windows CLI binaries are now code-signed, which should make installation and update flows smoother on Windows (#4906).
  • Improved module panic backtraces so runtime failures are easier to diagnose (#577).
  • Hardened local durability so snapshot files, metadata.toml, and pid files are properly synced to disk instead of being vulnerable to loss on an untimely crash (#4891, #4892, #4890).
  • Fixed an Unreal SDK bug where overlapping subscriptions could fire duplicate OnInsert events for already-cached rows (#4903).

If you run into anything new with this release, file an issue on GitHub or drop into Discord and let us know.

What's Changed

Read more

Release v2.1.0

24 Mar 00:56

Choose a tag to compare

Another week, another reason to celebrate 🎉 2.1.0 is here, and it's bringing some long-awaited features alongside a handful of satisfying bug squashes!

Features

🦀 Rust client Wasm support

This one's been a long time coming. The Rust client SDK can now compile and run in the browser thanks to resolved Wasm compilation issues. If you've been waiting to build browser-based apps with the Rust SDK, your wait is over #4183

🎮 C++ Modules + Unreal SDK

Unreal developers, rejoice — both the C++ module bindings and the Unreal SDK have been brought up to speed with SpacetimeDB 2.0's APIs and codegen. Full compatibility, no more workarounds.

  • Update C++ bindings for 2.0 compatibility #4461
  • Update Unreal SDK to match latest APIs and codegen #4497

Bug Fixes

There are several bug fixes in this release:

  • Fix useTable isReady reverting to false after first row event by #4580
  • Fix v2 client disconnects dropping subscriptions for other v2 clients #4648

If you experience any new issues with this release either file an issue on GitHub or drop into our Discord — we're always around.

We'll see you again soon for the next release 😉

What's Changed

New Contributors

Full Changelog: v2.0.5...v2.1.0

Release v2.0.5

13 Mar 15:54

Choose a tag to compare

Hello again everyone! This is another small bug fix release. There was a small bug introduced during the v2.0.4 that we're fixing here, plus another fix for users who are trying to use LLMs in procedures. We recommend upgrading to this version at your earliest convenience.

Fixes

Thank you to everyone who has reported issues in the discord! It has made it much easier to track these bugs down and fix them quickly 🛠️

What's Changed

New Contributors

Full Changelog: v2.0.4...v2.0.5

Release v2.0.4

11 Mar 18:28

Choose a tag to compare

Hello everyone! This week's release is a small bug-fix patch with a few UX improvements 🎉

New Features

  • The spacetime CLI now checks daily for updates. When an update is available a notice is posted telling the user to upgrade.
  • The spacetime dev project initialization logic now includes a fuzzy search which makes it much easier to find and select a template.

Bug Fixes

  • Fix spacetime login --token falling through to web login
  • Several correctness fixes which could prevent a database from loading

What's Changed

New Contributors

Full Changelog: v2.0.3...v2.0.4

Release v2.0.3

04 Mar 20:52
5836c26

Choose a tag to compare

SpacetimeDB v2.0.3

We've been getting amazing feedback on our 2.0 release. Today we have a release of small bugfixes and QoL improvements in the CLI and SDK based on some of what we've been hearing. More to come soon!

New features

  • spacetime logs --level filtering. Filter logs by severity with --level warn (that level and above) or --level info --level-exact (exact match only). Works with both text and JSON output. (#4362)

Bug fixes

  • We have improved the latency for making commits durably persisted
  • React: fix useTable isReady stuck on false.
  • TanStack Start: fix useSpacetimeDBQuery returning untyped rows.
  • TypeScript: fix toCamelCase conversion.
  • Fix index truncate edge cases.
  • CLI: preserve leading .. in --out-dir paths.
  • CLI: fix publishing in directories with spaces.
  • CLI: skip upgrade prompt when -y is passed.

C# SDK

  • Improve error messages for Views. Better diagnostics when view queries fail in the C# SDK. (#4435)

What's Changed

New Contributors

Full Changelog: v2.0.2...v2.0.3

Release v2.0.2

26 Feb 19:54
bc4fcec

Choose a tag to compare

SpacetimeDB v2.0.2

A bug fix and quality-of-life release following the 2.0 launch. This release focuses on CLI improvements, durability tuning, and documentation fixes.

Bug fixes

  • TypeScript: fix table schema wire name lookup crash. The TypeScript SDK was using PascalCase accessor names for wire protocol lookups, causing crashes when case conversion was enabled. (#4449)
  • spacetime dev: fix file watcher ignoring --module-path. When --module-path was set via CLI flag or spacetime.json, the file watcher still watched the default directory instead. (#4464)
  • spacetime dev: better error when module directory does not exist. Previously showed a confusing "could not detect language" error. Now shows the actual missing path. (#4467)
  • Fix "Press any key to exit" in templates. The prompt said "any key" but actually required Enter. Updated text and logic to match. (#4468)
  • Don't save source_config to spacetime.json. Internal build configuration was being persisted to the user-facing config file. (#4422, #4423)

Performance

  • Reduce local durability fsync interval to 10ms (down from misconfigured 500ms default), improving confirmed reads latency for local (non-replicated) databases. (#4466, #4420)
  • C# SDK: ArrayPool for row iteration buffers. RawTableIterBase.Enumerator now rents from ArrayPool<byte>.Shared instead of allocating a fresh byte[] per step, significantly reducing GC pressure. (#4385)

Documentation

  • Correct unique indexes in cheat sheet to use filter, not find. (#4452)
  • Correct "table" to "view" in Zen of SpacetimeDB. (#4434)
  • Update C# docs with List<T> returns and IEnumerable<T> examples. (#4392)
  • Fix AI assistant rules links in llms.txt. (#4430)
  • Add ARM M-series CPU note in benchmark readme. (#4426)
  • Add schedule name correction for LLM rules. (#4370)
  • Fix Spacerace button and rename nav item to Referrals. (#4458, #4477)

What's Changed

Full Changelog: v2.0.1...v2.0.2

SpacetimeDB 2.0

20 Feb 22:03
a4d29da

Choose a tag to compare

SpacetimeDB 2.0 is finally here! 🌟

image

Today we're announcing SpacetimeDB! SpacetimeDB 2.0 has some big changes, so buckle up! Get ready for web development at the speed of light!

To find out in detail how to update your applications for 2.0 see our Migration Guide.

TypeScript/JavaScript Support

In October we launched beta support for TypeScript and JavaScript, and we're happy to announce that with the release of 2.0 TypeScript support is leaving beta! We also have a bunch of updates to the API that being much needed consistency to the APIs.

Web framework integration

Along with TypeScript and JavaScript support, we've built integrations and templates with all your favorite frameworks including:

Unreal Engine/C++ Support

For all those who have been waiting for official Unreal Engine 5 support, it's here! Alongside C++ modules as well!

Incredible performance

SpacetimeDB 2.0 delivers eye watering throughput even for tiny transactions with high contention. Well over 100k transactions per second for TypeScript modules and up to 170k transactions per second for Rust modules!

image

See how it compares to other databases in our new keynote presentation!

A new Maincloud FREE tier and all new pricing!

With 2.0, we're also announcing a brand new, simpler pricing scheme along with a free tier for users who want to try out Maincloud!

This new simplified pricing makes it easier than ever to predict your costs. Check out our pricing calculator on the pricing page.

Spacerace Referral Program

Alongside our new pricing, we're introducing the Spacerace Referral Program where you can get up to 400x more free credits per month by referring friends to the platform.

image

Procedures and HTTP calls

With 2.0 your SpacetimeDB modules are getting a big boost in capability too. For the first time, your modules can now access the outside world with Procedure Functions. Procedure functions give you the ability to make HTTP calls from within your module, letting you integrate directly with external APIs. This is how easy it is to call ChatGPT's API from within your module:

export const ask_ai = spacetimedb.procedure(
  { prompt: t.string(), apiKey: t.string() },
  t.string(),
  (ctx, { prompt, apiKey }) => {
    // Make the HTTP request to OpenAI
    const response = ctx.http.fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`,
      },
      body: JSON.stringify({
        model: 'gpt-4',
        messages: [{ role: 'user', content: prompt }],
      }),
      // Give it some time to think
      timeout: TimeDuration.fromMillis(3000),
    });

    if (response.status !== 200) {
      throw new SenderError(`API returned status ${response.status}`);
    }

    const data = response.json();
    const aiResponse = data.choices?.[0]?.message?.content;

    if (!aiResponse) {
      throw new SenderError('Failed to parse AI response');
    }

    // Store the conversation in the database
    ctx.withTx(txCtx => {
      txCtx.db.aiMessage.insert({
        user: txCtx.sender,
        prompt,
        response: aiResponse,
        createdAt: txCtx.timestamp,
      });
    });

    return aiResponse;
  }

Read more about Procedure Functions.

SpacetimeAuth (and Clerk and Auth0)

And to help you avoid needing to set up additional sidecars and services alongside SpacetimeDB we've also introduced SpacetimeAuth, our first party auth solution. SpacetimeAuth is completely free to use with SpacetimeDB Maincloud!

We've also built tutorials for how to integrate with other auth providers like Clerk and Auth0!

View Functions

In SpacetimeDB 2.0, adding sophisticated read permissions to expose portions of your data to users is as simple as creating a function:

export const players_for_level = spacetimedb.anonymousView(
   { name: 'players_for_level', public: true },
   t.array(playerAndLevelRow),
   (ctx) => {
       const out: Array<{ id: bigint; name: string; level: bigint }> = [];
       for (const playerLevel of ctx.db.playerLevels.level.filter(2n)) {
           const p = ctx.db.players.id.find(playerLevel.player_id);
           if (p) out.push({ id: p.id, name: p.name, level: playerLevel.level });
       }
       return out;
   }
);

You can think of view functions as a table that is backed by a reducer. From the client, they look just like any other table in your database, but in the module they're represented as a function that returns rows that you want to expose to clients. Better yet, the table is automatically parameterized by the identity of the viewing client, allowing different clients to see different data when viewing the same table.

Views can also return custom types allowing you to not only filter rows, but also columns. Views are an elegant way of solving read permissions without introducing a single new concept!

Read more about View Functions.

Typed Query Builder

In SpacetimeDB 2.0, you can kiss your stringly-typed queries goodbye! With our 2.0 SDK and code generation, we generate beautifully typed query builder APIs that allows your clients to build arbitrary queries over the data.

ctx.subscriptionBuilder().subscribe([tables.user.where(user => user.name.eq("Tyler")), tables.message]);

Never worry about runtime errors with your queries again! And the strongly typed queries also help LLMs succeed more often as well.

Even better, you can access this same query builder API inside your view functions to return queries from your views so they can be optimized by our incremental evaluation query engine!

export const high_scorers = spacetimedb.anonymousView(
  { name: 'high_scorers', public: true },
  t.array(players.rowType),
  (ctx) => {
    return ctx.from.players
      .where(p => p.score.gte(1000n))
      .where(p => p.name.ne('BOT'));
  }
);

Event Tables

Event tables are also all new in SpacetimeDB 2.0. Event tables allow you to publish short lived event information to clients without needing to clean up your tables later on. Event tables act like regular tables, but the rows are automatically deleted by SpacetimeDB at the end of a transaction. This both saves you storage costs and also bandwidth, as the database needs to synchronize less state!

Publishing an event to clients is as simple as inserting into a row into the event table, and subscribing to it like any other table.

// server
const damageEvent = table({
  public: true,
  event: true,
}, {
  entity_id: t.identity(),
  damage: t.u32(),
  source: t.string(),
});

export const attack = spacetimedb.reducer(
  { target_id: t.identity(), damage: t.u32() },
  (ctx, { target_id, damage }) => {
    // Game logic...

    // Publish the event
    ctx.db.damageEvent.insert({
      entity_id: target_id,
      damage,
      source: "melee_attack",
    });
  }
);

// client
conn.db.damageEvent.onInsert((ctx, event) => {
  console.log(`Entity ${event.entityId} took ${event.damage} damage from ${event.source}`);
});

Read more about Event Tables.

spacetime.json configuration

With 2.0, we're also introducing a new config file to make it easier to interact with your databases. Now with spacetime.json you can save all your database configuration in a single file that you check in to git, so instead of this:

spacetime generate --lang typescript --out-dir src/module_bindings
spacetime publish --server maincloud --module-path spacetimedb my-database

You can now just type this:

spacetime generate
spacetime publish

spacetime dev

Development is getting simpler too, with our new spacetime dev command. This command is your one stop shop for development. It:

  1. Watches for changes in your module code
  2. Compiles your module
  3. Generates your client module bindings
  4. Publishes your module
  5. Runs your client

Now all you have to do is change your code and your whole app updates instantly!

All new dashboard and metrics

We've also added beautiful new dashboards and analytics so you can monitor your apps and data in real-time! And they update in real-time too! It's incredible to see tables updating live, trust us!

#...

Read more

Release v1.12.0 - Client-side Typed Query Builder

04 Feb 17:18

Choose a tag to compare

The end of 1.0 is nigh! 🤩

v1.12 will be the last minor version before we drop SpacetimeDB 2.0! SpacetimeDB 2.0 will come with code breaking changes (you may need to change your modules and clients), but it will not require a migration of the existing data directory, and include backwards compatibility with existing clients and modules, so all existing databases and modules will continue working on both Standalone deploys and Maincloud.

If you're not subscribed to our YouTube channel, you should be. Trust me on that one.

We've got some great updates today in v1.12!

Typed Query Builder

  • Added a typed query builder for the TypeScript client. (#4021)
  • Added a Rust client query builder. (#4003)
  • Added a typed query builder for the C# client, plus additional regression coverage. (#3982, #4123)

You can now subscribe to your server's data with type safe queries from clients:

TypeScript

import { queries } from "./module_bindings";
conn.subscriptionBuilder().subscribe([queries.user.build()]);

C#

conn.SubscriptionBuilder().AddQuery(ctx => ctx.From.User().Build()).Subscribe();

Rust

conn.subscription_builder().add_query(|ctx| ctx.from.user().build()).subscribe();

NOTE: We would like to remove the .build() for 2.0, but you can try it out with the existing API.

Other highlights

  • New front-end framework SDKs

    • Added a Vue framework SDK. (#4037)
    • Added a Svelte framework integration. (#4063)
  • Organizations support

    • Introduced Organizations support. (#4087)
  • Operational tooling improvements

    • Added spacetime login --no-browser for headless/CI environments. (#4142)
    • Core: added a method to query the replica IDs managed by the host controller. (#4160)

Developer experience & docs

  • Added new authentication tutorials:
  • Documentation updates and clarifications, including explaining “maincloud” context. (#4029, #4071, #4168)

Performance & internal improvements

  • Multiple datastore and update-path optimizations (construction, view evaluation fast paths, layout usage, and small data-structure refinements). (#4133, #4134, #4138, #4136)
  • Reduced JS worker request/reply sizes and improved data-structure choices for better cache efficiency. (#4150, #4151)

Reliability & correctness

  • Fixed Hash indices not working. (#4060)
  • Durability: notify waiters after lockfile drop. (#4051)
  • Fixed occasional panic when a client disconnects. (#4162)
  • Improved blob handling flexibility (copy_filter and related). (#4096)
  • Marked MutTxId as !Send to avoid incorrect cross-thread usage. (#4039)
  • Added support and filtering improvements around Uuid (including React Hook where support and making the new Uuid type filterable). (#4030, #3991)

New contributors

What's Changed

Read more