ARCANUM
durable log · database

Rune

Streams, state and live aggregates for a game backend, in one system. Write events, read player state by key, query leaderboards as they change.

≈ 50 µs
p50 produce → ack
≈ 200 µs
p99 produce → ack
rUDP
reliable UDP transport, never TCP
0
allocations on the hot path

A log that is also your database

materialized views

Joins and aggregates over your topics, current on every write. Read any row by key.

tables

Compacted topics keep the latest value per key: player state with no separate database.

typed schemas

Schema registry and generated C++ types. Add, drop and rename fields without breaking old clients.

transactions

Exactly-once writes across topics and partitions, consumer offsets in the same commit.

consumer groups

Partitions spread across your workers and rebalanced on join, leave or failure.

durable streams

Replicated, keyed, ordered per partition, idempotent producers, automatic failover.

TLS 1.3

Encrypted client sessions with hostname verification.

transient topics & views

Replicated in memory, never on disk. Transient views rebuild from their topics on restart.

game-loop client

Run the client inside your server tick: no client threads, no blocking calls.

Rune QL

Define and evolve topics with statements in the rune console.

In an MMO backend

Your topics are your database

usercharacterpositionsharded by userId
character_view user ⋈ character ⋈ positionuser_stats count · max · avg per user
rune> topic user { userId int64, name string(32), level int32 } partitions 16 key userId; rune> topic character { userId int64, characterId int64, class string(16), level int32 } partitions 16 key (userId, characterId) partition by userId; rune> topic position { userId int64, characterId int64, zone int32, x float64, y float64, z float64 } partitions 16 key (userId, characterId) partition by userId;
rune> create view character_view key (userId, characterId) as select u.name, c.class, c.level, p.zone, p.x, p.y, p.z from character c join user u on u.userId = c.userId left join position p on p.userId = c.userId and p.characterId = c.characterId; rune> create view user_stats key userId as select count(*) as characters, max(level) as top_level, avg(level) as avg_level from character group by userId;

A position write updates one row. A rename updates every row of that user. Views are persisted by default and recover on restart. No ETL, no cache to invalidate.

Rune vs Kafka 4.0

Same hardware · 3 nodes · replication factor 3 · 64 B records

throughput, rec/s · higher is better

Rune1.4M
Kafka430k