It is necessary to design a backend architecture for a messenger (Slack, Teams, Mattermost). Requirements and constraints: only 1x1 chats, no group chats only text messages, no attachments service accessible via the internet up to 10,000 users in the system messages should be delivered quickly, within a few seconds message order should be preserved, messages should not be duplicated ability to scroll back in chat history, i.e., messages need to be stored clients – mobile devices, no need to design them authorization does not need to be designed
sobes.tech AI
Answer from AI
For designing a backend of a messenger with 1x1 chats and text messages, considering the requirements, the following architecture can be proposed:
-
API server in Go — accepts requests from clients, handles sending and receiving messages.
-
Message storage — a relational database (e.g., PostgreSQL) with a messages table:
CREATE TABLE messages (
id SERIAL PRIMARY KEY,
sender_id INT NOT NULL,
receiver_id INT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
- Indexes on (sender_id, receiver_id, created_at) for quick chat history retrieval.
-
Message delivery — use WebSocket or long polling to ensure fast real-time message delivery.
-
Order and deduplication — messages are numbered by creation time, the client receives them in created_at order. The server guarantees id uniqueness.
-
Scaling — with 10,000 users, the load is moderate, and a single API server with a load balancer can be used.
-
Caching — Redis can be added to cache the latest messages to speed up loading.
-
Security — although authorization does not need to be designed, basic protection against DDoS and data validation should be considered.
Example of handling message sending in Go (simplified):
func SendMessage(w http.ResponseWriter, r *http.Request) {
var msg Message
if err := json.NewDecoder(r.Body).Decode(&msg); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
msg.CreatedAt = time.Now()
// Save to DB
err := db.QueryRow(`INSERT INTO messages (sender_id, receiver_id, content, created_at) VALUES ($1, $2, $3, $4) RETURNING id`,
msg.SenderID, msg.ReceiverID, msg.Content, msg.CreatedAt).Scan(&msg.ID)
if err != nil {
http.Error(w, "DB error", http.StatusInternalServerError)
return
}
// Send to receiver via WebSocket
sendToReceiver(msg)
w.WriteHeader(http.StatusOK)
}
This approach ensures fast message exchange, history storage, and a simplified architecture suitable for the specified requirements.