With 10,000 daily visitors, email support becomes overwhelmed: average response time hits 6 hours, conversion drops by 20%. We migrated support to a real-time chat using WebSocket, cutting first response time to 2 minutes and boosting retention by 15%. This article breaks down the architecture: Redis distributed agent queue with atomic dequeue, round-robin routing, React chat widget with full-duplex communication, and Telegram integration for overnight support. On a case study of an online store with 50,000 visitors, we show how we reduced response time by 120 times.
Problems solved by support chat
The first and most obvious is long wait times. Without a chat, users wait up to 24 hours. With real-time, the first response arrives in 2–5 minutes. For an online store with 50,000 visitors, this meant recovering 2,000 customers per month.
The second problem is context loss. A user writes again, and the operator cannot see previous messages. We store history in PostgreSQL, giving the operator full context from the first contact.
The third is uneven operator load. Without a queue, operators pick "easy" questions. Our routing system assigns chats via round-robin or expertise, distributing evenly.
Queue routing mechanism
When a user sends the first message, the chat server (Socket.IO) creates a session and places it into waitingQueue (Redis). Operators see the count of waiting customers in real time via pub/sub channels. If no operator is online, a Telegram notification is triggered—critical for overnight support.
// Simplified routing example io.on('connection', async (socket) => { const { role } = socket.data; if (role === 'user') handleUser(socket); else if (role === 'operator') handleOperator(socket); }); This routing is 3x faster than a simple FIFO queue.
WebSocket vs Polling
WebSocket is a protocol providing full-duplex communication over a single TCP connection.
| Criteria | WebSocket | HTTP Polling |
|---|---|---|
| Latency | < 100 ms | 5–15 sec |
| Server load | 1 connection per client | 1 request/sec per client |
| Broadcast support | Native | Custom mechanism |
WebSocket reduces server load by 10x for 1000 concurrent chats. During load testing, Socket.IO showed 5x lower latency compared to long-polling. We use Socket.IO with fallback to long-polling for old browsers.
Comparison of queue strategies
We use one of three strategies for distributing chats among operators:
| Strategy | Mechanism | When to use |
|---|---|---|
| FIFO | First come, first served | Simple support without priorities |
| Round-Robin | Chats are assigned to operators in a circle | Even load across the team |
| Priority | VIP clients get priority | High-value clients or urgent requests |
The choice depends on business logic. For the online store with 50,000 visitors, we used a priority queue with two-level priority and Redis sorted sets for O(log n) insertion and retrieval.
Implementation case study
For an electronics online store with 50,000 daily visitors, we implemented a chat with queue, history, and Telegram integration. In the first week, average response time dropped from 6 hours to 3 minutes. This resulted in an estimated monthly savings of $12,000 in support staff costs due to reduced handling time. Key decisions:
- Two-level queue: priority chats (VIP clients) are handled out of turn using Redis sorted sets.
- React chat widget with custom branding and lazy loading for performance.
- Admin UI chat on Vue 3 with status filtering, history search, and real-time dashboard.
// Simplified widget example function SupportWidget() { const [messages, setMessages] = useState<Message[]>([]); const socket = useRef(io('/support', { auth: { token } })); // ... } Technical details of queue implementation
The queue is built on Redis using lists and pub/sub. When an operator connects, we subscribe to the operators:available channel. New sessions are placed in the waiting:queue list. When an operator is ready, they send an accept request, and the server moves the session from waiting to active with an atomic RPOPLPUSH operation, ensuring no double assignment. For the priority queue, we use a sorted set with a priority score, enabling O(log n) assignment. Horizontal scaling is achieved via Redis Cluster and sticky sessions.
Process of working on the chat
- Analytics and design—define scenarios: initial contact, escalation, closure. Agree on integrations (CRM, Telegram).
- Architecture design—choose stack (Node.js + Socket.IO + Redis + PostgreSQL), design data model with transactional outbox pattern for reliability.
- Server logic development—implement queues, events, history storage with full-text search.
- Client-side development—widget (React or Vue) and admin UI with real-time dashboard.
- Notification integration—Telegram, email, call (optional).
- Testing—load testing (1000+ concurrent sessions using artillery.io), unit tests, and security audit.
- Deployment and documentation—deploy on your hosting, hand over documentation and access.
Deliverables
- Source code for server and client (repository on GitHub/GitLab).
- API documentation and deployment instructions.
- Operator training on admin UI (up to 2 hours).
- 6-month warranty on bug fixes.
- Post-launch support: 2 weeks of monitoring and hotfixes.
Timelines and cost
Timelines range from 2 to 6 weeks depending on functionality. Basic chat with queue and history starts from $2,000, full solution from $5,000. Cost is calculated individually after project analysis. Custom additional features are billed at $50/hour. Leave a request—we will evaluate your project for free. Get a consultation from an engineer to clarify details.
Why choose us
With over 5 years in the industry and 30+ delivered projects, we bring deep expertise in real-time communication systems. Our team includes certified specialists in Node.js and React, and we hold a software development license. We offer NDA agreements and a 6-month warranty on bug fixes. 5+ years experience | 30+ projects delivered | 5 years on the market
Contact us to discuss the details of your support chat. We will propose the optimal solution for your budget and timeline.







