Chat application

Users, conversations and messages: delivery states, group chats and notifying clients, modelled as classes rather than infrastructure.

On the roadmap:Software Design · step 6: Low-level design: games and apps

Lesson 14 of 16 · 10 min read · quiz · exercise

The problem

Users send text messages one-to-one or in groups. The app shows who is online, message status (sent, delivered, read) and notifies offline users. This lesson is about the classes; the infrastructure view (WebSockets, storage at scale) is in the chat-system lesson of the classic designs course.

Entities

Figure SDA-LLD-14-1 · Chat classes · © forcsguy.com

A conversation has a type (direct or group) and participants. A message belongs to one conversation and has one receipt per recipient.

Sending a message

Figure SDA-LLD-14-2 · Sending a message · © forcsguy.com

type Status = "SENT" | "DELIVERED" | "READ";
class Conversation {
  private subscribers = new Map<string, (m: Message) => void>();
  constructor(readonly id: string, readonly members: string[]) {}

  subscribe(userId: string, fn: (m: Message) => void) { this.subscribers.set(userId, fn); return () => this.subscribers.delete(userId); }

  send(from: string, text: string): Message {
    if (!this.members.includes(from)) throw new Error("not a member");
    const m = new Message(newId(), this.id, from, text);
    m.receipts = Object.fromEntries(this.members.filter(u => u !== from).map(u => [u, "SENT" as Status]));
    store.save(m);                                         // persist first
    for (const [u, fn] of this.subscribers) if (u !== from) fn(m);   // push to online users
    return m;                                              // offline users get it when they reconnect, or by push notification
  }
}

Offline users and ordering

  • Offline users receive messages on reconnect by asking for everything after the last message id they have, and may get a push notification.
  • Order within a conversation comes from a server-assigned, increasing message id.
  • Read receipts are updates to the per-recipient receipt, then aggregated for the sender (in a group, "read by 3 of 5").

Design notes

  • Observer decouples the conversation from how clients are connected.
  • Group size matters: a small group can notify each member directly; very large channels need a different fan-out approach.
  • Presence (online, last seen) is a separate component with its own throttled updates.
  • Privacy: block lists, muted conversations, and "delete for everyone" are policies checked before delivery.
  • Extensions: media messages (store files elsewhere, send a reference), replies, reactions, end-to-end encryption.

Real-world reading

Check your understanding

Question 1 of 3

0 correct so far

Which pattern fits 'notify everyone in the conversation when a message arrives'?

Go deeper

  • Chat system design (classic system designs course) by This site: for the infrastructure side: WebSockets, presence and storage

© 2026 forcsguy.com. Original lesson text and diagrams. Books and sites linked above belong to their authors.