irt.io vs PartyKit

PartyKit is a framework for realtime servers. You write a server class with connection and message handlers, deploy it, and design the wire protocol yourself. irtio ships the state model instead: a typed schema, per-instance ownership, binary deltas and a tick loop.

When PartyKit is the better choice

  • The realtime thing is not a game. Collaborative documents, chat, live cursors on a marketing site, presence widgets and streaming AI output are all a better fit for a general purpose realtime server than for a room with a schema and a tick rate.
  • You want your own protocol. If you already have a message format, or the state is a CRDT document rather than a set of records, a state-sync system is something to work around.
  • Your server has to reach other services. A PartyKit server is ordinary code, so it can call APIs, await results and serve HTTP routes next to the socket. An irtio room handler is synchronous and has no fetch, which is what makes a room replayable.
  • You are already on that stack. Running your realtime piece in the same runtime and account as the rest of your app is worth a lot on its own.

When irt.io is the better choice

  • You would otherwise write a sync engine. Deltas, join catch-up, interpolation, write batching, reconnect and correction are the parts of multiplayer that take the longest and look the most like everyone else’s. On a raw socket they are yours to build.
  • Cheating matters. irtio gives every instance an owner and runs your validator on every owner write, before anyone else sees the value. Server-owned collections cannot be written by a client at all.
  • The game moves continuously. A fixed-rate tick, server physics and client prediction are configuration in irtio.
  • You want the game layers. Voice, simulated players, visibility filtering, saves and leaderboards are already there.

Model comparison

PartyKitirt.io
AuthorityServer, and you write what it enforcesServer, per instance, with validators
Who operates the serverYou deploy your code to their platformirtio
State modelWhatever you keep in the server object and its storage, over messages you defineTyped schema, per-instance ownership, binary deltas
PredictionYou write itBuilt in for physics rooms, interpolation for everything else
PhysicsBring your ownRapier 3D or matter.js 2D, stepped on the server
VoiceNot includedjoinVoice(room)
TestingOrdinary server tests you arrangeIn-process rooms on a fake clock, plus simulated players over real sockets
Hibernation and idle costServers sleep when idle and wake on the next connectionRooms sleep after idleMs and wake with state intact
LanguageTypeScript or JavaScript, browser clientsTypeScript, browser clients

What porting looks like

Both sides are already room-shaped, so the port is mostly about deleting your protocol.

List the message types your server handles. Each one becomes one of two things. A message that reports what a player did to something they control becomes an owned write: put the record in the schema, add it in onJoin with { owner: ctx.clientId }, and the client assigns to it. The message type, its encoder, its decoder and its handler all go away. A message that asks the server to decide something becomes an RPC against a server-owned collection, which keeps its handler almost unchanged.

Then delete the broadcast half. Anything that serializes state and pushes it to connections is replaced by the room’s own delta flush, and anything on the client that applies those updates is replaced by reading room.state and drawing room.render.

Two pieces need a new home. Storage on the server object maps onto room state plus saves and player storage, and a scheduled wake-up maps onto alarms. Anything that awaited an external service has to move out of the room, because handlers are synchronous.

On the client, your socket becomes joinRoom(schema). The reconnect and backoff code you wrote around it is not needed.

Next steps

This page describes each product’s model as it stood at the page’s last review. Send corrections to hello@irt.io.