Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 24 – Case studies: messaging, real time and collaboration

Design team chat like Slack or Discord

Design team chat for workspaces and huge communities: channels, roles and threads, channel servers, permission-aware search and apps with safe limits.

  • Advanced
  • 30 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 6 of 30 minutes free
Free: A few giants carry the load, and every request names its workspace. With a pass: the other 15 sections and 3 interview answers, about 24 minutes.

What you will learn

  • Estimate messages, deliveries, connections and storage for a team chat service
  • Design workspaces, channels, roles and threads
  • Scale channel fan-out, presence and typing to communities of hundreds of thousands of members
  • Build permission-aware search, safe integrations and tenant isolation

Before you start

What you’ll learn · Before you start

What you will learn

  • Estimate messages, deliveries, connections and storage for a team chat service
  • Design workspaces, channels, roles and threads
  • Scale channel fan-out, presence and typing to communities of hundreds of thousands of members
  • Build permission-aware search, safe integrations and tenant isolation

Before you start

On this page

To design team chat like Slack or Discord for 500,000 workspaces, start from the tenant. A workspace owns its members, roles, channels, apps and search, and every request and access check names it. Inside it, channels hold messages in the order of a sequence number per channel, kept for good and searchable; threads are replies keyed by their parent message. A post is checked against the channel’s permissions, numbered and stored, then handed to the channel’s owner, a channel server chosen by hashing the channel id, which fans it out to the gateways whose members are subscribed. A change log feeds the search indexes, which filter results by what the searcher may read, and the apps, which get signed events within per-workspace limits. Communities with hundreds of thousands of members add one more rule: presence and typing go only to people who are looking.

Not affiliated

Based on public information about Slack and Discord. MySmartCoPilot is not affiliated with Slack and Discord, and Slack and Discord’s real architectures may differ from what this lesson describes.

A few giants carry the load, and every request names its workspace

Ask these first; the answer this lesson assumes follows each question:

  • What is a workspace? A tenant: a company or a community, with its own members, roles, channels and apps. Discord’s developer documentation calls one a guild.
  • How large? 500,000 workspaces and 20 million people a day; most workspaces have fewer than 100 members, the largest company 200,000 and the largest community a million.
  • Which channels? Public channels anyone in the workspace may join, private channels for invited members, direct messages, and threads of replies under a message.
  • How long is history kept? For good, unless a workspace sets a retention period, and all of it is searchable.
  • Which integrations? Apps and bots that receive events and post messages, and incoming webhooks.

An interviewer who asks you to design team chat like Slack usually wants three things beyond one-to-one delivery: permissions that differ per channel, search over years of history, and apps that must not hurt other workspaces. People post, edit, delete, react and reply in threads; mention one person or a whole channel; search; manage roles; and install apps. The non-functional requirements: a post reaches online members within a second; nobody ever reads a channel they may not see, in the app or in search; one noisy workspace cannot slow the others; and nothing posted is lost.

The team chat service's estimate sheet Python · estimate/team_chat_sheet.py
# The estimate sheet of a team chat service (lesson system-design-hld/design-team-chat): workspaces with channels,
# history kept and searchable, apps that receive events. Every constant is an assumption with a name, so you can put
# your own numbers in and run it again. Sizes are decimal (1 TB = 10**12 bytes).
DAY = 86_400
PEAK = 3  # working hours concentrate the day's messages: the busiest hour against the daily average

DAILY_USERS = 20_000_000
WORKSPACES = 500_000
MESSAGES_EACH = 40  # messages a person sends in a working day
ONLINE_MEMBERS = 25  # members of a channel who are online when a message is posted, on average
DEVICES_EACH = 1.3
ONLINE_AT_PEAK = 0.6  # share of devices connected at the busiest hour
PER_GATEWAY = 70_000  # connections per gateway: 100,000 it can hold, run at 70 %
MESSAGE_BYTES = 1_000  # a message as stored: text, mentions, reactions and edits with their metadata
REPLICAS = 3
APP_EVENTS_EACH = 0.5  # events sent to installed apps per message, on average

per_day = DAILY_USERS * MESSAGES_EACH
peak = per_day / DAY * PEAK
sockets = DAILY_USERS * DEVICES_EACH * ONLINE_AT_PEAK
year = per_day * MESSAGE_BYTES * 365

print("Team chat: the estimate sheet")
print(f"  Messages      {per_day / 10**6:,.0f} million a day: {per_day / DAY:,.0f}/s on average, {peak:,.0f}/s at the peak")
print(f"  Deliveries    {peak * ONLINE_MEMBERS:,.0f}/s at the peak, to {ONLINE_MEMBERS} online members per message")
print(f"  Connections   {sockets / 10**6:.1f} million at the peak, on {-(-sockets // PER_GATEWAY):,.0f} gateways of {PER_GATEWAY:,}")
print(f"  Storage       {per_day * MESSAGE_BYTES / 10**9:,.0f} GB a day, {year / 10**12:,.0f} TB a year, {year * REPLICAS / 10**12:,.0f} TB with {REPLICAS} replicas, kept for good")
print(f"  App events    {peak * APP_EVENTS_EACH:,.0f}/s at the peak, signed, retried, limited per workspace")
print(f"  A workspace   {DAILY_USERS / WORKSPACES:,.0f} people and {per_day / WORKSPACES:,.0f} messages a day on average, a mean that hides the giants")

Output

Team chat: the estimate sheet
  Messages      800 million a day: 9,259/s on average, 27,778/s at the peak
  Deliveries    694,444/s at the peak, to 25 online members per message
  Connections   15.6 million at the peak, on 223 gateways of 70,000
  Storage       800 GB a day, 292 TB a year, 876 TB with 3 replicas, kept for good
  App events    13,889/s at the peak, signed, retried, limited per workspace
  A workspace   40 people and 1,600 messages a day on average, a mean that hides the giants

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 team_chat_sheet.py

The sheet shows a different balance from consumer chat. Messages are few, 27,778 a second at the peak, but each reaches 25 online members on average, so deliveries reach 694,444 a second, and history kept for good grows by 292 TB a year before replication. The average workspace, 40 people and 1,600 messages a day, describes almost none of them: a few giants carry most of the load, and the design has to survive them. Discord’s engineers met the same skew in storage: they partitioned messages by channel and a time bucket sized from their largest channels (Discord).

Checkpoint

Check the estimate

  1. Question 1 of 2 20 million people each post 40 messages in a working day, and the busiest hour runs at three times the daily average. How many messages a second is that at the peak?

    Type a number.

    A hint

    A day has 86,400 seconds.

    Show the answer: Question 1 of 2

    Answer: 27778 messages a second (anything from 25000 to 30556 counts)

    20,000,000 × 40 = 800 million messages a day; ÷ 86,400 ≈ 9,259 a second on average, and × 3 ≈ 27,778 a second at the peak.

  2. Question 2 of 2 At the peak of 27,778 posts a second, each post reaches 25 online members. How many deliveries a second?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 694444 deliveries a second (anything from 625000 to 763888 counts)

    27,778 × 25 ≈ 694,444 deliveries a second. Team chat posts fewer messages than a consumer messenger, but each one fans out to more people.

The first design

Team chat design: a message API checks permissions and stores, channel servers fan out to gateways, a log feeds search and apps.Members' appsMessage APIper workspacePermissionsroles, overwrites,membershipsMessage store(channel, bucket), seqChannel serversone owner per channelGatewayssubscribed to channelsChange logSearchindexes routedby workspaceIntegrationssigned events,rate limits1. post2. may post here?3. number, store4. to the channel's owner5. fan out6. deliver7. change eventindexeventssearch, filteredby permissions

The write path, the fan-out path and the change log of team chat

Text description of the diagram

Members' apps connect to gateways and call the message API of their workspace.

  1. An app posts a message to the message API.
  2. The API asks the permissions service whether this member may post in this channel, from the workspace's roles, the channel's overwrites and its memberships.
  3. It gives the message the channel's next sequence number and stores it in the message store, whose partitions are keyed by channel and bucket.
  4. It hands the message to the channel's owner, one of the channel servers, chosen by the channel's id.
  5. The channel server fans the message out to every gateway that has subscribed to the channel on behalf of its connected members.
  6. Each gateway delivers it to the members' apps.
  7. Every stored change also goes to a change log, which feeds the search indexes, routed by workspace, and the events that integrations receive, signed and rate-limited.

A dashed arrow shows members' apps querying search, whose results are filtered by the searcher's permissions.

Follow one post through it. The message API checks the member’s permission to post in the channel, gives the post the channel’s next sequence number and stores it. The channel’s owner, one channel server picked by the channel’s id, sends it once to every gateway that subscribed to that channel, and each gateway delivers it to its connected members. The stored change goes to a log, which feeds the search index and the events that apps receive. Step through it:

Interactive · step by step One post through the first design Step through one post in a busy channel, from the member's app to the people online and to search.
One post through the first design, step 7 of 7. Showing Member's app, Message API (may this member post?), Message store (stored with its seq), Channel server, Change log, Gateways, Search and apps, Members online. In focus: Change log, Search and apps.Member's appMessage APImay this member post?Message storestored with its seqChannel serverthe channel's ownerChange logGatewayssubscribed to the channelSearch and appsMembers onlineindex and notify

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. A post arrives. A member posts in a channel of a workspace. The request names the workspace and the channel, as every request does.
  2. Checked first. The message API checks that this member may post in this channel. A post that fails the check is refused here and goes nowhere else.
  3. Numbered and stored. The post gets the channel's next sequence number and is stored before anything is delivered, so nothing reaches anyone that could later be lost.
  4. To the channel's owner. The API hands the post to the channel's owner, the one channel server that a hash of the channel id picks.
  5. Once per gateway. The owner sends the post once to every gateway that subscribed to the channel, not once per member.
  6. Delivered locally. Each gateway delivers the post to its own connected members. At the peak a post reaches 25 members online on average, which makes 694,444 deliveries a second.
  7. Search and apps read the log. The stored change goes to a change log, which feeds the search index and the events that apps receive. A slow index or a slow app never delays a delivery.

The questions this design has to answer:

  • How are workspaces, channels, roles and threads stored, and how large may a channel’s partition grow?
  • How does one post reach 10,000 online members without 10,000 sends from one server?
  • How do roles and channel overwrites combine, and in which order?
  • What stops a member removed from a private channel from seeing the next post?
  • What do presence and typing cost in a community of 100,000, and how is that cut?
  • How is search laid out for 500,000 workspaces, and how does it respect permissions?
  • How do apps receive events safely, and what keeps one app or one workspace from hurting the rest?

Most of these come down to the same discipline: every request carries its workspace, and every limit is counted per workspace.

Checkpoint

Check the first design

  1. Question 1 of 2 Which of these must happen before a post is fanned out to members' gateways?

    Choose every answer that is right.

    Show the answer: Question 1 of 2

    Answer:

    • Giving the post the channel's next sequence number
    • Storing the post
    • Checking that the author may post in the channel

    The post is checked, numbered and stored first, so nothing is delivered that was not allowed or could be lost. Search and apps read the change log afterwards; a slow index or a slow app must never delay delivery.

  2. Question 2 of 2 The search cluster is slow today and indexes new posts a minute late. What happens to the delivery of a new post?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Nothing changes; delivery goes from the store to the channel's owner, and search reads the change log on its own

    The message API stores the post and hands it to the channel's owner, which fans it out; the stored change also goes to a log that search and apps read. Their delays show up as late search results, never as late posts.

Workspaces, channels, roles and threads as data Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • Messages partitioned by channel and bucket, with sizes
  • Channel servers: one owner per channel, fan-out to gateways
  • Permissions: roles, overwrites and their order, in code
  • Removing someone from a private channel while posts are in flight
  • Huge communities: presence and typing, measured
  • Search that respects channel permissions, with the shards counted
  • Apps and webhooks: signed events, retries and limits per workspace
  • Failure drills, from a lost channel server to an @everyone
  • Bottlenecks at 10× and 100×, and the designs rejected
  • The deep-dive questions, answered
  • Expectations by level, and a practice round
  • Practise: the last check before search results are shown
    • Filter search hits by workspace and channel access
  • Interview questions
    • Why is the workspace the first thing to design in team chat?
    • Someone posts @everyone in a community of 800,000 members, and notification delivery falls behind for every workspace for twenty minutes. What happened, and how do you design mentions so that one workspace cannot do this again?
    • An employee is removed from a private incident channel. A message posted a second later still reaches her laptop, and the next morning she finds another one in search. Find every path that let this happen, and fix them so that none can.
    • Your team chat has 500,000 workspaces, from three people to 200,000, and all history is searchable. Design the search index layout and the permission filter, and say what you do when one company's index outgrows its shards.
  • Key takeaways

4 diagrams · 3 runnable examples (JavaScript, Python) · 1 exercise with sample tests · 3 interview answers · about 51 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Design a chat app like WhatsApp: delivery

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.