# emitter-io/emitter: a Go MQTT broker with built-in storage, keys and clustering

> Emitter is a distributed publish-subscribe broker written in Go, speaking MQTT over TCP and WebSockets, with message history, channel keys and Prometheus metrics. It suits teams that want a self-hosted broker plus storage and access control in one binary, and it is a poor fit if you need a permissive licence or a drop-in Mosquitto replacement.

**emitter-io/emitter** — High performance, distributed and low latency publish-subscribe platform.

- Repository: https://github.com/emitter-io/emitter
- Website: https://emitter.io
- Stars: 4,008 · Forks: 360
- Language: Go
- License: AGPL-3.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/emitter-io-emitter

## What emitter-io/emitter is for

Emitter is a publish-subscribe broker, not a client library. It speaks MQTT over TCP and WebSockets, and the README positions it for online gaming and mobile apps on the low-latency, binary-message side, and for dashboards, visual analytics and chat on the real-time web side, plus IoT where sensors are controlled and data is gathered. The distinguishing claim is that storage and security ship with the broker: message storage with history and message-level expiry, and secure channel keys with permissions that the README says can face the internet.

That combination is the reason to look at it. Running Mosquitto plus a separate database plus an auth proxy is three moving parts; Emitter's README presents those as one deployment. The trade-off is that you inherit Emitter's own model for channels, keys and storage rather than composing your own from standard pieces.

## How the broker is put together

The repository layout tells you most of the architecture. main.go is the entry point, internal/ holds the implementation, and emitter.conf is the configuration file. The dependency list in go.mod is unusually informative: github.com/weaveworks/mesh handles inter-broker gossip and membership, which is how a cluster of brokers finds itself without an external coordinator; github.com/tidwall/buntdb and github.com/dgraph-io/badger/v3 appear for storage; github.com/coocood/freecache and github.com/axiomhq/hyperloglog cover in-memory caching and cardinality estimation; github.com/prometheus/client_golang and gopkg.in/alexcesaro/statsd.v2 back the monitoring the README advertises; github.com/valyala/fasthttp serves the HTTP surface, including the /keygen page; and github.com/eclipse/paho.mqtt.golang is present, which suggests MQTT client code inside the broker as well as the server side.

The README describes the consistency position plainly: resilient, highly available and partition tolerant, AP in CAP terms. That is a deliberate choice with a cost. A cluster that stays available during a partition will not guarantee that every subscriber sees every message in the same order, and the README does not document a reconciliation step for messages published on the minority side of a split. If your workload is a command queue where duplicates or gaps are unacceptable, this is the wrong consistency model, and no amount of throughput compensates.

## Installing emitter with docker run and generating a first key

The README gives a one-line Docker start. The image is emitter/server and the container name is emitter, with port 8080 published.

```bash
docker run -d --name emitter -p 8080:8080 --restart=unless-stopped emitter/server
```

On first start, with no configuration or environment variables supplied, the README says the server prints a message saying it could not find a licence and then generates one. The output looks like this:

```shell
[service] unable to find a license, make sure 'license' value is set in the config file or EMITTER_LICENSE environment variable
[service] generated new license: uppD0PFIcNK6VY-7PTo7uWH8EobaOGgRAAAAAAAAAAI
[service] generated new secret key: JUoOxjoXLc4muSxXynOpTc60nWtwUI3o
```

Copy that generated licence and start the container again with it set through the environment variable. The README's example is:

```bash
docker run -d --name emitter -p 8080:8080 -e EMITTER_LICENSE=uppD0PFIcNK6VY-7PTo7uWH8EobaOGgRAAAAAAAAAAI --restart=unless-stopped emitter/server
```

Then open http://127.0.0.1:8080/keygen in a browser to generate your key. The README's warning is worth repeating: the secret key from the first run is what you use to create channel keys, and it should be treated as a credential. If you would rather build from source, the README's alternative is to clone the repository, run go get -x . and go build -x ., then execute ./emitter; it notes that gcc and musl-dev may be needed depending on your system. The Dockerfile exposes ports 4000, 8080 and 8443, so a deployment that needs the MQTT TCP listener or TLS must publish those too, not just 8080.

## Licence and the cost of staying current

Emitter is licensed under AGPL-3.0. For a self-hosted internal broker that nobody outside your organisation interacts with over a network, that is often workable. For a product where you modify Emitter and expose it to users, the network-copyleft terms are the thing to read, and this is a question for your own legal review rather than a summary here. The README does not discuss commercial licensing or an alternative licence.

Upgrade cost is shaped by the release cadence. The listed releases are v3.1 on 2024-02-02, v3.0 on 2021-12-26 and v2.8 on 2020-06-04. Major versions are years apart, and the last push to the repository was on 2026-04-29, so the codebase does receive changes between tagged releases. Practically, that means you should not plan on frequent release notes as your upgrade signal; you either track master or pin a tag and accept that fixes may land only on master. The go.mod requires Go 1.24 and pins a toolchain of go1.24.0, so a build from source needs a current Go toolchain, and the Dockerfile's builder stage is golang:alpine, which follows the current Go release.

## Where Emitter is the wrong tool

The README does not document rollback, message replay guarantees or a dead-letter mechanism. Message storage with history and message-level expiry is advertised, but the README does not state how long history is retained by default, how it is queried, or what happens when the storage backend is full. If your requirement is a durable log with offsets and consumer groups, that is Kafka territory and Emitter's storage is not described as that.

The AP stance is the second boundary. A broker that prefers availability during a partition is a poor fit for exactly-once command delivery, for financial ledgers, or for anything where a missing message is a correctness bug rather than a latency blip. The README's own framing is low latency, binary messaging and high throughput, which is a different priority order. Finally, if your clients are plain MQTT devices and you only need brokering, Emitter's storage and key model are extra surface area you will maintain without using.

## Emitter against Mosquitto and NATS

Mosquitto is the obvious comparison for anyone shopping for an MQTT broker. It is a small broker that does brokering and little else; persistence, authentication and clustering are separate concerns you assemble yourself or buy. Emitter's difference is that storage, channel keys with permissions, TLS, shared subscriptions and Prometheus or StatsD monitoring are presented as part of the broker, with a cluster formed through weaveworks/mesh gossip rather than an external coordinator. If you already run an auth service and a time-series store, Mosquitto's smaller surface is an advantage; if you do not, Emitter is fewer components.

NATS is the other useful contrast, and the difference is protocol and model. NATS has its own client protocol rather than MQTT, and its subject-based messaging and JetStream persistence are a different design from Emitter's channels, channel keys and per-message expiry. Choosing between them is mostly a question of whether your existing clients already speak MQTT and whether you want the broker to own authorisation through keys. The README does not compare Emitter to either project, so treat this as a description of approaches rather than a benchmark.

## Conclusion

Adopt emitter-io/emitter if you want one Go binary that combines an MQTT broker, message history, channel-level key permissions and Prometheus metrics, and you are comfortable with AGPL-3.0. Do not adopt it if you need a permissively licensed broker, or if you expect the MQTT feature set of a mature general-purpose broker; the README does not document which MQTT 5 features are implemented. Before committing, verify the first-run licence and secret key flow on your own host, confirm that the ports your clients need are the ones the Dockerfile exposes (4000, 8080, 8443), and read emitter.conf for the settings the README leaves unmentioned.

## FAQ

### What is emitter-io/emitter?

It is a distributed, scalable and fault-tolerant publish-subscribe platform built with the MQTT protocol, written in Go. The README lists message storage with history and message-level expiry, secure channel keys with permissions, TLS, monitoring with Prometheus and StatsD, and deployment with Docker and Kubernetes.

### How do I install emitter-io/emitter?

The README's quick start is a single docker run of the emitter/server image publishing port 8080, or a build from source by cloning the repository and running go get -x . and go build -x . before executing ./emitter. On first start with no configuration, the server generates a licence and a secret key that you then supply through the EMITTER_LICENSE environment variable or the license value in emitter.conf.

### Which ports does the emitter-io/emitter Docker image expose?

The Dockerfile exposes 4000, 8080 and 8443, and the README's docker run example publishes 8080. The keygen page the README points you to is served at http://127.0.0.1:8080/keygen.

### What licence is emitter-io/emitter released under?

The repository is licensed under AGPL-3.0. The README does not mention any alternative or commercial licence.

## Sources

- [emitter-io/emitter on GitHub](https://github.com/emitter-io/emitter)
- [License: AGPL-3.0](https://github.com/emitter-io/emitter/blob/master/LICENSE)
- [Project website](https://emitter.io)
- [README](https://github.com/emitter-io/emitter/blob/master/README.md)
- [Releases](https://github.com/emitter-io/emitter/releases)

---

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