Distributed real-time chat platform powered by Spring Boot microservices, Kafka, Redis, PostgreSQL, WebSockets, Docker, and Kubernetes.
ConvoMesh models the shape of a production-style messaging system. Messages enter through a gateway, move through WebSocket and Kafka-driven services, fan out through Redis-backed pub/sub, and land in connected clients in real time.
- Real-time messaging over STOMP + SockJS
- Event-driven communication with Kafka
- Multi-instance WebSocket delivery with Redis pub/sub
- Persistent message storage with PostgreSQL
- API routing with Spring Cloud Gateway
- Containerized services with Docker
- Local orchestration with Kubernetes and Minikube
- Fault-tolerant behavior you can actually demo locally
| Category | Details |
|---|---|
| Architecture | Microservices + event-driven messaging |
| Runtime | Java 17, Spring Boot, Spring Cloud Gateway |
| Messaging | Kafka, Redis |
| Persistence | PostgreSQL |
| Realtime | WebSocket, STOMP, SockJS |
| Infra | Docker, Kubernetes, Minikube |
| Frontend | Static HTML, CSS, JavaScript |
If you just want the fastest happy path, run these from the repo root:
minikube start --driver=docker
kubectl config use-context minikube
eval $(minikube docker-env)
cd Auth-Service && docker build -t auth-service:latest .
cd ../Chat-Service && docker build -t chat-service:latest .
cd ../websocket-service && docker build -t websocket-service:latest .
cd ../Notification-service && docker build -t notification-service:latest .
cd ../Gateway && docker build -t gateway:latest .
cd ..
docker pull postgres:latest
docker pull redis:latest
minikube image load postgres:latest
minikube image load redis:latest
kubectl apply -f k8s/
minikube service gateway --urlThen:
cd frontend
python3 -m http.server 5500Open http://127.0.0.1:5500, paste the gateway URL from minikube service gateway --url into the frontend, and connect.
Browser client
|
v
Gateway (Spring Cloud Gateway)
|
+--> Auth Service
+--> Chat Service
+--> WebSocket Service
|
v
Kafka
|
v
Notification Service
|
v
Redis Pub/Sub
|
v
WebSocket Service replicas
|
v
Connected clients
| Service | Port | Responsibility |
|---|---|---|
gateway |
8080 |
Single entry point for external HTTP and WebSocket traffic |
auth-service |
8081 |
Authentication-related endpoints |
chat-service |
8082 |
Message persistence and chat APIs |
websocket-service |
8083 |
STOMP endpoint and chat message publishing |
notification-service |
8084 |
Kafka consumer and broadcast coordination |
postgres |
5432 |
Persistent storage |
redis |
6379 |
Cross-instance pub/sub |
zookeeper |
2181 |
Kafka coordination |
kafka |
9092 |
Event streaming backbone |
- Java 17
- Spring Boot
- Spring Cloud Gateway
- Spring WebSocket
- Apache Kafka
- Redis
- PostgreSQL
- Docker
- Kubernetes
- Minikube
Auth-Service/
Chat-Service/
Gateway/
Notification-service/
websocket-service/
frontend/
k8s/
docker-compose.yml
Install these before running the project:
- Java 17
- Docker Desktop
- Kubernetes CLI (
kubectl) - Minikube
- Python 3
This is the recommended local setup if you want the full distributed workflow.
minikube start --driver=docker
kubectl config use-context minikube
kubectl cluster-infoIf you previously had a broken local cluster, reset it first:
minikube stop
minikube delete
minikube start --driver=dockerBuild the application images inside Minikube's Docker environment so Kubernetes can use them directly.
eval $(minikube docker-env)Run these commands from the repository root:
cd Auth-Service && docker build -t auth-service:latest .
cd ../Chat-Service && docker build -t chat-service:latest .
cd ../websocket-service && docker build -t websocket-service:latest .
cd ../Notification-service && docker build -t notification-service:latest .
cd ../Gateway && docker build -t gateway:latest .
cd ..The Kubernetes manifests for PostgreSQL and Redis use imagePullPolicy: Never, so those images must exist inside Minikube.
docker pull postgres:latest
docker pull redis:latest
minikube image load postgres:latest
minikube image load redis:latestkubectl apply -f k8s/
kubectl get pods -wWait until all workloads are in Running state, then stop the watch with Ctrl + C.
minikube service gateway --urlOn macOS with the Docker driver, keep that terminal open. Minikube uses a local tunnel, and closing the terminal stops access to the service URL.
Open a new terminal:
cd frontend
python3 -m http.server 5500Then open:
http://127.0.0.1:5500
The frontend includes a Gateway URL field. Use the exact URL returned by:
minikube service gateway --urlExample:
http://127.0.0.1:52591
- Open multiple browser tabs
- Join the same room in both tabs
- Send messages from either tab
- Confirm that messages appear in real time across both sessions
If you want a simpler local container setup without Kubernetes, Docker Compose is the quickest option:
docker compose up --buildThis starts the services defined in docker-compose.yml.
For the frontend:
cd frontend
python3 -m http.server 5500When running with Docker Compose, the gateway is available at:
http://127.0.0.1:8080
Check running pods:
kubectl get podsInspect logs:
kubectl logs deployment/gateway --tail=100
kubectl logs deployment/websocket-service --tail=100
kubectl logs deployment/kafka --tail=100Restart a deployment:
kubectl rollout restart deployment/<name>Delete and redeploy the stack:
kubectl delete -f k8s/
kubectl apply -f k8s/Stop Minikube:
minikube stopDelete the entire local cluster:
minikube deleteYour cluster is usually not running yet. Restart Minikube and verify the context:
minikube start --driver=docker
kubectl config use-context minikube
kubectl cluster-infoThe Kubernetes API server is unhealthy or overloaded. The cleanest fix is usually:
minikube stop
minikube start --driver=dockerIf that is not enough:
minikube delete
minikube start --driver=dockerMost often the frontend is pointing to the wrong gateway URL.
Use the URL returned by:
minikube service gateway --urlDo not assume the gateway is reachable at http://127.0.0.1:8080 when using Minikube.
This repository already includes a fix in k8s/kafka.yaml: enableServiceLinks: false.
That prevents Kubernetes from injecting service-link environment variables like KAFKA_PORT, which can confuse the Confluent Kafka image and cause startup failures.
Run that command from the repository root:
ConvoMesh/
If you are inside Gateway/ or another service directory, Kubernetes will not find the k8s/ folder.
Delete the WebSocket pods and watch Kubernetes recreate them:
kubectl delete pod -l app=websocket-service
kubectl get pods -wThis is a simple way to demonstrate self-healing behavior in the cluster.
- Microservices architecture
- Event-driven design
- Real-time bidirectional communication
- Horizontal scaling concepts
- Service discovery in Kubernetes
- Operational debugging in a production-like local environment
- It combines synchronous APIs and asynchronous event pipelines in one system
- It demonstrates how Redis helps coordinate multiple WebSocket instances
- It shows how Kubernetes changes the local development workflow compared to plain Docker
- It gives you a realistic playground for debugging networking, service discovery, restarts, and rollout behavior
Aman Gautam