In development. Join the waitlist for early access.

Realtime messaging backend

Realtime channels. Every event, in order.

Public, private and presence channels over WebSockets. Publish from your backend with a signed REST call. Every event gets a sequence number, so a client that reconnects replays exactly what it missed.

const client = new MessageGo("wss://your-host", {
  app_id: "demo-app",
  token: jwt, // issued by your backend
});
await client.connect();

const room = await client.subscribe("presence:room-1");

room.bind("new_message", ({ seq, data }) => {
  console.log(seq, data.body);
});
room.onJoin((joins) => console.log(Object.keys(joins)));

Built on proven parts, not a black box.

  • Elixir
  • Phoenix Channels
  • PostgreSQL
  • WebSocket
  • JWT

How it works

Connections drop. Your users shouldn't notice.

Phones change networks and tabs go to sleep. A realtime layer that only delivers what is live leaves a gap each time that happens. MessageGo stores and numbers every event, so a returning client asks for everything after its last sequence number and gets it, in order, before live events resume.

How MessageGo moves an eventYour backend publishes an event over REST. MessageGo stores it with a sequence number in a durable log and pushes it over WebSockets to web, mobile and native clients. A client that reconnects asks for events after its last sequence number and receives the ones it missed.Your backendsigned REST publishPOSTMESSAGEGOpublic:*private:*presence:*durable event log · public:generalseq 12001new_messageseq 12002new_messageseq 12003new_messageseq 12004new_messageWSWeb appiOS · AndroidReact Native · Flutterreconnect: from_seq=12003 → replays seq 12004
One unit, repeated: the numbered event. The log is the source of truth; WebSockets are just how it reaches your clients.

Capabilities

Five properties of the design, not features bolted on.

  • 01

    Three channel types

    public:*, private:* and presence:*. Private and presence channels need a short-lived channel token; presence tracks who joins and leaves.

    See the code
  • 02

    Ordered, durable events

    Every event gets an event_id, a per-channel seq and a timestamp, and is stored before it is delivered.

    See an event
  • 03

    Replay on reconnect

    The SDK rejoins with from_seq and missed events arrive in order. At-least-once delivery within the retention window (72 hours by default).

    See how it works
  • 04

    Signed publishing

    Your backend publishes with an HMAC-SHA256 signature. An Idempotency-Key header stops retries from creating duplicate events.

    See a publish call
  • 05

    Any client

    A JavaScript SDK, plus a documented wire protocol for building React Native, Flutter, iOS and Android clients.

    Join the waitlist

In code

From first connection to resumed stream, in a few lines.

  1. 01

    Authorize

    Your backend issues a connection JWT with a user_id and an exp. Private channels trade it for a channel token automatically.

  2. 02

    Subscribe

    One call joins a channel and binds handlers. Each payload arrives with its seq.

  3. 03

    Resume

    After a long gap, pull history from the last seq you saw, or let the SDK replay it on reconnect.

resume.js
const sub = await client.subscribe("public:general");
sub.bind("new_message", render);

// The SDK reconnects and replays on its own. To catch up
// manually after a long offline period:
const missed = await client.fetchHistory("public:general", {
  afterSeq: sub.lastSeq(),
  limit: 50,
});

missed.forEach((e) => render(e.data));
// each e has: event_id, seq, event, data, created_at

Be first on MessageGo.

We're finishing the platform. Leave your email and we'll tell you when early access opens.

We'll only use your email to contact you about MessageGo.