WebSocket Basics
Part of: Advanced FastAPI Patterns
Learn how to create WebSocket endpoints in FastAPI for real-time bidirectional communication between client and server.
What You'll Learn
- Understand the WebSocket protocol and how it differs from HTTP
- Create a WebSocket endpoint that accepts connections
- Send and receive text messages over a WebSocket connection
- Handle WebSocket disconnections gracefully
Theory and Concepts
WebSocket Basics
What You'll Learn
In this lesson you will learn how to create WebSocket endpoints in FastAPI for real-time, bidirectional communication. You will understand:
- What the WebSocket protocol is and how it differs from HTTP
- How to create WebSocket endpoints in FastAPI
- The WebSocket connection lifecycle: accept, send, receive, close
- How to handle client disconnections gracefully
Theory
What are WebSockets?
HTTP follows a request-response pattern: the client sends a request, the server sends a response, and the connection is done. This works well for most web applications, but some use cases need real-time, bidirectional communication:
- Chat applications: Messages should appear instantly
- Live dashboards: Data updates should stream continuously
- Collaborative editing: Changes should sync in real time
- Gaming: Actions and state need constant exchange
WebSockets solve this by establishing a persistent, full-duplex connection between client and server. Once connected, either side can send messages at any time without waiting for the other.
HTTP vs WebSocket
| Feature | HTTP | WebSocket |
|---------|------|-----------|
| Connection | Short-lived | Persistent |
| Direction | Client initiates | Bidirectional |
| Overhead | Headers on every request | Minimal after handshake |
| Use case | Request/response | Real-time streaming |
The WebSocket Handshake
A WebSocket connection starts as a regular HTTP request with an Upgrade header:
1. Client sends HTTP request with Upgrade: websocket
2. Server responds with 101 Switching Protocols
3. Connection is upgraded to WebSocket
4. Both sides can now send messages freely
WebSockets in FastAPI
FastAPI provides first-class support for WebSockets through Starlette. Here is the basic pattern:
[Code Example]
Connection Lifecycle
A WebSocket connection goes through these stages:
1. Accept the connection:
[Code Example]
This completes the handshake and establishes the connection.
2. Send and receive messages:
[Code Example]
3. Handle disconnection:
[Code Example]
When a client disconnects, the next receive call raises WebSocketDisconnect. Always handle this exception to avoid unhandled errors.
Path Parameters with WebSockets
Just like HTTP endpoints, WebSocket endpoints support path parameters:
[Code Example]
Query Parameters
WebSocket endpoints also support query parameters:
[Code Example]
Key Concepts
- @app.websocket(path): Decorator to define a WebSocket endpoint
- websocket.accept(): Completes the handshake, must be called first
- websocket.receive_text(): Waits for and returns a text message from the client
- websocket.send_text(msg): Sends a text message to the client
- websocket.receive_json(): Receives and parses a JSON message
- websocket.send_json(data): Serializes and sends a JSON message
- websocket.close(): Closes the connection from the server side
- WebSocketDisconnect: Exception raised when the client disconnects
Best Practices
1. Always call accept() first before sending or receiving messages
2. Always handle WebSocketDisconnect to avoid unhandled exceptions when clients leave
3. Use a while True loop for continuous message handling until disconnect
4. Validate early -- check authentication or permissions before accepting the connection
5. Keep message handling lightweight -- offload heavy processing to background tasks
6. Use JSON messages for structured data exchange between client and server
7. Add a health check endpoint so monitoring tools can verify the server is running
Additional Resources
- FastAPI WebSocket Documentation
- Starlette WebSocket Reference
- MDN WebSocket API
- RFC 6455 - The WebSocket Protocol
Helpful Hint
Use '@app.websocket("/ws")' to create a WebSocket endpoint. Inside, call 'await websocket.accept()' first, then use a while loop with 'await websocket.receive_text()' and 'await websocket.send_text()'. Wrap the loop in try/except WebSocketDisconnect.
