# Nchan: a pub/sub server built as an Nginx module

> Nchan turns Nginx into a pub/sub server for WebSocket, EventSource and long-polling subscribers, with buffers in shared memory or Redis. It fits teams that already run Nginx and want to keep live connections out of the application tier.

**slact/nchan** — Fast, horizontally scalable, multiprocess pub/sub queuing server and proxy for HTTP, long-polling, Websockets and EventSource (SSE), powered by Nginx.

- Repository: https://github.com/slact/nchan
- Website: https://nchan.io/
- Stars: 3,067 · Forks: 291
- Language: C
- License: NOASSERTION
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/slact-nchan

## What Nchan replaces in a live-update stack

The README describes Nchan as a pub/sub server built as a module for Nginx, configurable as a standalone server or as a shim between an application and its live subscribers. The problem it targets is concrete: live connections. A browser tab holding a long-poll or EventSource request open occupies a connection slot somewhere, and if that slot belongs to your application process, every idle subscriber costs you memory and a worker. Nchan moves that cost into Nginx, which already handles connections asynchronously and distributes them across worker processes.

A second problem is fan-out. Publishing one message to ten thousand subscribers is not the same operation as answering ten thousand HTTP requests. Nchan treats channels as the unit: messages are published to a channel with an HTTP POST or over a Websocket, and subscribers attach to that channel through Websocket, EventSource, long-polling, interval polling, HTTP chunked transfer, or multipart/mixed responses. The README lists per-channel configurable buffers with no-repeat, no-loss delivery guarantees, and channel multiplexing, where one subscriber connection can carry hundreds of channels.

The intended user is not someone building a chat product from scratch. It is a team that already terminates HTTP in Nginx, wants browser clients to receive pushed updates, and would rather add a module than add a broker plus a client library plus a second network hop.

## How the module handles publishers, subscribers and buffers

The mechanism visible in the README is location-based. You declare one Nginx location as a subscriber endpoint with the nchan_subscriber directive and another as a publisher endpoint with nchan_publisher, and both take a channel identifier, commonly from a query argument such as $arg_id. Publishers POST to the channel; subscribers hold a request open and receive whatever the buffer delivers.

Buffering is the part that determines behaviour under failure. Nchan stores messages in nonblocking shared memory by default, which the README calls fast, and optionally in Redis, which it calls slower but persistent. Shared memory means a message lives inside one Nginx instance and dies with it. Redis means messages survive the instance and, per the README, allow scaling to many Nginx servers and auto-failover with no single point of failure using Redis Cluster. That is the real architectural fork: local memory is the low-latency path, Redis is the multi-node path, and the README does not present a hybrid that gives you both properties at once.

Beyond transport, Nchan exposes HTTP request callbacks and hooks for integration, channel events and a URL for monitoring performance statistics (nchan_stub_status), and channel groups with usage accounting and limits. Those are operational surfaces rather than protocol features, and they are what make the module usable by someone other than the person who wrote the config.

## Installing Nchan and publishing your first message

The README offers packages for several platforms before it offers a source build. On macOS it gives a Homebrew route that taps a third-party formula and installs a full Nginx build with the module included:

```bash
brew tap denji/nginx; brew install nginx-full --with-nchan-module
```

On Debian, the README points at a dynamic module build in the Debian package repository, libnginx-mod-nchan, and separately at prebuilt static packages, nginx-common.deb and nginx-extras.deb, installed by downloading both and running dpkg -i followed by sudo apt-get -f install. Ubuntu gets the same static package treatment with nginx-common.ubuntu.deb and nginx-extras.ubuntu.deb. Fedora has dynamic module RPMs, Arch has AUR packages, and there is a buildpack and a one-click app for Heroku. A statically compiled binary and Linux Nginx installation files are also published as a tarball.

If none of those fit, the README's source path is to configure Nginx with the module added:

```bash
./configure --add-module=path/to/nchan ...
```

For Nginx later than 1.9.11 it notes that you can instead build Nchan as a dynamic module with --add-dynamic-module=path/to/nchan, then run make and make install. Note that the first snippet ends in an ellipsis in the README itself: those are not the complete configure flags, they are the ones you add to your existing Nginx configure line.

The getting-started config is two locations inside an http/server block:

```nginx
location = /sub {
  nchan_subscriber;
  nchan_channel_id $arg_id;
}

location = /pub {
  nchan_publisher;
  nchan_channel_id $arg_id;
}
```

After reloading Nginx, a subscriber connects to /sub?id=yourchannel and a publisher POSTs to /pub?id=yourchannel. The README's own getting-started example stops mid-sentence after "You can now publish messages to channels by", so the exact publish command is not spelled out there; the publisher endpoint is the POST target, and the channel comes from the id argument. What you should see is the POST returning and the held subscriber request receiving the message body. For browsers, the README points at NchanSubscriber.js, a wrapper published on NPM that supports long-polling, EventSource and resumable Websockets.

## Where Nchan is the wrong choice

Nchan is not a message broker with delivery receipts. The README promises no-repeat and no-loss delivery per channel buffer, which is a statement about what the buffer hands to a connected subscriber, not about what an offline subscriber missed. There is no documented replay-from-offset API, no consumer group, and no acknowledgement step. If your system must prove that a specific client processed a specific message, Nchan is the wrong layer.

It is also an Nginx module, and that shapes everything. You cannot upgrade Nchan without upgrading or rebuilding Nginx, and the README's own install matrix shows the consequence: the Debian and Ubuntu static packages are prebuilt against particular Nginx builds, and the dynamic module path depends on your Nginx version being compatible. Running Nchan means your web server release cadence and your pub/sub release cadence are the same cadence.

The scaling claim deserves the same caution. The README states that with a well-tuned OS and network stack on commodity hardware you can expect upwards of 300K concurrent subscribers per second at minimal CPU load, but it also discloses that the benchmark measures Nchan's internal response time after publishing, excluding TCP handshake and internal HTTP request parsing, averaged over 5 runs with 50-byte messages. That is a measure of the module's own dispatch cost, not of what your deployment will serve. Treat it as a ceiling on the component, not a forecast for your traffic.

Finally, the Redis path is not free. The README calls Redis storage slower and persistent in the same sentence, so choosing it to get multi-server scaling and failover means accepting a latency cost the shared-memory path does not pay.

## Nchan versus running a separate pub/sub service

The alternative most teams compare against is a standalone pub/sub service reached over a network protocol, with clients connecting through a library rather than through HTTP endpoints. The difference in approach is where the connection state lives. With a separate service, your Nginx layer proxies or upgrades to another process, and that process owns the subscriber registry, the buffers and the failover logic. With Nchan, Nginx itself is the subscriber registry.

That changes the failure boundary. A separate service can be restarted, scaled and versioned independently of your web tier, and it can offer semantics Nchan does not document, such as durable logs or consumer offsets. Nchan's advantage is that it removes a hop and a process: subscribers terminate in the same server that already terminates their HTTP, and there is no second thing to deploy, secure or monitor for connection counts.

The cost is coupling. If you already run Nginx and your pub/sub needs are channel fan-out with short-lived messages, the standalone service is an extra component earning its keep only through features you are not using. If your pub/sub needs are durable, replayable, or independently scalable from your web tier, Nchan will not grow into that role, and adopting it means migrating twice.

## Maintenance, licensing and upgrade cost

The repository is not archived, and the last push was on 2026-09-11, which is recent enough that the project is still receiving commits. The README states that the latest Nchan release is 1.3.8, dated February 14, 2026, and links a changelog. The project has a long history: the README says the first iteration was written in 2009-2010 as the Nginx HTTP Push Module and was refactored into its present state in 2014-2016.

Upgrade cost has one specific wrinkle that the README documents. Nchan is backwards-compatible with all Push Module configuration directives, but some of the more unusual and rarely used settings have been disabled and will be ignored with a warning. The README points to an upgrade page for the detailed list of changes and incompatibilities. If you are migrating an old Push Module config, that page is the thing to read before you reload, because a silently ignored directive is a behaviour change you will not see in the config diff.

The licence field is NOASSERTION, and the repository's top level contains a file named LICENCE. The README does not state licence terms, and the repository metadata does not resolve to a standard identifier, so confirm the terms from that file before you ship Nchan in a product. This is not legal advice; it is a note that the machine-readable licence signal is missing here.

## Conclusion

Adopt Nchan if you already run Nginx and want to stop holding thousands of idle HTTP connections inside your application workers. Skip it if your pub/sub needs per-message acknowledgement, replay from a durable log, or a broker you can operate without touching Nginx. Before committing, verify that your Nginx version builds the module (or that the distro package matches your Nginx package), and decide up front whether buffers live in shared memory or Redis, because that choice fixes your failover behaviour.

## FAQ

### Does Nchan require Redis?

No. Nchan stores messages in nonblocking shared memory by default, and Redis is an optional storage engine the README describes as slower but persistent. Redis is what enables scaling across multiple Nginx servers and failover with Redis Cluster.

### Which subscriber transports does Nchan support?

The README lists Websocket, EventSource (Server-Sent Events), long-polling, interval polling, HTTP chunked transfer and HTTP multipart/mixed. In a browser you can use Websocket or EventSource directly, or the NchanSubscriber.js wrapper library, which is also published on NPM.

### How do I build Nchan from source into Nginx?

Configure Nginx with --add-module=path/to/nchan added to your existing configure flags, or --add-dynamic-module=path/to/nchan if you are on Nginx later than 1.9.11, then run make and make install. The README points at nginx.org for Nginx and the GitHub releases page for the Nchan source.

## Sources

- [Issues](https://github.com/slact/nchan/issues)
- [Project website](https://nchan.io/)
- [README](https://github.com/slact/nchan/blob/master/README.md)
- [slact/nchan on GitHub](https://github.com/slact/nchan)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/slact-nchan
