Library / SDK
django/channels_redis avatar
django/channels_redis

channels_redis and the two Redis channel layers for Django Channels

Redis channel layer backend for Django Channels

650 stars199 forksPythonBSD-3-Clause

At a glance

What is it?
django/channels_redis puts Redis behind Django Channels, with a stable layer that does its own group bookkeeping and a Pub/Sub layer the project still marks as Beta. It fits teams already running Channels, but a few settings punish careless changes.
Who is it for?
Adopt channels_redis if you already run Django Channels and want Redis to carry the layer, and stay on RedisChannelLayer until the Pub/Sub backend leaves Beta. Pass on it if your Redis host list changes often, since sharding then risks losing data.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 64 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A channel layer for teams already running Channels

Every Django Channels deployment needs a channel layer, the component that moves events between the processes serving an ASGI application. Without one, a message sent by one worker never reaches a worker holding the connection. django/channels_redis fills that role by putting Redis behind the layer, and the project describes itself in one line as a Redis channel layer backend for Django Channels. The audience is narrow and specific: teams already running Channels 4.2.2 or later who want their websocket and HTTP traffic to share Redis infrastructure instead of adding a second broker. The dependency floor in setup.py is honest about that scope. The package requires redis>=4.6, msgpack~=1.0, asgiref>=3.9.1,<4 and channels>=4.2.2, and it declares python_requires as >=3.9, while the project states it is tested against Python 3.10 to 3.14 and against the latest redis-py as well as its 5.x branch and its main development branch. Two layers ship inside the package, and choosing between them is the first decision a new user faces.

The Pub/Sub implementation is still labelled Beta

The repository splits its work across two implementations and labels them differently on purpose. RedisChannelLayer is described as the original layer, and it implements channel and group handling itself. RedisPubSubChannelLayer is newer and uses Redis Pub/Sub for message dispatch, and the project documentation marks it as currently at Beta status, meaning it may be subject to breaking changes whilst it matures. That word carries more weight than it looks. A beta backend is a public interface without a stability promise, so a renamed option or a changed message format can reach your production settings without a major version bump to warn you. The mature path is the original layer, which keeps its own channel and group bookkeeping instead of leaning on Redis Pub/Sub dispatch. Both layers support a single-server and a sharded configuration, so picking one does not lock you out of scaling out later. The practical consequence for an evaluator is simple: treat the Pub/Sub layer as something you would trial on your own deployment, and treat RedisChannelLayer as the default you can reason about.

Prefix and host list mistakes cause silent partitioning

Two settings decide whether two applications can share one Redis instance safely, and both are easy to get wrong. The first is prefix, which defaults to asgi and is added to every Redis key the layer writes. If two or more entirely separate channel layers run through the same Redis instance they must use different prefixes, while every server talking to the same layer has to use the same prefix. Get that wrong in either direction and you either interleave unrelated traffic under one key namespace or partition a layer that was supposed to be shared. The second is hosts, whose default is redis://localhost:6379 and which accepts URIs, (host, port) tuples, or dicts conforming to the redis Connection documentation. Passing several hosts enables sharding, and the documentation is blunt about the cost: changing the host list will lose some sharded data. That turns resizing the cluster into a migration rather than a config edit.

Capacity refuses messages, expiry quietly discards them

Traffic that exceeds the configured capacity is dropped, and the layer refuses connections rather than queueing them. The capacity option sets the default channel capacity and defaults to 100; once a channel is at capacity it refuses more messages. How that refusal lands depends on the caller: an HTTP server will refuse connections, while Django sending a response will just wait until there is space. The asymmetry matters when you size the layer, because the same setting produces a fast failure on one path and a slow stall on another. Per-channel tuning is available through channel_capacity, a dict mapping channel name patterns to capacities where a string key is read as a glob and a compiled re object is treated as a regular expression. The documented example sets http.request to 200, all http.response! channels to 10 and all websocket.send! channels to 20, and passing an OrderedDict enforces a matching order. Timeouts behave in the same spirit: expiry defaults to 60 seconds and group_expiry defaults to 86400, after which channels are removed from the group. The project suggests reducing group_expiry for a healthier system that encourages disconnections, but not below the relevant timeout in the interface server, for example the --websocket_timeout in daphne.

Installing the package and pointing Django at it

Installation is a single package name, and the project says so plainly. The install command is:

bash
    pip install channels-redis

Earlier releases of this package were called asgi_redis and remain available on PyPI under that name if you need them for Channels 1.x projects, while this package is for Channels 2 and later. Wiring it into a Django project means setting CHANNEL_LAYERS in the settings file:

python
    CHANNEL_LAYERS = {
        "default": {
            "BACKEND": "channels_redis.core.RedisChannelLayer",
            "CONFIG": {
                "hosts": [("localhost", 6379)],
            },
        },
    }

The BACKEND path selects which implementation you get, and the hosts list tells the layer where Redis lives. If your server listens on a UNIX domain socket you can point at it with ["unix:///path/to/redis.sock"], which the project says should be slightly faster than a loopback TCP connection. There is no separate daemon to start for the layer itself, since Redis is the only external process in the picture.

Sentinel and self-signed TLS need different connection shapes

Connection shapes get more elaborate once Redis is not a single plain server. Sentinel connections are configured with a dict containing a sentinels list, where each entry is a (host, port) pair such as ("localhost", 26379), plus a master_name key naming the Sentinel master set, and any additional connection kwargs can be passed alongside. Plain Redis and Sentinel connections can be mixed and matched if sharding, which is convenient for staged migrations but also means the host list can hold two different kinds of entry at once. Self-signed SSL, described with Heroku as an example, uses a host dict of its own:

python
    "default": {
        "BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
        "CONFIG": {
            "hosts":[{
                "address": "rediss://user@host:port",  # "REDIS_TLS_URL"
                "ssl_cert_reqs": None,
            }]
        }
    }

That form disables certificate requirement checking through ssl_cert_reqs set to None, so the connection encrypts the traffic without proving who is on the other end. The documentation also notes that the Redis protocol itself is still unencrypted, which is a good reason to keep the symmetric encryption mode in mind for anything sensitive.

Symmetric encryption covers payloads, not key names

The optional symmetric encryption mode closes part of the gap the TLS story leaves open. Setting symmetric_encryption_keys turns on encryption of the message payloads, and it needs the cryptography package, which setup.py exposes as the cryptography extra:

bash
    pip install channels-redis[cryptography]

Keys are a list of strings; the first key is always used for encryption and all of them are considered for decryption, so a rotation is a matter of adding a new key at the start and moving the old one down, then removing it once the message expiry time has passed. The documentation is careful about what this buys you: data is encrypted both on the wire and at rest in Redis, yet the channel and group key names could still contain metadata patterns of use to attackers, and the Redis protocol remains unencrypted, which is why routing connections over TLS is still advised. Keys should have at least 32 bytes of entropy. They are passed through the SHA256 hash function before being used as encryption keys, and while any string will work, the shorter the string the easier the encryption is to break.

Where channels_redis is the wrong tool

There are several reasons to look elsewhere. If you specifically want Redis Pub/Sub dispatch, the layer that offers it is marked Beta and the project says it may be subject to breaking changes whilst it matures, which is a hard condition to accept for a component every message passes through. If you resize the host list, sharded data can be lost, so a cluster whose shape changes often belongs on a layer with a different persistence story. Capacity ceilings that refuse messages instead of queueing them also sit badly with bursty traffic you would rather backlog, though raising the expiry setting addresses part of that case. The project publishes no GitHub releases, so version tracking happens through the CHANGELOG.txt file at the repository root, and the README does not document a rollback procedure for a failed upgrade. The licence is BSD-3-Clause, which permits modification and redistribution under its conditions, though that is not advice about how those obligations land in your own setup. The last push was on 2026-08-20, and the repository is not archived.

Editorial conclusion

Adopt channels_redis if you already run Django Channels and want Redis to carry the layer, and stay on RedisChannelLayer until the Pub/Sub backend leaves Beta. Pass on it if your Redis host list changes often, since sharding then risks losing data. Before committing, check that your Redis client satisfies redis>=4.6, that your interface server timeout is not shorter than group_expiry, and whether any payload is sensitive enough to need symmetric_encryption_keys.

Frequently asked questions

How do I install channels_redis for a Django Channels project?

Install it with pip install channels-redis, then set CHANNEL_LAYERS in your Django settings with the channels_redis.core.RedisChannelLayer backend and a hosts entry. The package requires channels>=4.2.2, asgiref>=3.9.1,<4 and redis>=4.6, and the project states it is tested against Python 3.10 to 3.14.

Is the Redis Pub/Sub channel layer in channels_redis ready to rely on?

The project marks RedisPubSubChannelLayer as currently at Beta status and warns that it may be subject to breaking changes whilst it matures. RedisChannelLayer is the original implementation and handles channel and group handling itself.

How do I configure Sentinel or sharded Redis in channels_redis?

Sentinel connections use a dict with a sentinels list and a master_name key, plus any additional connection kwargs. Passing several hosts enables sharding and plain Redis and Sentinel entries can be mixed that way, but the project warns that changing the host list will lose some sharded data.

Does channels_redis encrypt messages sent through the layer?

Only if you turn it on, by passing symmetric_encryption_keys and installing the cryptography extra. The first key encrypts and all keys are tried for decryption, which allows rotation without downtime, and keys should have at least 32 bytes of entropy.

Official sources

  1. django/channels_redis on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/django-channels-redis.svg)](https://hysenlabs.com/projects/django-channels-redis)

Was this useful?