Skip to content

Repository files navigation

Socket Talk - Real-Time Chat Application

A full-stack real-time messaging platform built with a microservices architecture. Users can send friend requests, chat one-on-one or in groups, and receive messages instantly via WebSockets. Messages are persisted asynchronously through a Redis-backed queue for high throughput and scalability.

Architecture Overview

┌───────────┐       ┌──────────────┐       ┌──────────────┐
│  Frontend  │◄─────►│  HTTP Server │◄─────►│  PostgreSQL  │
│  (React)   │       │  (Express)   │       │              │
└─────┬──────┘       └──────────────┘       └──────▲───────┘
      │                                            │
      │ WebSocket                                  │
      │                                            │
┌─────▼──────┐       ┌──────────────┐       ┌──────┴───────┐
│  WS Server │◄─────►│    Redis     │◄─────►│  DB Service  │
│    (ws)    │       │  (Pub/Sub +  │       │ (Queue Worker)│
└────────────┘       │   Queue)     │       └──────────────┘
                     └──────────────┘

How it works:

  1. The HTTP Server handles authentication, friend requests, chat CRUD, and serves the REST API.
  2. The WebSocket Server manages real-time connections. When a user sends a message, it publishes to Redis Pub/Sub for instant delivery to all participants and pushes the message onto a Redis queue.
  3. The DB Service (queue consumer) picks messages off the Redis queue and persists them to PostgreSQL, decoupling real-time delivery from database writes.
  4. Redis Pub/Sub enables horizontal scaling — multiple WS server instances can share messages across connections.

Tech Stack

Layer Technology
Frontend React, TypeScript, Vite, Tailwind CSS, Radix UI, React Query, React Router
HTTP Server Node.js, Express, TypeScript, JWT, bcrypt
WebSocket Server Node.js, ws library, Redis Pub/Sub
Database PostgreSQL 15, Prisma ORM
Message Queue Redis (List-based queue + Pub/Sub)
Queue Consumer Node.js worker service
Monorepo Turborepo, pnpm workspaces
Containerization Docker, Docker Compose, Kubernetes

Features

  • Real-Time Messaging — Instant message delivery via WebSocket connections with Redis Pub/Sub
  • Friend System — Send, accept, or reject friend requests; private chats auto-created on acceptance
  • Private & Group Chats — One-on-one conversations and group chats with role-based permissions (Owner, Admin, Member)
  • Group Invites — Invite friends to groups with 48-hour expiring invitations
  • Typing Indicators — See when someone is typing in real-time
  • Async Message Persistence — Messages are queued in Redis and batch-written to the database by a separate worker, keeping the WS server fast
  • Cursor-Based Pagination — Efficient infinite-scroll message history
  • User Profiles — Customizable profiles with bio, avatar, social links, interests, and location
  • JWT Authentication — Stateless auth shared across HTTP and WebSocket services
  • Responsive UI — Clean interface built with Tailwind CSS and Radix UI primitives

Project Structure

socket-talk/
├── apps/
│   ├── frontend/          # React + Vite SPA
│   ├── http-server/       # Express REST API
│   ├── ws-server/         # WebSocket server
│   └── db-service/        # Redis queue consumer worker
├── packages/
│   ├── prisma/            # Shared Prisma schema & client
│   ├── ui/                # Shared UI component library
│   ├── eslint-config/     # Shared ESLint config
│   └── typescript-config/ # Shared TypeScript config
├── k8s/                   # Kubernetes manifests
├── docker-compose.yml
└── turbo.json

Database Schema

User ─────┬──── Profile (1:1)
          ├──── Friend (many-to-many, bidirectional)
          ├──── FriendRequest (sender/receiver)
          ├──── ChatParticipant ──── Chat
          ├──── Message
          └──── GroupInvite

Chat ─────┬──── ChatParticipant (with roles: OWNER, ADMIN, MEMBER, GUEST)
          ├──── Message
          └──── GroupInvite (48hr expiry)

Getting Started

Prerequisites

  • Node.js >= 18
  • pnpm 9+
  • PostgreSQL 15
  • Redis

1. Clone and install

git clone https://github.com/<your-username>/socket-talk.git
cd socket-talk
pnpm install

2. Set up environment variables

Copy the example env files and configure them:

# Database connection
cp packages/prisma/.env.example packages/prisma/.env

# HTTP server
cp apps/http-server/.env.example apps/http-server/.env

# WebSocket server
cp apps/ws-server/.env.example apps/ws-server/.env

# DB service (queue consumer)
cp apps/db-service/.env.example apps/db-service/.env

# Frontend
cp apps/frontend/.env.example apps/frontend/.env

Environment variables:

Service Variable Default
Prisma DATABASE_URL postgresql://postgres:password@localhost:5432/postgres
HTTP Server PORT 3000
HTTP Server JWT_SECRET secret
WS Server JWT_SECRET secret
DB Service REDIS_URL redis://localhost:6379
Frontend VITE_BACKEND_URL http://localhost:3000/api/v1
Frontend VITE_WS_URL ws://localhost:3001

3. Set up the database

cd packages/prisma
npx prisma migrate dev

4. Start all services

# From the root directory
pnpm dev

This starts the HTTP server (:3000), WebSocket server (:3001), DB service worker, and frontend (:5173) concurrently via Turborepo.

Run with Docker Compose

docker compose up --build

This spins up PostgreSQL, Redis, all backend services, and the frontend in containers with health checks and persistent volumes.

API Endpoints

Method Endpoint Description
POST /api/v1/auth/register Register a new user
POST /api/v1/auth/login Login and receive JWT
GET /api/v1/users/profile Get current user profile
PUT /api/v1/users/profile Update profile
GET /api/v1/users/search/:username Search users by username
GET /api/v1/friends Get friend list
POST /api/v1/friends/requests/send/:userId Send friend request
GET /api/v1/friends/requests Get sent & received requests
PUT /api/v1/friends/requests/:requestId Accept or reject request
POST /api/v1/chats Create a chat (private or group)
GET /api/v1/chats Get user's chats
GET /api/v1/chats/:chatId/messages Get messages (cursor paginated)
POST /api/v1/chats/:chatId/invites Send group invite
GET /api/v1/invites Get pending group invites
PUT /api/v1/invites/:inviteId Accept or reject group invite

WebSocket Events

Event Direction Description
join_chat Client → Server Join a chat room
send_message Client → Server Send a message to a chat
typing_start Client → Server Notify others you're typing
leave_chat Client → Server Leave a chat room
receive_message Server → Client Receive a new message
typing Server → Client Someone is typing indicator

Message Flow

User sends message
       │
       ▼
  WS Server receives it
       │
       ├──► Redis Pub/Sub ──► All connected clients in the chat receive it instantly
       │
       └──► Redis Queue (db_update_message)
                   │
                   ▼
            DB Service (worker)
                   │
                   ▼
            PostgreSQL (message persisted + chat.lastMessageAt updated)

Kubernetes Deployment

The k8s/ directory contains manifests for deploying to a Kubernetes cluster:

  • PostgreSQL & Redis with persistent volume claims
  • HTTP Server (2 replicas) and Frontend (2 replicas) for high availability
  • DB Service (1 replica) as a queue consumer
  • Traefik Ingress routing / to frontend, /api to HTTP server, /socket to WS server
  • Secrets management via Kubernetes Secrets

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors