What it is
Inter-database communication for SpacetimeDB, until native IDC ships. Your database sends a message from any reducer, and it's pushed to the other database right after your transaction commits. The receiver applies it in a transaction of its own and can reply the same way, so both sides are event-driven with no polling.
Delivery is reliable: no message without its commit and no commit without its message. Retries back off from 500 ms to 60 s, each peer's messages stay in order, and every message is applied exactly once. It also includes signed RPC and SQL calls to peers, and handoffs that move an entity (say, a character) to another database without ever duplicating or losing it.
Where it fits
- Any setup with more than one database that need to react to each other: a shop and a warehouse, game world shards passing players between them, a central account database feeding per-region game databases, or splitting a large module into services.
- It replaces calling another database's HTTP API from a procedure, with a hand-maintained table of tokens on one side, a table of known callers on the other, and polling for changes.
How it works
Mount it with schema({ ..., idc }), pass the config from environment variables (IDC_SELF, IDC_SECRET, IDC_PEERS, IDC_TRANSPORT) into idc.configure in init, and add the inbox and pairing HTTP routes.
idc.send(ctx.as.idc, 'warehouse', 'reserve', {...}) writes the message to an outbox table in the same transaction as your change, and a scheduled procedure POSTs it, HMAC-signed, right after the commit. On the other side, your onMessage callback runs inside the transaction that also records the message id, so a retried delivery is never applied twice.
It waits until commits are durable before sending and before forgetting, and a crash test checks this in CI. TypeScript, Rust and C# versions speak the same protocol, so the databases can be written in different languages.


