How do I send something to connected websocket clients from another thread?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
If your WebSocket server runs on an asyncio event loop, the safest way to send messages from another thread is to hand work back to that loop. The key rule is that the thread should not try to manipulate WebSocket connections directly; it should schedule a coroutine or place a message onto a thread-safe bridge that the loop owns.
Why Direct Cross-Thread Sends Are Risky
Most Python WebSocket servers keep connection objects tied to a single event loop. A background thread may be able to see those objects, but using them directly from the wrong thread can cause race conditions, event-loop errors, or corrupted connection state.
The safer pattern is:
- the event loop owns the WebSocket clients
- a worker thread produces messages
- the worker thread schedules work back onto the loop
That preserves the normal async model instead of mixing thread execution directly into socket operations.
Keep Track of Connected Clients in the Event Loop
A basic WebSocket server can hold the active connections in a set.
Only the event loop should add or remove clients from this set. That keeps ownership clear.
Schedule Broadcasts From Another Thread
If a worker thread wants to broadcast a message, use asyncio.run_coroutine_threadsafe and pass it the main event loop.
This is the core solution: the thread does not send directly. It asks the event loop to run the broadcast coroutine on its behalf.
Use a Queue When Message Volume Is Higher
If the worker produces many messages, a queue is often cleaner than scheduling one coroutine per event. The thread pushes messages into a thread-safe queue, and an async task drains that queue inside the event loop.
This design helps when many producers need to feed one broadcast channel, because the event loop still remains the only place that touches the connections.
Handle Closed Clients Carefully
Broadcast code should expect some clients to disconnect between the moment you snapshot the set and the moment you send. That is why return_exceptions=True is useful in asyncio.gather.
You can also prune closed clients after failed sends if your library or wrapper exposes a clear closed-state signal. The important point is to treat disconnections as normal rather than exceptional application failures.
Common Pitfalls
The biggest mistake is calling websocket.send() directly from the worker thread. Even if it appears to work under light load, it breaks the event-loop ownership model.
Another common issue is mutating the shared client set from both the loop and the thread. Keep client registration and removal inside the event loop only.
People also sometimes block the event loop accidentally by using a normal queue.get() inside async code. If you use a standard thread queue, pull from it with asyncio.to_thread or a dedicated nonblocking bridge.
Finally, do not assume every broadcast reaches every client. Disconnections and send failures are part of normal WebSocket operation, so the broadcast path should be resilient.
Summary
- Let the
asyncioevent loop own all WebSocket connections. - From another thread, schedule sends back onto that loop with
asyncio.run_coroutine_threadsafe. - Use a queue when worker threads produce many messages.
- Keep connection registration and cleanup inside the event loop, not in worker threads.
- Treat disconnects as normal and write broadcast code that tolerates them.
Related reading
- How do I stop a thread when my winform application closes
- How do I terminate a thread in C11?
- How do I test an async method with NUnit or possibly with another framework?
- How do I Understand Read Memory Barriers and Volatile
- How do I set the maximum line length in PyCharm?
- How do I solve error externally-managed-environment every time I use pip 3?
- How do I unit test asynchronous methods nicely?
- How do I update an ObservableCollection via a worker thread?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.