Oct 23, 20265 min read

Best Python Framework for WebSockets and Real-Time Apps in 2026

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:

  • Whether WebSocket handlers live next to your HTTP routes.
  • Whether rooms and broadcast are built in.
  • How messages reach clients on other instances.
  • Where Redis and the database run locally and in production.

Python real-time options at a glance

OptionApproachBest fit
FastAPIWebSocket routes from StarletteAsync APIs adding real-time endpoints
Django ChannelsConsumers and channel layers for DjangoDjango projects that need WebSockets
LitestarWebSocket handlers and a channels pluginTeams that want broadcast built into the framework
python-socketioSocket.IO server with rooms and reconnectionApps with Socket.IO clients
Compare features across all four options
CapabilityFastAPIDjango ChannelsLitestarpython-socketio
RoleWeb frameworkDjango extensionWeb frameworkSocket.IO server
Rooms and broadcastYou build themGroupsChannels pluginRooms
Fan-out across instancesYou build itRedis channel layerRedis backendRedis manager
Local infrastructureYou run itYou run RedisYou run RedisYou run Redis
Production infrastructureYou provision itYou provision itYou provision itYou provision it

FastAPI: WebSockets next to your API

FastAPI

FastAPI exposes Starlette's WebSocket support with the same path parameters and dependencies as HTTP routes.

Key features

  • @app.websocket routes with Depends for auth.
  • receive_text, receive_json and matching send methods.
  • Runs on any ASGI server.

Good to know

There is no broadcast or room abstraction, so fan-out across instances is yours to build.

Try FastAPI →

Django Channels: WebSockets for Django

Django Channels

Django Channels adds consumers for WebSockets and a channel layer, usually backed by Redis, for sending messages between consumers and processes.

Key features

  • Consumers with access to Django auth and sessions.
  • Groups for broadcasting to many connections.
  • Redis channel layer for multiple processes.

Good to know

Channels requires running Django under ASGI, and the Redis channel layer is another service in each environment.

Try Django Channels →

Litestar: channels built in

Litestar

Litestar has WebSocket handlers and a channels plugin for publishing to subscribers, with memory and Redis backends.

Key features

  • WebSocket listeners with typed data.
  • Channels plugin for broadcast and history.
  • Redis backend for multiple instances.

Good to know

The community is smaller than FastAPI's, so fewer examples cover edge cases.

Try Litestar →

python-socketio: the Socket.IO protocol

python-socketio

python-socketio implements a Socket.IO server with rooms, namespaces and acknowledgements, and runs under ASGI next to other frameworks.

Key features

  • Rooms and namespaces.
  • Redis and other client managers for multiple instances.
  • Compatible with the JavaScript Socket.IO client.

Good to know

Clients must speak Socket.IO, so plain WebSocket clients cannot connect directly.

Try python-socketio →

Encore: the infrastructure SDK you add to your framework

Encore

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()
FastAPI holds the socket, Postgres keeps history and Redis channels carry each message to every instance.

Key features

  • Redis and Postgres are declared in the same module as the endpoint that uses them.
  • Every instance subscribed to a channel receives each published message, which is what broadcast needs.
  • A deploy provisions both in your own AWS or GCP account.
  • A coding agent asked for read receipts can add a second channel and try it against the local Redis in the same session, then read the request in a trace through the local MCP server.

Good to know

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.

Try Encore →

How to choose

  • FastAPI for WebSocket endpoints in an async API.
  • Django Channels when the app is Django.
  • Litestar for broadcast built into the framework.
  • python-socketio when clients use Socket.IO.

Python support in Encore is in beta, and you can sign up for access.

Frequently asked questions

What is the best Python framework for WebSockets?

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.

How do WebSocket servers in Python scale past one instance?

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.

How do I broadcast WebSocket messages across instances with Encore?

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.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders