Why Cosmictron for Games?
⚡ Sub-millisecond Latency
0.8ms average response time. Game logic runs inside the database—no network hops.
🎯 Deterministic Reducers
ACID transactions ensure game state consistency. No race conditions or desync.
👥 10K+ Concurrent Players
Scale to thousands of players on a single $20 server. Horizontal scaling ready.
🔄 Real-time Sync
Player positions, scores, and game state sync instantly to all clients.
Example: Simple Arena Game
Schema
#[table(name = "players")] pub struct Player { #[primary_key] pub id: u64, #[index] pub session_id: String, pub x: f32, pub y: f32, pub health: i32, pub score: u32, #[index] pub last_update: u64, } #[table(name = "game_state")] pub struct GameState { #[primary_key] pub id: u32, // always 0 for singleton pub status: String, // "waiting" | "playing" | "ended" pub started_at: Option, }
Game Logic
// Player joins the game #[reducer] pub fn join_game(session_id: String) -> Player { let player = Player { id: 0, session_id, x: rand::random::() * 100.0, y: rand::random:: () * 100.0, health: 100, score: 0, last_update: ctx.timestamp(), }; ctx.db.players().insert(&player); player } // Update player position #[reducer] pub fn move_player(player_id: u64, x: f32, y: f32) { // Verify ownership let player = ctx.db.players().id().find(player_id) .expect("Player not found"); assert_eq!(player.session_id, ctx.sender().to_string()); // Update position ctx.db.players().id().update(player_id, Player { x, y, last_update: ctx.timestamp(), ..player }); } // Handle player hit #[reducer] pub fn player_hit(target_id: u64, damage: i32) { let target = ctx.db.players().id().find(target_id) .expect("Target not found"); let new_health = (target.health - damage).max(0); if new_health == 0 { // Player died - update scores ctx.db.players().id().delete(target_id); // Award kill to attacker let attacker = ctx.db.players() .session_id().find(ctx.sender().to_string()) .expect("Attacker not found"); ctx.db.players().session_id().update( ctx.sender().to_string(), Player { score: attacker.score + 1, ..attacker } ); } else { ctx.db.players().id().update(target_id, Player { health: new_health, ..target }); } }
Client Subscription
Clients subscribe to game state and receive real-time updates:
// Subscribe to all player positions const playersSub = await client.subscribe( 'SELECT id, x, y, health, score FROM players', (delta) => { delta.inserts.forEach(player => game.addPlayer(player)); delta.updates.forEach(player => game.updatePlayer(player)); delta.deletes.forEach(player => game.removePlayer(player.id)); } ); // Send player movement function onPlayerMove(x: number, y: number) { client.callReducer('game', 'move_player', { player_id: myPlayerId, x, y }); }
Performance at Scale
BitCraft, an MMORPG built on similar technology, handles:
- Tens of thousands of concurrent players
- 6M+ hours of total playtime
- Real-time world simulation with thousands of entities
Cosmictron's DBSP engine and zero-latency architecture make similar scale achievable for small teams.
Get the Code
Check out the complete example in our repository:
git clone https://github.com/cosmictron/cosmictron.git cd cosmictron/examples/gameserver
The example includes:
- Complete game server with player management
- TypeScript game client using Phaser.js
- Real-time position synchronization
- Scoring and health system