A production-grade real-time chat & messaging platform — the delivery engine behind a Slack/WhatsApp-style app, built as a senior-backend portfolio piece.
The product is the delivery engine, not the chat-bubble UI.
Every messaging product sits on a system that gets a message from one device to everyone else's — instantly, in order, exactly once, and never lost — even when devices are offline, networks flap, and a user has five devices. The chat UI is a commodity; the delivery guarantees underneath are the hard part, and the part this project is about:
- Strict per-conversation ordering — a server-assigned monotonic
seqis the source of truth (never wall-clock). - Exactly-once display — at-least-once delivery + idempotent client dedup on
clientMsgId. - No lost messages — durably persisted before the sender is acked; offline devices catch up on reconnect.
- Horizontal scale — stateful WebSocket pods with cross-pod fan-out via Redis; survives pod loss.
This is a distributed-systems project wearing a chat app's clothes.
| Phase | 4 — flagship: AI assist ✅ (Day 13 of 15) · Phases 0–4 complete |
| Shipped | auth · conversations · messaging (seq, exactly-once) · optimistic send · history + sync · presence/typing/receipts · multi-pod Redis fan-out (nginx LB) · pod-kill zero-loss · Kafka durable log · backoff+jitter reconnect · graceful drain · direct-to-blob media (MinIO) · push: outbox + Kafka consumer, deduped, FCM drop-in · AI assist: summarize + smart replies (provider-agnostic; Groq/Ollama drop-in, stub fallback) · ⭐ async AI moderation (3rd Kafka consumer) + summary caching + rate-limit · dockerized · light/dark |
| Next | Day 14–15 — deploy & productize (Phase 5) |
Full milestone table → docs/requirement-execution-plan/.
Angular client ──WSS/STOMP + REST──► ┌── API tier (stateless: auth, convos, history) ──► Postgres
(RxJS streams) └── WS tier (stateful: send/deliver/receipts)
│ assign seq · persist · ack · fan-out
▼
Redis (Pub/Sub fan-out · presence) · Kafka (durable log)
Deep dive → docs/ARCHITECTURE.md.
| Path | What | Stack |
|---|---|---|
backend/ |
The delivery engine | Java 21 · Spring Boot 3.4 · Maven |
frontend/ |
The client that proves the guarantees | Angular 20 · RxJS · signals |
infra/ |
Local dev infrastructure | docker-compose (Postgres + Redis) |
docs/ |
Design, ADRs, the phased plan, and build/deploy runbooks | Markdown |
Ports avoid a native Postgres (5432) and Apache (8080) on the dev machine. Postgres → 5433 · Redis → 6379 · Backend → 8081 · Frontend → 4200.
Option A — everything in Docker (one command):
docker compose -f infra/docker-compose.yml up -d --build
# Postgres + Redis + backend (Spring Boot) + frontend (nginx) all come up.Option B — infra in Docker, apps on the host (hot-reload for dev):
docker compose -f infra/docker-compose.yml up -d postgres redis # just the datastores
cd backend && mvn spring-boot:run # API → http://localhost:8081
cd frontend && npm install && npm start # web → http://localhost:4200Open http://localhost:4200 → register → land on the home page showing your /me profile.
(Inside Docker the backend reaches the DB as postgres:5432; the browser hits the published localhost:8081.)
API smoke test (curl)
curl -X POST http://localhost:8081/v1/auth/register -H "Content-Type: application/json" \
-d '{"username":"alice","displayName":"Alice","password":"password123","platform":"WEB"}'
# response carries accessToken → call /me with it:
curl http://localhost:8081/v1/users/me -H "Authorization: Bearer <accessToken>"All engineering docs live in docs/:
| Doc | What |
|---|---|
| ARCHITECTURE.md | How the system works — components, send/sync paths, the invariants |
| DEPLOYMENT-ARCHITECTURE.md | Deploy strategy — two-tier rollout, the stateful WS-tier drain, CI/CD, scaling, DR |
| data-model.md · wire-protocol.md | Domain/schema · REST + STOMP contract |
| adr/ | 12 Architecture Decision Records (every load-bearing trade-off) |
| requirement-execution-plan/ | The phased build plan (what/why) |
| step-by-step-implementation/ | Build + deploy runbooks (the how) |
MIT.