v2.4.0

vladmandic/humanv2.4.0Jun 3, 2026by rekhoff

AI Summary

v2.4.0 introduces unstable HTTP handlers for modules across multiple languages, optimizes reducer execution performance with a dedicated runtime, and fixes critical durability and observability bugs.

Key Highlights

  • Unstable HTTP handlers in modules for webhooks and REST APIs
  • Faster WASM reducer execution using a dedicated synchronous runtime
  • Fixed silent data loss on resume (durability bug)
  • V8 heap metrics now cover procedure workers

New Features

  • HTTP handlers in modules (Rust, TypeScript, C#, C++)
  • Dedicated synchronous WASM runtime for reducers
  • V8 heap metrics for procedure workers
  • Enhanced commitlog decode error context

Full Release Notes

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 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`:
```rust
[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.

Modules can now define custom HTTP routes and serve arbitrary HTTP requests directly from module code (Rust: [#4636](https://github.com/clockworklabs/SpacetimeDB/pull/4636), Typescript: [#4980](https://github.com/clockworklabs/SpacetimeDB/pull/4980), C#: [#5024](https://github.com/clockworklabs/SpacetimeDB/pull/5024),C++: [#5023](https://github.com/clockworklabs/SpacetimeDB/pull/5023)). 

Using a Rust as an example, annotate a function with `#[spacetimedb::http::handler]` to create a handler, then wire it into your module's routing table with `#[spacetimedb::http::router]`.

```rust
#[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)
}
```

[#5024](https://github.com/clockworklabs/SpacetimeDB/pull/5024) adds the C# handler/router API `[SpacetimeDB.HttpHandler]`, `[SpacetimeDB.HttpRouter]`
[#5023](https://github.com/clockworklabs/SpacetimeDB/pull/5023) adds the C++ handler/router API `SPACETIMEDB_HTTP_HANDLER()`, `SPACETIMEDB_HTTP_ROUTER()`

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](https://github.com/clockworklabs/SpacetimeDB/pull/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](https://github.com/clockworklabs/SpacetimeDB/pull/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](https://github.com/clockworklabs/SpacetimeDB/pull/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](https://github.com/clockworklabs/SpacetimeDB/pull/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](https://github.com/clockworklabs/SpacetimeDB/pull/4927)).

## What's Changed
* V8 heap metrics: Track instance memory usage for procedure workers too by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/5122
* fix `unity-testsuite`: clear intermediate Godot build state by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/5133
* Revert "Properly handle execution time<->energy conversion in v8 host (#4884)" by @jdetter in https://github.com/clockworklabs/SpacetimeDB/pull/4927
* commitlog: Error context for commit decode errors by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/5129
* Use synchronous runtime for the main wasm execution lane by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/5095
* core: Remove view cleanup trace logs by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/5137
* commitlog: Truncate segment before resuming by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/5116
* Isolate Godot NuGet restore from Unity package cache by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/5136
* Add required ci check for `keynote-2` benchmark by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/5078
* Add Deep Database Style by @cloutiertyler in https://github.com/clockworklabs/SpacetimeDB/pull/4925
* CI: skip Internal Tests dispatch for docs-only changes by @cloutiertyler in https://github.com/clockworklabs/SpacetimeDB/pull/4995
* Implement HTTP handlers / webhooks in Rust modules by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/4636
* Move `Internal Tests` to its own workflow by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/5147
* Remove physical module layout info from read sets by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/5149
* Add basic troubleshooting guide by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/5142
* Drop tps threshold for rust keynote-2 ci check by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/5159
* Add new LLM chat template by @JasonAtClockwork in https://github.com/clockworklabs/SpacetimeDB/pull/5150
* Add new hangman TS template by @JasonAtClockwork in https://github.com/clockworklabs/SpacetimeDB/pull/5119
* Don't use ReadableStream as an asyncIterator by @coolreader18 in https://github.com/clockworklabs/SpacetimeDB/pull/5144
* Add new money exchange TS template by @JasonAtClockwork in https://github.com/clockworklabs/SpacetimeDB/pull/5134
* Add TypeScript Blackholio server + client by @JasonAtClockwork in https://github.com/clockworklabs/SpacetimeDB/pull/5140
* Godot Blackholio completion by @lisandroct in https://github.com/clockworklabs/SpacetimeDB/pull/5030
* Remove `.github/docker-compose.yml` by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/5160
* CI - `ci self-docs` includes value names by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/5152
* Update selected crate licenses to Apache 2.0 by @clockwork-labs-bot in https://github.com/clockworklabs/SpacetimeDB/pull/5151

**Full Changelog**: https://github.com/clockworklabs/SpacetimeDB/compare/v2.3.0...v2.4.0