BlueprintHTTP + WS • Redis • DynamoDB

Beautifully crafted chat system design

A production‑ready architecture that blends stateless REST with realtime WebSockets, fan‑out via Redis, and high‑throughput storage on DynamoDB.

Transport
HTTP + WS
Datastore
DynamoDB
Fan‑out
Redis
Compute
EC2 clusters

High‑Level Architecture

HTTP for stateless CRUD and history. WebSocket for low‑latency, push‑based updates across clusters.

Infrastructure Diagram
Chat App Infrastructure Diagram showing HTTP/WS entries, EC2 clusters, DynamoDB, Redis, and S3.
Compute & Routing
  • HTTP LB distributes REST traffic across HTTP EC2 clusters.
  • WebSocket LB manages long‑lived connections for realtime.
  • HTTP EC2 handles user creation and message history.
  • WS EC2 keeps persistent sessions for low latency.
Data Storage
  • DynamoDB: fast, scalable reads/writes for users, rooms, messages, and relations.
Realtime Fan‑out
  • Redis stores WS connection IDs and broadcasts across WS nodes for cross‑server delivery.
Dual entry points
HTTP for REST, WS for push. Best of both worlds for UX and scalability.
Separation of duties
Stateless APIs on HTTP nodes. Stateful connections on WS nodes.
Resilient broadcast
Redis enables cross‑node delivery even when users land on different WS hosts.

Data Structures

Client-side state for different components

User basic data

type User = {
  id: string, // unique identifier of the user
  name: string, // a name of the user shown on the UI
  avatar?: string, // the image representation of the user
}

Interfaces

HTTP API endpoints and WebSocket actions.

RESTGet users, create users, fetch room messages.
GET/users
Get users you can create a room with.
Response
[
  { "id": "user_123", "name": "Alice", "avatar": "https://example.com/avatar/alice.png" },
  { "id": "user_456", "name": "Bob",   "avatar": "https://example.com/avatar/bob.png" }
]
POST/users
Create a new user.
Payload
{
  "name": "Alice",
  "avatar": "https://example.com/avatar/alice.png"
}
Response
{
  "id": "user_123",
  "name": "Alice",
  "avatar": "https://example.com/avatar/alice.png"
}
GET/rooms/{room_id}/messages
Get message history of a room.
Response
[
  {
    "roomId": "room_456",
    "messageId": "msg_001",
    "content": "Hello!",
    "senderId": "user_123",
    "createdAt": "2024-06-16T12:34:56.789Z",
    "status": "success"
  },
  {
    "roomId": "room_456",
    "messageId": "msg_002",
    "content": "Hi!",
    "senderId": "user_456",
    "createdAt": "2024-06-16T12:35:12.000Z",
    "status": "success"
  }
]
WebSocketCreate rooms and messages, broadcast to online users.
WSaction: create_room
Create a room via WebSocket and notify participants.

Can also be modeled as HTTP + SSE if WS is not preferred.

Payload
{
  "action": "create_room",
  "participants": ["user_123", "user_456"]
}
Response
{
  "type": "room_created",
  "room": {
    "id": "room_456",
    "participants": [
      { "id": "user_123", "name": "Alice" },
      { "id": "user_456", "name": "Bob" }
    ],
    "createdAt": "2024-06-16T12:36:00.000Z"
  }
}
WSaction: create_message
Create a message and broadcast to the room.
Payload
{
  "action": "create_message",
  "roomId": "room_456",
  "messageId": "msg_003", // client-generated UUID
  "content": "How are you?",
  "senderId": "user_123",
  "createdAt": "2024-06-16T12:36:10.000Z"
}
Response
{
  "type": "message_created",
  "message": {
    "roomId": "room_456",
    "messageId": "msg_003",
    "content": "How are you?",
    "senderId": "user_123",
    "createdAt": "2024-06-16T12:36:10.000Z",
    "status": "success"
  }
}
Tip

Room creation can also be modeled as HTTP + SSE if WebSocket is not preferred for that flow.

Ready to build the chat experience?

Use this blueprint as your starting point and adapt to your product needs.