vernemq/vernemq: an Erlang MQTT broker built for clustered deployments
A distributed MQTT message broker based on Erlang/OTP. Built for high quality & Industrial use cases. The VerneMQ mission is active & the project maintained. Thank you for your support!
At a glance
- What is it?
- A distributed MQTT broker covering versions 3.1, 3.1.1 and 5.0, with shared subscriptions, session balancing and pluggable backends for the databases an industrial deployment already runs.
- Who is it for?
- VerneMQ is a broker to evaluate when your devices outnumber your operator patience and you need clustering, shared subscriptions and per-session load spreading rather than a single tidy process.
- Can I use it commercially?
- Yes. Apache-2.0 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 received new commits within the last day.
- What is it written in?
- Mainly Erlang, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three protocol versions, one broker process
The README's opening explains what MQTT is and where it came from: an extremely simple and lightweight publish/subscribe protocol invented at IBM and Arcom, now Eurotech, to connect restricted devices in low bandwidth, high latency or unreliable networks. It also makes a small correction worth repeating, that MQTT used to stand for MQ Telemetry Transport but no longer is an acronym.
VerneMQ implements the 3.1, 3.1.1 and 5.0 specifications, which means a fleet with old firmware and a new application can share one broker. The feature list is long enough that it is worth grouping by what problem each item solves.
Protocol correctness: all three quality of service levels, session takeover for multiple sessions per client ID, FIFO or LIFO queue handling, shared subscriptions, and for MQTT 5.0 clients specifically the AUTH mechanism, message expiration, delayed Last Will and Testament, request and response flows, topic aliases, flow control, subscription flags including Retain as Published and No Local, subscriber identifiers, and all the property types such as user properties and reason strings.
Clustering: cluster support, session balancing, and a cluster status web page. That combination is what separates this class of broker from a single-process one.
Six database backends are supported out of the box
The feature list names authentication and integration for MongoDB, Redis, MySQL, PostgreSQL and CockroachDB, plus a Memcached integration. Any one of those being a checkbox rather than a plugin is the single most useful fact for an industrial deployment, because industrial deployments already have one of those databases and would rather not add a second datastore to hold credentials.
The other structural features point at protecting the broker rather than at features for clients. Message load regulation and message load shedding for system protection are the pair that matter: regulation throttles, shedding drops, and having both means a flood degrades predictably instead of taking the node down. Offline message storage based on LevelDB covers the case where a subscriber reconnects expecting queued messages.
Logging is configurable to console, files and syslog, metrics can be reported to Graphite, and there is an administration HTTP API plus real-time MQTT session tracing. That last one is underrated. Being able to watch individual sessions live turns a support question about a stuck client from guesswork into something you can see happening.
Full multitenancy is also listed, and the `docker-compose.yml` in the repository root is a good hint at how the project expects those backends to be wired during testing. It stands up Postgres, MySQL 5.7.33, Memcached, Mongo and Redis with test credentials, which is the quickest way to see which backends the test suite actually exercises.
Building from source needs Erlang/OTP 25 to 28
The quick start assumes you have the source tree, and the build requirement is specific: Erlang/OTP 25 through 28, `libsnappy-dev` installed, and a C compiler for Eleveldb. On Debian that means `build-essential`. Once those are in place the build is two commands:
$ cd $VERNEMQ
$ make relThe Makefile shows why that works. It resolves the local `rebar3`, warns if no `erl` is on the path, and the `rel` target concatenates `vars.config` into `vars.generated` with an `app_version` derived from `git describe --tags --always`. So the version baked into the release comes straight from your git history, which is the behaviour you want when you are chasing a bug report from a specific commit.
There is an `OVERLAY_VARS` hook that appends an extra config file to the generated vars, and a `dev%` pattern rule that builds a node-specific development release through the `gen_dev` script and `vars/dev_vars.config.src`. For debugging there is `debug_build`, which builds a release with the debugger and wx available.
Starting the broker is the second documented step:
$ cd $VERNEMQ/_build/default/rel/vernemq
$ bin/vernemq startThe README flags one operational detail that is easy to miss and annoying later: that release directory is a complete self-contained instance of VerneMQ and Erlang, and it is strongly suggested you move it out of the source tree before running it in production. Once running, `http://localhost:8888/status` returns the status page.
2.2.1 fixes a shared subscription regression from 2.1.0
The release notes for 2.2.1, published on 2026-09-17, read like a list of things that broke under load, which is a good sign about what the project tests. The headline item is a fix for stale local shared subscriptions after a trie restart, described in the notes as a regression introduced in 2.1.0. Shared subscriptions are load-bearing in a clustered broker, and stale entries mean one subscriber silently stops receiving its share.
The other fixes are equally specific. Non-zero message ids are now enforced, which is a specification compliance item rather than a feature. Labelless Graphite metrics are aggregated into a summary instead of being dropped, so monitoring does not lose data when a metric lacks a label. The `vmq_swc` garbage collection on standalone nodes was fixed by initialising the local watermark row. And webhook calls gained a `connect_options` list defaulting to `[{no_delay, true}]`, which the notes attribute to a Nagle's algorithm performance regression in Hackney. That last one is the kind of fix that matters on a satellite link.
Version 2.2.0, from 2026-08-09, is broader and includes a fix for clients rapidly connecting and disconnecting, a parallel internode cluster readiness check, disabling the retain expiry check by default, and handling of v5 properties in the auth-on-publish path.
The repository also ships a `changelog.md`, and GitHub reports the last push on 2026-09-17 with the repository not archived. The README says releases are announced based on bugfixes and features, with bugfix releases cut between minor ones when something urgent is pending.
Apache2 licence, plus a commercial option
The README states that VerneMQ is Apache2 licensed, and the repository root carries `LICENSE.txt` along with `3rd-party-licenses.txt` and `THANKS`. GitHub records the repository as Apache-2.0, so the licensing position is unambiguous, which is not something to take for granted with broker software.
The nuance is the commercial layer. The README points to a services page for commercial support options, and the release schedule section says custom releases can be offered for commercial users. Both statements can hold at once. Open source for the broker, paid for support, guaranteed fixes, or custom builds. The projects to watch for confusion here are enterprise editions with feature differences, and this is not one: the repository contains the full broker.
That is relevant when you evaluate alternatives, since the related search terms around this project include VerneMQ versus EMQX and VerneMQ versus RabbitMQ. RabbitMQ is AMQP and VerneMQ is MQTT, so they are not substitutes for each other unless you add a bridge. EMQX is a closer comparison, and there the differentiator tends to be the Erlang runtime on one side and the breadth of broker features on the other.
Support options matter more for a broker than for most components, because a broker outage is a fleet-wide outage. The README's own recommendation is to search the VerneMQ Users Google group and the documentation before asking anywhere else.
Editorial conclusion
VerneMQ is a broker to evaluate when your devices outnumber your operator patience and you need clustering, shared subscriptions and per-session load spreading rather than a single tidy process. The two decisions that shape everything else are already made for you: Erlang/OTP gives you supervision trees and hot code loading, and the authentication and integration story is wide enough that MongoDB, Redis, MySQL, PostgreSQL, CockroachDB and Memcached are all first-class backends rather than plugins you write. Version 2.2.1 shipped on 2026-09-17 and GitHub reports the last push the same day, so the project is moving. Note the licensing detail: the README says Apache2 and there is a `LICENSE.txt` in the root, but there are also commercial support options and custom releases offered by the vendor. Build with `make rel` on Erlang/OTP 25 through 28, start the resulting release with `bin/vernemq start`, and read docs.vernemq.com before you configure a listener, since the README covers installation and nothing about production settings.
Frequently asked questions
What is MQTT and what is its purpose?
MQTT is a lightweight publish/subscribe messaging protocol created at IBM and Arcom to connect constrained devices over low bandwidth, high latency or unreliable links. VerneMQ's README describes it as the reliable message hub layer for an IoT platform or a product fleet, and it implements versions 3.1, 3.1.1 and 5.0.
Is MQTT better than HTTP for IoT devices?
The two solve different problems. HTTP request and response suits occasional requests over reliable links, while MQTT keeps a persistent connection open and pushes messages to subscribers, which suits small frequent payloads on expensive links. Many deployments use both, with HTTP for commands and MQTT for telemetry.
What is the difference between MQTT and Kafka?
Kafka is a partitioned log for durable event streams that you replay, while MQTT is a broker for delivering messages to connected subscribers, with topic hierarchies and quality of service levels. Kafka is a good fit for analytics pipelines, MQTT for device fleets, and the two are often combined rather than swapped.
Official sources
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.
[](https://hysenlabs.com/projects/vernemq-vernemq)