Library / SDK
zeromq/netmq avatar
zeromq/netmq

netmq: version 3 lives in another repository, the flagship example is never closed, and the endian switch is mutually exclusive with ZeroMQ

A 100% native C# implementation of ZeroMQ for .NET

3,179 stars763 forksC#NOASSERTION

At a glance

What is it?
NetMQ is a native C# port of ZeroMQ, and its README is mostly a pointer list: to the ZeroMQ Guide, to a wiki, to a mailing list, to a bug tracker, and to a blog series written in 2014. What the file does contain is a compatibility warning that nobody can escape, a code sample that does not compile, and a reference to a second repository for the previous major version.
Who is it for?
Use NetMQ when you want ZeroMQ's socket model in C# and you are starting a new project, since the default big endian behaviour is what interoperates with every other ZeroMQ implementation. Read the compatibility note before you upgrade anything, because the only way to talk to a pre-3.3 peer is to give up ZeroMQ compatibility, and that trade is not available on a mixed network.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 19 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • zeromq/netmq3,179 ★ · -1
Star history
Repository2026-09-242026-11-14
zeromq/netmq3.2k3.2k

-1 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Version 3 is a different repository under a different organisation

The versioning section explains that two versions are maintained, and then immediately hands one of them to somebody else.

Version 3 is described as the stable version, and version 4 as the same thing without obsolete code. A wiki page covers migrating between them, and both are published to the same package feed.

Then the sentence that matters for anyone crossing that line: this repository is for version 4, and for version 3 the reader is sent to a different repository, under a different organisation, with a different name.

That is a heavier boundary than a major version usually is. A consumer moving from 3 to 4 is not switching a version constraint, they are switching where the source comes from, which name the import root has, and which release tags they can pin. A fork of one cannot be merged with a fork of the other without reconciling two histories.

It also means the compatibility note below, which describes a break inside the 3.x line, applies to a codebase this repository does not contain.

The example at the centre of the README does not compile

There is exactly one code sample in this document, and it has two problems.

code
using (var server = new ResponseSocket("@tcp://localhost:5556")) // bind
using (var client = new RequestSocket(">tcp://localhost:5556"))  // connect

Those two lines are fine, and the address prefixes are the mechanism rather than decoration, which the next section covers. The problem is what comes after them.

The sample creates a response socket and a request socket in a using block, sends a frame from the client, receives it on the server, sends a reply back, and receives that. Then it stops. The using block is never closed, there is no closing brace, and the final statement ends without a semicolon.

So the one piece of executable documentation in the README does not compile, which is worth knowing before you copy it. The rest of the sample is a faithful request and response round trip, so the fix is two characters rather than a rewrite.

It is also the only place a reader sees what a socket looks like. Everything else in the file is prose or a link, so the sample carries the entire conceptual weight of the introduction.

Bind and connect are the same string with a different first character

The example encodes which side of the connection a socket takes in the address itself, which is the single most surprising thing about this API for someone arriving from a socket library that separates the two.

An at sign in front of the protocol means bind, and a greater-than sign means connect. The server in the sample takes one address, the client takes the other, and both point at the same host and port.

That design has a practical consequence that the introduction hints at rather than states: a bind address and a connect address are not interchangeable strings, so the same endpoint has two spellings, and swapping them silently changes which side of the socket pair you are on. In a deployment where configuration is templated, that is the kind of error that produces a socket that connects successfully to nothing.

It also explains why the transport story is described as seamless access to multiple transport protocols. The protocol prefix is part of the same address string that carries the bind or connect role, so changing either is an edit to one value.

The compatibility switch lets you reach old peers or ZeroMQ, never both

One note in this README is longer and more consequential than the introduction, and it is about a decision that cannot be dodged.

Since version 3.3.07, number serialization changed from little endian to big endian in order to be compatible with ZeroMQ. Any NetMQ version prior to 3.3.0.7 is not compatible with the new version.

There is a way to support older peers: set the Endian option on a NetMQ socket to little endian. The same sentence then says that doing so makes it incompatible with ZeroMQ. So the option does not restore compatibility across the board, it moves the incompatibility from old NetMQ peers to every ZeroMQ implementation on the network.

The recommendation follows: update to the latest version and use big endian, which is now the default.

Two details in that section are worth noting. The version is written two ways, as 3.3.07 in the first sentence and 3.3.0.7 in the second, so anyone scripting a version check has to guess which form is canonical. And the note sits at the bottom of the file, after the consulting table, where a wire format break of this kind is unlikely to be found.

The documentation is one guide, one volunteer's site, and a 2014 blog series

The documentation section is a list of links, and the links have different vintages.

The instruction comes first: before using NetMQ, make sure to read the ZeroMQ Guide. That is a deliberate delegation, since NetMQ is a port and its intended audience is assumed to already know the protocol it implements.

Then the NetMQ documentation itself, hosted on Read the Docs, with a credit to a named individual who agreed to do the documentation. That credit tells you the documentation is a single person's work rather than a team effort, which matters when you are evaluating whether it will be kept current.

Samples live in yet another repository, and the blog links are a mix of one contributor's category page and six posts from a single blog, all dated August and September 2014. The series is numbered, and the numbering is not quite complete: the posts run from a first introduction through a second on socket types, a third on socket options, a fourth on multiple socket polling, then an unnumbered post on sending from multiple sockets, and then a sixth on divide and conquer. Number five is missing and one post has no number at all.

Two continuous integration systems are configured at once

The root of the repository contains configuration for two build systems, and only one of them is current.

The badge at the top of the README points at a GitHub Actions workflow, and there is a .github directory behind it.

Beside that, an appveyor.yml file sits in the root. AppVeyor is the older hosted Windows build service, and its configuration has outlived the migration. The tree carries codecov.yml as well, so coverage reporting was configured for both systems.

This is the same pattern most repositories reach after changing CI providers: the new configuration is added, the old one stays because deleting it was never urgent. It costs nothing at build time and it does cost a reader, because a file in the root is a claim that something still depends on it.

The rest of the root is documentation-shaped. There is a .readthedocs.yml beside an mkdocs.yml, so the Read the Docs site is built with MkDocs from the docs directory. AUTHORS.md and CONTRIBUTING.md both sit next to README.md, which means the contribution rules exist in two places.

Coding standards are prose, and the process is a named specification

The contributing section is short and specific, and it duplicates a file in the root.

Process first: the project uses the C4.1 process, linked to a specification in the ZeroMQ RFC archive, and the instruction is to read it before contributing. The ownership section repeats the same instruction, so the requirement appears twice.

Standards next, and they are precise: C# styles, camelCase for variables and fields with an m_ prefix for instance members and an s_ prefix for static fields, PascalCase for methods, classes, and constants. Then two settings arrive in one garbled clause, asking the reader to use Insert Spaces and 4 for tab and indent size.

None of that is backed by a configuration file. There is no editor configuration file in the root listing, so the naming convention and the indentation rule exist only as sentences, and the naming convention in particular is the kind of thing a linter would enforce.

Three further ways to help are offered: join the mailing list and be active in it, write tutorials in the wiki, and write about the project in your own blog and open a pull request adding a link at the bottom of the README. That last one is why the blog series and the support table below it grow over time.

Support is a table with one row, naming the founder and maintainer, and one instruction: if you provide support or consulting, add yourself by pull request.

Editorial conclusion

Use NetMQ when you want ZeroMQ's socket model in C# and you are starting a new project, since the default big endian behaviour is what interoperates with every other ZeroMQ implementation. Read the compatibility note before you upgrade anything, because the only way to talk to a pre-3.3 peer is to give up ZeroMQ compatibility, and that trade is not available on a mixed network. And plan your repository boundary now: the previous major version is not a branch of this one, it is a different project under a different organisation, so an upgrade across it is a migration of sources as well as packages.

Frequently asked questions

What is ZeroMQ used for?

This repository does not describe ZeroMQ itself; it tells you to read the ZeroMQ Guide before using NetMQ. What it says about its own library is that NetMQ extends the standard socket interfaces with features traditionally provided by specialised messaging middleware, including an abstraction of asynchronous message queues, multiple messaging patterns, message filtering through subscriptions, and access to multiple transport protocols.

Which is better for messaging, gRPC or ZeroMQ?

No comparison with gRPC appears anywhere in this repository. The only relationship it states is that NetMQ is a 100 percent native C# port of ZeroMQ, and that one of its own changes, in version 3.3.07, switched number serialization to big endian specifically to become compatible with ZeroMQ.

netmq vs rabbitmq

Nothing in the readme compares NetMQ with RabbitMQ or names it. What the file offers as a position is that NetMQ sockets provide an abstraction of asynchronous message queues, multiple messaging patterns, and message filtering through subscriptions, with the surrounding tooling being a mailing list, a wiki, and a YouTrack instance.

What is the difference between NetMQ 3 and NetMQ 4?

Version 4 is the same as version 3 without obsolete code. Both are maintained and both are on the same package feed, with a wiki page on migrating. The version 3 line lives in a separate repository, so crossing that boundary means changing where the source comes from as well as which version you take.

What changed in NetMQ 3.3.07?

Number serialization changed from little endian to big endian to be compatible with ZeroMQ, and any earlier version is not compatible with the result. A socket's Endian option can be set to little endian to support older peers, though that makes it incompatible with ZeroMQ, so the readme recommends updating and keeping big endian, which is the default.

Official sources

  1. Issues
  2. README
  3. Releases
  4. zeromq/netmq on GitHub
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/zeromq-netmq.svg)](https://hysenlabs.com/projects/zeromq-netmq)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/zeromq-netmq.svg)](https://hysenlabs.com/projects/zeromq-netmq)

Was this useful?