Relay
(Real-time Chat)A community chat app with channels, threads and presence that stays snappy with thousands online.
- <80ms message latency
- 50k messages / min
- 4.8★ app rating
2024 · React · Node.js · WebSockets · Redis · Docker
Problem
(what hurt)
The community lived in a rented chat tool that capped history and exports. They wanted their own space, but a single server fell over at around 800 concurrent users.
Project goal: A remote-first community wanted a chat app it owned, with channels, threads and presence, that feels instant even with thousands of people online.
Architecture
(how it fits together)
Stateless WebSocket gateways sit behind a load balancer. Each message is validated, written to Postgres and published to Redis, which fans it out to every gateway holding sockets for that room.
Tech decisions: A Node WebSocket gateway scaled horizontally with Redis Pub/Sub, optimistic UI in React, messages persisted in Postgres, and everything shipped as Docker containers.
- React
- Node.js
- WebSockets
- Redis
- Docker
wss.on("connection", (socket, req) => {
const user = authenticate(req);
socket.on("message", async (raw) => {
const msg = MessageSchema.parse(JSON.parse(raw.toString()));
await db.message.create({ data: { ...msg, authorId: user.id } });
// fan out to every gateway node in the cluster
await pub.publish("room:" + msg.roomId, JSON.stringify(msg));
});
});
sub.on("message", (channel, payload) => {
rooms.get(channel)?.forEach((s) => s.send(payload));
});Features
(what it does)
Optimistic sending
Messages appear instantly and reconcile with the server ID when the write lands, so chat never feels laggy.
Presence and typing
Ephemeral presence lives only in Redis with short TTLs, keeping the database free of noise.
Threads
Replies branch off any message without cluttering the channel.
Challenges
(what was hard)
01Reconnect storms
Deploys used to drop every socket at once. Jittered backoff and graceful connection draining fixed it.
02Ordering
Server-assigned sequence numbers per room keep messages in order across nodes.
Results
- <80ms message latency
- 50k messages / min
- 4.8★ app rating
Relay now handles 50k messages a minute at peak with sub-80ms delivery, and the community fully moved over in a month.
design & code by Shreya Pathak