Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save nito-Q/b8bbd188059b5a17bac786f5aa3e771a to your computer and use it in GitHub Desktop.

Select an option

Save nito-Q/b8bbd188059b5a17bac786f5aa3e771a to your computer and use it in GitHub Desktop.
Design Slack (Frequently Asked at OpenAI, DataBricks & Meta)

Design Slack: System Design Interview Solution (Asked at OpenAI, Meta & Databricks)

This is a high-level outline of a complete system design solution that helped a candidate pass the OpenAI system design interview round. It covers requirements gathering, API design, architecture, and key technical decisions for building a Slack-like messaging platform. There's also a link to a video walkthrough below for those that prefer that format to reading.


Problem Statement

Design a Slack-like messaging product scoped to a 2-week MVP for corporate teams, focusing on internal company communication with channels, direct messages, threads, file sharing, and real-time delivery.

Clarifying Questions & Assumptions

User Base & Geography:

  • Primary users: Corporate teams for internal communication
  • Initial deployment: Single region (Europe or North America)
  • Multi-tenant product: Multiple independent companies, each with isolated workspaces
  • Two role types: workspace members (read/post) and workspace admins (manage channels/users)

Scale Assumptions:

  • ~5,000 total users across all workspaces
  • Up to 1,000 fully active concurrent users at peak
  • 20,000-30,000 messages per hour at peak (~300-500 messages/minute)
  • Read-heavy system: ~10:1 read-to-write ratio due to channel broadcast effect
  • File uploads: 50 MB cap per file, few thousand uploads daily
  • Worst-case file transfer: ~25 GB/minute if every peak message had max-size file

Phase 1: Requirements

Functional Requirements

ID Tag Requirement Description
FR-1 MUST DO Workspaces and admin controls Isolated workspaces. Admins can create/archive channels, invite/remove members, deactivate accounts.
FR-2 MUST DO Channels Create, browse, join, leave public channels. Any workspace member can read any public channel.
FR-3 MUST DO Direct Messages Private 1-to-1 messages between workspace members.
FR-4 MUST DO Messaging Send and read messages in channels and DMs. Fetch history with cursor-based pagination.
FR-5 MUST DO Threads Reply to any channel message, creating threads. Many threads per channel. Replies not echoed to main channel.
FR-6 MUST DO File uploads Upload/view files in channels, DMs, threads. 50 MB cap. 30-day retention minimum.
FR-7 MUST DO Near-real-time delivery Online users receive new messages promptly via push-based delivery to web client.
FR-8 MUST DO In-app notifications Web app notifications for @mentions and thread replies. Thread followers: root author + prior repliers.
FR-9 SHOULD DO Email notifications Email for mentions/DMs when user inactive (simple heuristic).
FR-10 NICE TO HAVE Additional chat UX Reactions, typing indicators, read receipts, presence. All deferred.

Non-Functional Requirements

ID Tag Requirement Details
NFR-1 MUST DO Availability 99.9% monthly (≤43 min downtime/month). Single-region with AZ redundancy.
NFR-2 MUST DO Latency Message send p99 ≤200ms, fetch p99 ≤300ms.
NFR-3 MUST DO Durability Messages/files/metadata persisted durably. RPO ~1 minute acceptable.
NFR-4 MUST DO Security All external traffic TLS encrypted. Every request authenticated. Server-side access control. Rate limiting and payload limits.
NFR-5 SHOULD DO Observability Logs, metrics, alerts for latency, errors, file uploads, delivery lag.
NFR-6 MUST DO Scalability Handle 5K users, 1K concurrent peak, 300-500 msg/min, associated reads/notifications, few thousand daily file uploads.

Out of Scope

  • Full-text search and message indexing
  • Voice and video calling
  • Bots, third-party integrations, webhooks
  • Single Sign-On (SSO)
  • Advanced permissions (channel moderators, guest accounts, compliance controls)
  • Presence, typing, read receipts
  • Native mobile push notifications (APNS/FCM)
  • File retention beyond 30 days
  • Multi-region active-active deployment

📺 Want More Depth?

In case you're looking for more handholding see the below video and deep dive tutorial walkthroughs:


Phase 2: First-Class Entities

Entity Description
Workspace Top-level container for a company. Every entity scoped to a workspace.
User Member of one or more workspaces. Has role per workspace: member or admin.
Channel Named group conversation within workspace. Public by default for MVP.
DmConversation Private 1-to-1 conversation between two workspace members.
Message Single message in Channel or DmConversation. Has conversation_id and optional thread_root_id for replies.
FileRecord Metadata for uploaded file: uploader, workspace, storage URL, size, MIME type, expiry. Bytes in object storage.
Notification Persisted in-app notification for mention or thread reply, owned by recipient.

Phase 3: API Design

Approach

REST over HTTPS: Stateless, universally supported, fits request-response traffic. All responses JSON. JWT bearer tokens in Authorization header. API Gateway validates JWT signature and extracts user_id; downstream services perform authorization checks against workspace/channel membership.

Pagination: Opaque cursor (not page numbers) encoding position in result set. Stable under concurrent data changes.

Idempotency: Client-generated idempotency_key (UUID) on message sends. Server deduplicates retries.

Key Endpoints

Workspaces & Admin

POST   /workspaces
POST   /workspaces/{ws_id}/members
PATCH  /workspaces/{ws_id}/members/{user_id}

Channels

GET    /workspaces/{ws_id}/channels
POST   /workspaces/{ws_id}/channels

Direct Messages

GET    /workspaces/{ws_id}/dms
POST   /workspaces/{ws_id}/dms
GET    /workspaces/{ws_id}/dms/{dm_id}/messages
POST   /workspaces/{ws_id}/dms/{dm_id}/messages

Messages & Threads

GET    /channels/{channel_id}/messages
POST   /channels/{channel_id}/messages
GET    /channels/{channel_id}/messages/{root_id}/replies
POST   /channels/{channel_id}/messages/{root_id}/replies

Files

POST   /files        # Request pre-signed upload URL
GET    /files/{file_id}

Example: Send a Message

Request:

POST /channels/{channel_id}/messages
Authorization: Bearer eyJ...
Content-Type: application/json

{
  "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
  "text": "Has anyone reviewed the spec?",
  "file_id": null
}

Response (HTTP 201):

{
  "message_id": "msg_01abc",
  "conversation_id": "ch_xyz",
  "sender_user_id": "usr_123",
  "text": "Has anyone reviewed the spec?",
  "created_at": "2025-03-15T09:41:00Z",
  "thread_root_id": null,
  "file": null
}

Phase 4: High-Level Architecture

Architectural Pattern

Event-driven microservices architecture. Each service owns bounded responsibility, communicates via synchronous REST (user-facing) or asynchronous events (background work). Services are stateless where possible—no in-memory user/session state, all persistence delegated to database/cache/storage. Stateless services scale horizontally without coordination.

Deployment: Single-region with availability zone redundancy. Regional load balancer provides 99.9% availability target without multi-region complexity.

Components

A) Web Client Browser-based UI (React + TypeScript) for channels, DMs, threads, files, notifications. Only client surface for MVP. Speaks REST APIs and WebSocket.

B) Regional Load Balancer Accepts HTTPS traffic, terminates TLS, performs health checks, distributes across API Gateway instances. After TLS termination, traffic stays on provider's private network. Technology: AWS ALB or GCP Load Balancer.

C) API Gateway Single entry point. Validates JWTs, enforces rate limits (e.g., 1 msg/sec per user, lower on auth endpoints), routes to services. Extracts user_id from token for downstream. Technology: AWS API Gateway or Kong.

D) Auth Service Issues JWT session tokens on login. Provides public key endpoint for gateway verification. No per-request round trip needed. Technology: JWT with RS256 signing.

E) Chat Service Authoritative backend for channels, DMs, messages, threads. Only service writing messages. On send: (1) check authorization, (2) insert message in transaction with idempotency constraint, (3) commit, (4) publish MessageCreated event, (5) return HTTP 201. Technology: Go or Node.js.

F) File Service Manages pre-signed upload flow. On POST /files: validates metadata (size ≤50MB, allowed MIME types), creates FileRecord, returns pre-signed upload URL to object storage. Client uploads bytes directly. On GET /files/{file_id}: returns metadata and signed download URL. Technology: Go or Node.js.

G) PostgreSQL: Primary Database Single durable store for all application data: users, workspaces, memberships, channels, DMs, messages, threads, files, notifications. Fully relational with foreign keys. ACID transactions for idempotency and consistency. WAL + streaming replication to standby in different AZ for durability. Supports native partitioning (by created_at) and horizontal scaling via Citus extension for future growth. Technology: PostgreSQL 15+.

H) Object Storage Stores raw file bytes. File Service generates pre-signed URLs for direct client upload/download. Lifecycle rules auto-delete files after 30 days based on central FILE_RETENTION_DAYS config. Technology: AWS S3 or GCS.

I) Realtime Delivery Service Maintains persistent WebSocket connections. Each instance holds in-memory map: connection_id → { user_id, subscribed_conversation_ids }. On MessageCreated event from bus, pushes to local connections subscribed to that conversation. Verifies user access before accepting subscriptions. Technology: Go (goroutine model) or Node.js with ws library.

J) Event Bus: Redis Pub/Sub Decouples Chat Service write path from consumers. After committing message, Chat Service publishes MessageCreated. Realtime Delivery and Notification Service both subscribe independently. No event durability (acceptable for MVP; messages durable in PostgreSQL). Broadcast to all Realtime instances; each checks local subscribers. Technology: Redis Pub/Sub.

K) Notification Service Subscribes to event bus. On MessageCreated: (1) identifies recipients (mentioned users + thread followers), (2) writes Notification records, (3) enqueues email jobs if recipients inactive, (4) publishes NotificationCreated for in-app push. Technology: Go or Node.js.

L) Async Queue & Workers: Redis-backed Job Queue Runs background jobs (email sending). Notification Service enqueues jobs; workers pick up, call email provider, retry with exponential backoff. Dead-letter queue for exhausted retries. Technology: Redis-backed job queue library.

M) Observability Prometheus (metrics scraping), Grafana (dashboards + alerts), Sentry (exception tracking), structured logs to CloudWatch/Datadog. Off-the-shelf tools, minimal setup.

Core Flows

Flow A: Send a Channel Message

  1. Client sends POST /channels/{channel_id}/messages with {idempotency_key, text, file_id} + JWT
  2. Load balancer routes to API Gateway
  3. API Gateway validates JWT, extracts user_id, enforces rate limits, forwards to Chat Service
  4. Chat Service checks workspace membership and channel access
  5. Chat Service begins transaction, inserts message (unique constraint on (sender_user_id, idempotency_key)), commits
  6. Chat Service publishes MessageCreated to event bus (fire-and-forget)
  7. Chat Service returns HTTP 201 with message object
  8. Realtime Delivery Service receives event, pushes to subscribed WebSocket connections
  9. Notification Service receives event, writes notifications, enqueues emails if needed

Flow B: Load a Channel Timeline

  1. Client sends GET /channels/{channel_id}/messages?limit=50&before=<cursor>
  2. API Gateway validates token, forwards to Chat Service
  3. Chat Service verifies channel access, runs paginated index scan on messages table, returns 50 messages + cursor
  4. Client establishes/maintains WebSocket connection, subscribes to channel for future messages

Flow C: Upload File & Attach to Message

  1. Client sends POST /files with metadata (filename, content_type, size)
  2. File Service validates (size ≤50MB, allowed type), creates FileRecord, returns pre-signed upload URL + file_id
  3. Client PUTs file bytes directly to pre-signed URL (object storage)
  4. Client sends POST /channels/{channel_id}/messages with file_id attached
  5. Chat Service writes message referencing file_id, proceeds through normal send flow (Flow A)

Flow D: Real-time Notification Delivery

  1. Message committed, MessageCreated published to event bus
  2. Notification Service receives event. For mention: writes Notification per mentioned user. For thread reply: queries messages table for thread root author + prior repliers, writes Notification per recipient (excluding sender)
  3. Notification Service publishes NotificationCreated event
  4. Realtime Delivery Service receives event, pushes to affected users' WebSocket connections
  5. Client updates notification badge and inbox without fetch
  6. If recipient inactive, Notification Service enqueues email job; worker delivers via external provider

Degradation Behaviour

Failure Result User Experience
Realtime Delivery unavailable Messages persist, readable via fetch API Users see messages on reconnect; core chat unaffected
Notification Service down Messaging continues In-app notifications delayed/missed; messages visible via fetch; email delivery paused
Redis queue/email worker down In-app notifications work Email delivery pauses; jobs in DLQ for replay
File Service unavailable File upload/download fail Channel/DM messaging continues uninterrupted
PostgreSQL unavailable Core chat stops Hot standby in separate AZ with automatic failover; must alert immediately

Technology Summary

Component Technology Key Rationale
Web client React, TypeScript Component model suits chat UI; type safety catches API errors
Load balancer AWS ALB / GCP LB Managed TLS, health checks, AZ redundancy
API Gateway AWS API Gateway / Kong Auth, rate limiting, routing via config
Auth Service JWT (RS256) Stateless verification at gateway
Chat Service Go / Node.js High concurrency, single authoritative writer
File Service Go / Node.js Independent scaling, pre-signed URLs
PostgreSQL PostgreSQL 15+ ACID, WAL durability, partitioning, Citus path
Object Storage S3 / GCS Lifecycle rules, pre-signed URLs
Realtime Delivery WebSockets (Go/Node.js) Full-duplex, universal support, efficient connections
Event Bus Redis Pub/Sub Lightweight fanout, pairs with cache/queue
Notification Service Go / Node.js Isolated failure domain
Async Queue Redis-backed queue Retries, DLQ, no separate broker
Observability Prometheus, Grafana, Sentry Off-the-shelf, industry standard

Key Design Decisions

Decision Choice Made Key Rationale
Architecture Pattern Event-driven microservices Clear service boundaries, independent scaling, isolated failures
Database PostgreSQL ACID for idempotency, WAL durability, partitioning + Citus for scale
Event Bus Redis Pub/Sub Lightweight fanout for MVP; also provides cache/queue; swappable for Kafka later
Threading Model Root-anchored (flat) O(1) pagination, simple notification recipient derivation
File Upload Pre-signed URLs Keeps bytes off app tier; scales independently
Auth JWT Stateless verification at gateway; no per-request Auth Service call
Pagination Cursor-based Stable under concurrent data changes (new messages arriving)
Idempotency Database unique constraint Safe under concurrent retries; no distributed coordination needed
Deployment Single-region + AZ redundancy Sufficient for agreed geography; achieves 99.9% without multi-region complexity
Real-time Delivery WebSockets Full-duplex, universal browser support, efficient for live features

Requirements Validation Checklist

Functional Requirements Coverage

✅ FR-1 Workspaces/admin: workspaces, workspace_memberships tables; admin role; channel/member management endpoints
✅ FR-2 Channels: channels, channel_memberships tables; Chat Service APIs; timeline index
✅ FR-3 DMs: dm_conversations table; unique constraint prevents duplicates; same message path as channels
✅ FR-4 Messaging: messages table; idempotency constraint; cursor pagination on (created_at, message_id)
✅ FR-5 Threads: Root-anchored via thread_root_id; flat fetch via thread index; multiple threads per channel
✅ FR-6 Files: file_records table; pre-signed URL pattern; 50MB cap; 30-day expiry via lifecycle rules
✅ FR-7 Real-time delivery: Realtime Delivery Service; WebSocket subscriptions; fanout on events; fetch-on-reconnect
✅ FR-8 In-app notifications: Notification Service; notifications table; thread follower derivation; push via WebSocket
✅ FR-9 Email notifications: Background worker; DLQ; enqueued by Notification Service on inactivity
✅ FR-10 Additional UX: Explicitly out of scope

Non-Functional Requirements Coverage

✅ NFR-1 Availability (99.9%): Stateless services + load balancer; AZ redundancy; hot standby PostgreSQL with failover
✅ NFR-2 Latency (send ≤200ms, fetch ≤300ms): Indexed lookups + single insert; post-commit event publish; compound indexes for timeline scans
✅ NFR-3 Durability (RPO ≤1 min): WAL-backed PostgreSQL; streaming replication to standby
✅ NFR-4 Security: JWT auth at gateway; server-side membership checks; rate limiting; payload caps
✅ NFR-5 Observability: Prometheus, Grafana, Sentry, structured logs
✅ NFR-6 Scalability (5K users, 1K concurrent, 300-500 msg/min): Stateless horizontal scaling; PostgreSQL has 1000x headroom over peak; pre-signed URLs for files


Data Model Highlights

Critical Tables

messages

message_id        UUID PRIMARY KEY
workspace_id      UUID NOT NULL REFERENCES workspaces(workspace_id)
conversation_id   UUID NOT NULL
conversation_type TEXT CHECK (conversation_type IN ('channel', 'dm'))
sender_user_id    UUID NOT NULL REFERENCES users(user_id)
text              TEXT NOT NULL
file_id           UUID REFERENCES file_records(file_id)
thread_root_id    UUID REFERENCES messages(message_id)
idempotency_key   UUID NOT NULL
created_at        TIMESTAMPTZ NOT NULL DEFAULT now()
UNIQUE (sender_user_id, idempotency_key)

workspace_memberships

workspace_id UUID NOT NULL REFERENCES workspaces(workspace_id)
user_id      UUID NOT NULL REFERENCES users(user_id)
role         TEXT CHECK (role IN ('member', 'admin'))
created_at   TIMESTAMPTZ NOT NULL DEFAULT now()
PRIMARY KEY (workspace_id, user_id)

dm_conversations

dm_id        UUID PRIMARY KEY
workspace_id UUID NOT NULL REFERENCES workspaces(workspace_id)
user_a_id    UUID NOT NULL REFERENCES users(user_id)
user_b_id    UUID NOT NULL REFERENCES users(user_id)
created_at   TIMESTAMPTZ NOT NULL DEFAULT now()
CHECK (user_a_id < user_b_id)
UNIQUE (workspace_id, user_a_id, user_b_id)

Critical Indexes

-- Channel timeline (partial index)
CREATE INDEX idx_messages_channel_timeline
ON messages (conversation_id, created_at DESC, message_id DESC)
WHERE conversation_type = 'channel';

-- Thread fetch (partial index, ascending for top-to-bottom read)
CREATE INDEX idx_messages_thread
ON messages (thread_root_id, created_at ASC, message_id ASC)
WHERE thread_root_id IS NOT NULL;

-- Notification inbox (partial index for unread only)
CREATE INDEX idx_notifications_inbox
ON notifications (recipient_user_id, created_at DESC)
WHERE read_at IS NULL;

-- Thread follower derivation (for Notification Service)
CREATE INDEX idx_messages_thread_root_sender
ON messages (thread_root_id, sender_user_id)
WHERE thread_root_id IS NOT NULL;

Key Trade-offs

Root-anchored threads (flat) vs. nested trees
✅ Single index scan for fetch; identical pagination to channels; simple notification recipient query
⚠️ Cannot natively model "reply to specific reply" (can add optional in_reply_to_message_id later)

Unified message table with polymorphic conversation reference
✅ Channels and DMs share schema, pagination, notification pipeline; extensible to new conversation types
⚠️ Discriminator column slightly less clean than separate tables

Best-effort event publish (post-commit) with fetch-on-reconnect recovery
✅ Keeps write path simple and fast; missed events recoverable via fetch
⚠️ Real-time delivery not guaranteed; upgrade path is outbox pattern (commit event record in same transaction, background dispatcher publishes)

Pre-signed URL file upload
✅ File bytes never touch app tier; uploads scale independently
⚠️ Two-step client flow; FileRecord created before bytes confirmed uploaded

Redis Pub/Sub as event bus
✅ Single Redis for eventing, queueing, caching; lightweight; sub-millisecond delivery
⚠️ No event durability (missed if subscriber down); swappable for Kafka when stronger guarantees needed

Single-region deployment with AZ redundancy
✅ Achieves 99.9% target without multi-region complexity; sufficient for agreed geography
⚠️ Full regional outage takes product down; second region is next availability milestone


For detailed deep dives covering:

  • Transaction anatomy and idempotency under concurrent retries
  • Data model design, indexes, and partitioning strategy
  • Real-time fanout scaling and subscription routing
  • Eventing reliability and the outbox pattern

See this tutorial


About This System Design Interview Problem

Problem: Design Slack (Real-time Messaging Platform)
Asked At: OpenAI, Databricks, Meta and other FAANG+ companies
Solution Type: Complete interview-ready answer with requirements, architecture, API design, and data modeling

What You'll Learn

This system design solution demonstrates how to approach real-time messaging systems in a 45-60 minute interview. The design covers:

  • Event-driven microservices architecture for scalable messaging
  • WebSocket implementation for real-time delivery
  • PostgreSQL data modeling with proper indexing strategies
  • Redis Pub/Sub for message fanout and caching
  • Idempotency patterns for reliable message delivery
  • Multi-tenant architecture for enterprise SaaS
  • Pre-signed URL patterns for file uploads at scale

Related System Design Interview Problems

If you're preparing for system design interviews at OpenAI, Meta, Google, or Amazon, you might also encounter:

  • Design WhatsApp/Facebook Messenger - Similar real-time messaging with mobile focus
  • Design Discord - Voice channels + text, gaming-optimized architecture
  • Design Google Docs - Collaborative editing with operational transforms
  • Design Twitter/X - Feed generation and real-time updates at massive scale
  • Design Zoom - Real-time video/audio with low latency requirements
  • Design Notification System - Push notifications across web/mobile/email

Interview Tips: How to Approach This Problem

If you get "Design Slack" or a similar messaging system in your OpenAI, Meta, or Google system design interview:

  1. Start with requirements gathering - Don't jump to architecture. Clarify scale, geography, and feature scope.
  2. Call out the read-heavy pattern - Messaging systems have 10:1 or higher read-to-write ratios due to channel fanout.
  3. Address real-time delivery explicitly - Explain WebSockets vs. SSE vs. polling trade-offs.
  4. Show idempotency awareness - Message duplication is a common failure mode; demonstrate you know how to prevent it.
  5. Think about multi-tenancy - Most enterprise messaging platforms serve multiple companies; show you understand data isolation.

Common follow-up questions interviewers ask:

  • "How would you handle message search?" (Full-text indexing, Elasticsearch)
  • "What if a user sends 1000 messages/second?" (Rate limiting, backpressure)
  • "How do you guarantee message ordering?" (Sequence numbers, vector clocks)
  • "What happens if Redis goes down?" (Degraded delivery, fetch-on-reconnect)

Get Truly Interview-Ready

Coditioning is your go-to platform for optimizing your chances of landing offers at Big Tech companies like OpenAI, Anthropic, Amazon, Meta, Google, Microsoft, Netflix, OpenAI, and Reddit.

We offer:

✅ Mock interviews (Human & AI) - Practice with engineers who've conducted real interviews at your target companies
✅ Personalized feedback - Get actionable insights on coding, system design, and behavioral interviews
✅ Learning resources - Complete system design solutions with step-by-step breakdowns
✅ Production engineering prep - Cover distributed systems, scalability, and infrastructure design

Start Preparing Today

🎯 Book a mock system design interview - Practice with experienced FAANG+ engineers
📚 Browse complete system design solutions - Real problems from OpenAI, Meta, Google, Amazon
📺 Watch free tutorials on YouTube - System design walkthroughs and interview tips


Keywords & Topics Covered

Core Concepts: system design interview, distributed systems, microservices architecture, event-driven design, real-time messaging, websocket architecture, database design, API design, scalability patterns, high availability systems

Interview Prep: openai interview, openai system design, meta system design interview, google system design interview, amazon system design interview, system design mock interview, faang interview preparation, big tech interviews, senior engineer interview, staff engineer interview

Technical Topics: postgresql optimization, redis pub/sub, cursor pagination, idempotency patterns, multi-tenant saas, message queues, load balancing, horizontal scaling, database sharding, caching strategies, rate limiting, jwt authentication

Problem Variations: design slack, design messaging app, design chat application, design real-time collaboration tool, design team communication platform, slack architecture, slack system design, messaging system architecture

Target Companies: openai interview questions, meta interview prep, google interview preparation, amazon system design, microsoft interview, netflix system design, reddit engineering interview, faang+ system design


Questions or feedback? Drop a comment on the YouTube video or reach out via Coditioning.com

Last updated: April 2025 | Based on real OpenAI interview experience | Free resource for interview preparation


Share This Resource

If you found this system design solution helpful:

  • ⭐ Star this gist
  • 🔗 Share with friends preparing for FAANG+ interviews
  • 📺 Subscribe to Coditioning on YouTube for more content
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment