FastAPI, Django Channels, Litestar and python-socketio compared for real-time Python backends, plus how Encore adds the Postgres and Redis that carry messages across instances.
Python's async ecosystem made WebSockets practical in most frameworks, and the JetBrains Python Developers Survey 2024 shows FastAPI used by 38 percent of respondents, ahead of Django at 35 percent.
Most of the work in a real-time backend goes into delivering a message received by one server to clients connected to another, and into running the broker that does this in every environment. The browser API is defined in the WHATWG WebSockets Standard, and every option below speaks the WebSocket protocol, with python-socketio adding its own protocol on top.
What to weigh when choosing:
FastAPI exposes Starlette's WebSocket support with the same path parameters and dependencies as HTTP routes.
@app.websocket routes with Depends for auth.receive_text, receive_json and matching send methods.There is no broadcast or room abstraction, so fan-out across instances is yours to build.
Django Channels adds consumers for WebSockets and a channel layer, usually backed by Redis, for sending messages between consumers and processes.
Channels requires running Django under ASGI, and the Redis channel layer is another service in each environment.
Litestar has WebSocket handlers and a channels plugin for publishing to subscribers, with memory and Redis backends.
The community is smaller than FastAPI's, so fewer examples cover edge cases.
python-socketiopython-socketio implements a Socket.IO server with rooms, namespaces and acknowledgements, and runs under ASGI next to other frameworks.
Clients must speak Socket.IO, so plain WebSocket clients cannot connect directly.
Encore combines a FastAPI or Django app with the databases behind its real-time features through an infrastructure SDK you install into the app, so the framework keeps the WebSocket endpoint while the service declares a Postgres database for history and a Redis database whose channels carry messages between instances. encore run starts Postgres locally along with Redis, and a deploy provisions both in your own AWS or GCP account, such as RDS and ElastiCache on AWS. Whichever option above you pick, Encore can add the Postgres and Redis to the same app.
import asyncio
from contextlib import asynccontextmanager
import encore
from encore.storage import postgres, redis
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
db = postgres.Database("chat", migrations="./migrations")
fanout = redis.Database("fanout")
@asynccontextmanager
async def lifespan(app: FastAPI):
await encore.start()
yield
app = FastAPI(lifespan=lifespan)
@app.websocket("/rooms/{room}")
async def room_socket(websocket: WebSocket, room: str):
await websocket.accept()
sub = await fanout.read().pubsub.subscribe[str](f"room:{room}")
async def forward() -> None:
# Messages published by any instance arrive here.
async with sub:
async for msg in sub:
await websocket.send_text(msg.payload)
task = asyncio.create_task(forward())
try:
while True:
text = await websocket.receive_text()
await db.exec(
"INSERT INTO messages (room, body) VALUES ($1, $2)", room, text
)
await fanout.write().pubsub.publish(f"room:{room}", text)
except WebSocketDisconnect:
task.cancel()
Redis channels do not store messages, and the Redis Pub/Sub docs describe at-most-once delivery, so a client that disconnects needs a history endpoint, not shown here, that reads what it missed from Postgres. The snippet keeps a reference to the forwarding task, since the asyncio documentation warns that the event loop only keeps weak references to tasks. When Encore provisions the databases, the cloud access sits with Encore's IAM role, not the agent or developer. Python support is in beta, and you can sign up for access.
Python support in Encore is in beta, and you can sign up for access.
FastAPI is the simplest way to add WebSocket endpoints to an async Python API. Django Channels brings WebSockets and channel layers to Django projects, Litestar has WebSocket handlers and a channels plugin built in, and python-socketio implements the Socket.IO protocol with rooms and reconnection. Encore is not a competing framework but an infrastructure SDK you add to the framework you pick, for the Postgres and Redis that store and fan out messages.
Each instance only knows its own connections, so messages have to travel through a shared broker. Redis publish and subscribe is the common choice, used by the Channels Redis layer and python-socketio's Redis manager.
Declare a Redis database with encore.storage.redis, subscribe each connection to a channel with db.read().pubsub.subscribe, and publish incoming messages with db.write().pubsub.publish. Every instance subscribed to the channel receives the message and forwards it to its connected clients.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.