A high-performance, scalable backend for real-time messaging and video calling, built with Go (Gin), WebSockets, Redis Pub/Sub, and PostgreSQL.
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Frontend │────▶│ Traefik │────▶│ GoTalk API │
│ (React/Next)│ │ (L7 Proxy) │ │ (Go + Gin) │
└─────────────┘ └──────────────┘ └──────┬──────┘
│
┌────────────────────────────┤
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ PostgreSQL │ │ Redis │ │ MinIO │
│ (Messages) │ │ (Pub/Sub) │ │ (Files) │
└───────────┘ └───────────┘ └───────────┘
chat-api/
├── cmd/
│ └── server/
│ └── main.go # Entry point
├── internal/
│ ├── config/
│ │ └── config.go # Configuration management
│ ├── handler/
│ │ ├── auth_handler.go # Auth endpoints
│ │ ├── chat_handler.go # Chat REST endpoints
│ │ └── ws_handler.go # WebSocket handler
│ ├── middleware/
│ │ ├── auth.go # JWT auth middleware
│ │ └── cors.go # CORS middleware
│ ├── model/
│ │ ├── user.go # User model
│ │ ├── message.go # Message model
│ │ ├── conversation.go # Conversation model
│ │ └── dto.go # Request/Response DTOs
│ ├── repository/
│ │ ├── user_repo.go # User data access
│ │ ├── conversation_repo.go # Conversation data access
│ │ └── message_repo.go # Message data access
│ ├── service/
│ │ ├── auth_service.go # Auth business logic
│ │ └── chat_service.go # Chat business logic
│ └── ws/
│ ├── hub.go # WebSocket hub + Redis Pub/Sub
│ └── client.go # WebSocket client connection
├── pkg/
│ └── auth/
│ └── jwt.go # JWT token manager
├── docker-compose.yml # Development stack
├── Dockerfile # Multi-stage build
├── .air.toml # Hot reload config
├── .env # Environment variables
└── go.mod
- Docker & Docker Compose
- Go 1.23+ (for local development)
# Start all services (Traefik, API, PostgreSQL, Redis, MinIO)
docker compose up -d
# View logs
docker compose logs -f api| Service | URL |
|---|---|
| API | http://api.localhost |
| Traefik Dash | http://localhost:8090 |
| MinIO Console | http://localhost:9001 |
| PostgreSQL | localhost:5432 |
| Redis | localhost:6379 |
curl http://api.localhost/healthMigrations run automatically when the API server starts (go run cmd/server/main.go or via Docker).
To populate the database with sample data (10 test users and 1 group chat), run the seeder:
# Run the database seeder locally
go run cmd/seeder/main.goRunning on Server (Kubernetes): Since the server uses Docker containers, the seeder binary has been compiled directly into the production image. You can execute it via K8s:
kubectl exec -it deployment/gotalk-api -n gotalk -- ./seederTest Accounts Created:
- Emails:
user1@gotalk.localtouser10@gotalk.local - Password (for all):
password123
POST /api/v1/auth/register # Register new user
POST /api/v1/auth/login # Login
GET /api/v1/auth/profile # Get profile (auth required)
GET /api/v1/users/search?q= # Search users (auth required)
GET /api/v1/conversations # List conversations
POST /api/v1/conversations # Create conversation
GET /api/v1/conversations/:id # Get conversation details
GET /api/v1/conversations/:id/messages # Get messages (paginated)
POST /api/v1/conversations/:id/messages # Send message
POST /api/v1/conversations/:id/read # Mark as read
GET /ws?token=<jwt_token> # Connect WebSocket
// Send message
{"type": "new_message", "payload": {"conversation_id": "uuid", "content": "Hello!"}}
// Typing indicator
{"type": "typing", "payload": {"conversation_id": "uuid"}}
// Stop typing
{"type": "stop_typing", "payload": {"conversation_id": "uuid"}}
// Read receipt
{"type": "message_read", "payload": {"conversation_id": "uuid", "message_id": "uuid"}}
// WebRTC Call Offer
{"type": "call_offer", "payload": {"to": "user_uuid", "sdp": {...}, "call_type": "video"}}
// WebRTC Call Answer
{"type": "call_answer", "payload": {"to": "user_uuid", "sdp": {...}}}
// WebRTC ICE Candidate
{"type": "call_ice_candidate", "payload": {"to": "user_uuid", "candidate": {...}}}// New message received
{"type": "new_message", "payload": {/* message object */}}
// User typing
{"type": "typing", "payload": {"conversation_id": "uuid", "user_id": "uuid", "username": "john"}}
// User online/offline
{"type": "online", "payload": {"user_id": "uuid", "is_online": true}}# In your frontend's docker-compose.yml
services:
frontend:
# ... your frontend config
networks:
- gotalk-network
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`chat.localhost`)"
- "traefik.http.routers.frontend.entrypoints=web"
- "traefik.http.services.frontend.loadbalancer.server.port=3000"
networks:
gotalk-network:
external: true- Distributed WebSocket with Redis Pub/Sub - Horizontal scaling support
- Cursor-based Pagination - Efficient message loading
- Multi-device Support - One user, multiple connections
- WebRTC Signaling Server - Custom signaling for video calls
- Graceful Shutdown - Clean connection handling
- JWT Authentication - Stateless auth with bcrypt
- Docker + Traefik - Production-ready infrastructure
MIT