Real-Time Chat Application
Messaging with presence, media and delivery states
A messaging application built on Socket.IO and Redis with one-to-one and group conversations, media messages, presence, typing indicators and delivery and read states.
What this system is
Chat looks simple until the network misbehaves. This project focused on the parts users notice when it goes wrong: whether a message was actually delivered, whether the other person is online, what happens when the connection drops mid-send, and whether the conversation looks the same after a reload.
- Category
- Real-time system
- Technologies
- Socket.IONode.jsRedisMongoDBMedia storage
- Client
- Client details withheld
What was actually wrong
- Messages must not be silently lost when a connection drops between send and acknowledgement.
- Presence held in the memory of a single server process cannot survive a restart or scale to more than one instance.
- Media messages need upload, storage and delivery that do not block the message channel or bloat the database.
- Conversation history has to be consistent across devices and after reconnection, without re-sending everything.
How it was solved
- A message lifecycle with explicit states — sending, sent, delivered, read — acknowledged by the server so the client can retry rather than assume.
- Presence and socket session state stored in Redis, making the socket layer restart-safe and horizontally scalable.
- Rooms per conversation, with authentication and membership checked when joining rather than trusted from the client.
- Media uploaded separately to object storage, with only references travelling through the message channel.
- Reconnection logic that requests missed events since the last known message, instead of reloading whole conversations.
- Persistence in MongoDB with indexes shaped around the two queries that matter: recent messages in a conversation, and a user's conversation list.
How the system is put together
The parts, and why each one is there.
- 01Node.js server with a Socket.IO gateway and REST endpoints for history and uploads.
- 02Redis for presence, socket sessions, typing state and unread counters.
- 03MongoDB for messages, conversations and membership.
- 04Object storage (S3-compatible / MinIO) for media, referenced by key from messages.
- 05Token authentication verified on socket connection, not only on HTTP.
What it does
The functionality that carries the system, described from the user's point of view.
One-to-one and group chat
Conversations with membership rules and per-room event routing.
Media messages
Images, documents and other attachments uploaded to object storage and referenced from the message.
Presence and typing
Online state and typing indicators backed by Redis with expiry, so stale state clears itself.
Delivery and read receipts
Per-message states acknowledged by the server and reflected in the UI.
Notifications
Unread counts and alerts for conversations the user is not currently viewing.
Reconnection handling
Missed events replayed on reconnect without reloading entire conversations.
Stack
Real-time
- Socket.IO
- WebSockets
Backend
- Node.js
- REST APIs
Data
- MongoDB
- Redis
Storage
- S3-compatible object storage
- MinIO
Development highlights
Message state is server-acknowledged, so the client never shows "sent" for something the server never received.
Presence keys carry a TTL, which means a crashed client cannot leave a user permanently shown as online.
Socket authentication and room membership are enforced server-side on every join.
Indexes designed for the actual access patterns, which is what keeps a chat list fast as history grows.
Where it ended up
Described in terms of what the system now does. No invented metrics.
A messaging layer that behaves predictably on unreliable mobile connections.
A socket architecture that can run more than one instance because no critical state lives in process memory.
Patterns — presence, delivery states, reconnection — reused directly in later real-time work.
Building something like this?
Tell me where your situation is similar and where it differs. The differences are usually where the real work is.
Typical first reply within one business day · Lahore, PKT (UTC+5)