Open-source project
AdaptiveConsulting/Aeron.NET avatar
AdaptiveConsulting/Aeron.NET

Aeron.NET is a .NET client for a messaging transport built around zero allocation

Efficient reliable UDP unicast, UDP multicast, and IPC message transport - .NET port of Aeron

524 stars99 forksC#Apache-2.0

At a glance

What is it?
Aeron.NET is a C# port of the Aeron client, an efficient and reliable transport for UDP unicast, UDP multicast and IPC built on a separate media driver process that talks to clients over shared memory. It suits .NET teams that need predictable low latency messaging and can accept the operational cost of the driver.
Who is it for?
Adopt Aeron.NET if your .NET system needs sustained high throughput with predictable, measurable latency and you can run the media driver alongside your application. Do not adopt it if you need a broker-based queue with durable storage and per consumer offsets, since Aeron deliberately has none of that, and do not expect a managed-only deployment, because the driver is a separate 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 last received commits 29 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 October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two parts, one process boundary you cannot ignore

Aeron comes in two parts, the media driver and the client, and the split is the first thing to understand. The driver runs in its own process and communicates with the client directly via shared memory. It sends and receives messages across the network to other drivers, or routes messages to other clients on the same host.

So this is not a client library that opens sockets. The .NET code publishes and subscribes to logical channels and stream identifiers, and the driver does the network work, the shared memory transport, and the fan out to local subscribers. The consequence is operational before it is anything else: you are running a second process, and in many deployment topologies a second machine, alongside your application.

The repository layout reflects that. There is a driver/ directory with a start-media-driver.bat script, a src/ directory holding the client and the samples, scripts/ for the sample batch files, images/ for the architecture diagram the readme refers to, and tools/ plus a Directory.Build.props for build configuration. The build tooling is also visible at the top level, with a .csharpierrc.json and .csharpierignore for the CSharpier formatter, an .editorconfig, a SonarLint.xml for SonarLint analysis, and a .tool-versions file for tool version pinning.

The project is Apache-2.0 licensed, the default branch is master, and the last push was on 2026-09-24, the same day as the 1.52.2 release, with 1.51.0 in June 2026 and 1.49.0 in October 2025. It is a port of the Aeron Client from the aeron-io project, and the readme links the original, so the .NET client tracks a Java lineage rather than defining its own protocol.

The performance claim, and what the design buys you

The readme states that performance is the key focus, and that Aeron is designed to have the highest throughput with the lowest and most predictable latency possible of any messaging system. Then it gives the mechanism, which is the part that matters: Aeron is designed not to perform any allocations after the initial set-up, which means less time is spent garbage collecting and as a result latency is kept down.

That is a specific and testable design commitment, and it explains several API choices you would otherwise have to reverse engineer. The publisher writes into an UnsafeBuffer over a byte array you allocated yourself, and offers the message with the length you computed:

csharp
const string channel = "aeron:ipc";
const int streamId = 42;

UnsafeBuffer buffer = new UnsafeBuffer(new byte[256]);

using(Aeron aeron = Aeron.Connect())
using(Publication publisher = aeron.AddPublication(channel, streamId)) {
  int messageLength = buffer.PutStringWithoutLengthUtf8(0, "Hello World!");
  publisher.Offer(buffer, 0, messageLength);
}

The buffer is not allocated per message. The message is written into it and offered. The subscription side is symmetric, with a fragment handler that reads from an IDirectBuffer at an offset and a length, and a poll loop that returns a count of processed fragments:

csharp
using(Subscription subscriber = aeron.AddSubscription(channel, streamId)) {
  while(subscriber.Poll(PrintMessage, 1) == 0) {  
      Thread.Sleep(10);
  }
}

The fragment handler concept is the part that carries the reliability model. A fragment handler is a delegate used for processing data that has been received, and the buffer will either contain a whole message or a fragment of a message to be reassembled. Aeron is a fragment-oriented transport, so a message larger than the maximum message length arrives in pieces, and the client reassembles it.

The consequence for a .NET developer is that the API is not a queue API. There is no broker, no consumer group, no offset to store, no per-message acknowledgement callback. There is a channel, a stream id, and a poll loop that tells you how many fragments were handled.

Installing the client and the driver, and the Java dependency

The client installs from NuGet as a package called Aeron.Client, and the readme gives the package manager command:

bash
    PM> Install-Package Aeron.Client

The driver comes from a separate package, Aeron.Driver, installed the same way. That package creates a directory in your project with a bat file to launch the driver, and if you have the source checked out you can run driver/start-media-driver.bat directly instead.

The dependency that catches people is Java. To run the media driver you need a Java 8 JRE installed, and the readme links the Oracle Java 8 JRE download. So the .NET client talks to a driver that is a Java process. That is the price of porting a Java transport to .NET rather than rewriting it, and it is the single fact that most affects where you can deploy it. A container that ships only the .NET runtime cannot run the driver.

The samples need building first, and the readme says you need Visual Studio 2017 installed, then gives the batch script to run:

bash
    scripts/build.bat

The driver must be running before the samples do anything, since every sample, including the IPC throughput one, talks to it. Once built, the hello world sample runs with scripts/hello-world.bat, and the readme shows the expected output line carrying the message, the stream id, the session, the term id and the term offset, followed by a prompt to press any key.

For building the library itself from source, the readme asks for Visual Studio 2017 Update 3 and notes that the tooling has not caught up so you also need the last .NET Core SDK. You open src/Adaptive.Aeron.sln and build the solution, and the final note is a performance instruction: for best performance, build in x64 release mode.

The samples as the specification

The readme's samples section is worth more than most API documentation, because it shows what the library does under load rather than what it can do.

The hello world sample sends and receives one message, and its source is at src/Samples/Adaptive.Aeron.Samples.HelloWorld/HelloWorld.cs. The throughput sample shows the overall throughput of the client and driver, sending messages via aeron:ipc which is designed for interprocess communication. It runs two threads which publish and subscribe 32-byte messages and every second prints out the number of messages and total number of bytes that were sent and received, and the readme shows output in the fourteen to fifteen million messages per second range over a one second duration. That figure is from the maintainer's own machine, so treat it as an indication of the order of magnitude rather than a number to plan against.

The ping-pong sample is the one for latency. It starts pong, which listens for messages and replies to each one, then starts ping, which sends messages carrying the current time and records the latency when the response arrives. After a million messages the sample presents a histogram, and the readme includes one with a mean of 15.195 microseconds and a standard deviation of 46.974 in microseconds, with a maximum of 5021.695 and a hundred thousand samples in the tail. The histogram format is HdrHistogram, and the readme points at the HdrHistogram plot file viewer so you can upload your own results and get a chart.

Two details in that output are worth pausing on. The mean is in microseconds, so the typical round trip is fifteen millionths of a second, which is the domain this library is built for. The maximum is over five milliseconds, and the standard deviation is three times the mean, which is the honest shape of a tail latency distribution. Any design that depends on Aeron needs to account for that tail, not the mean.

Where Aeron.NET is the wrong choice

The first limitation is that Aeron has no persistence and no delivery guarantee in the way a broker gives you. It is a transport, and reliability is handled through Aeron features such as retransmission and heartbeats rather than by a store that keeps your messages. If your requirement is a durable queue that survives a consumer restart, or per message acknowledgement with redelivery, or replay from an offset, this is the wrong tool and you want a broker instead. The readme describes Aeron as an efficient reliable UDP unicast, UDP multicast and IPC message transport, and reliable here means the transport layer does its job, not that your messages are stored for later.

The second limitation is the Java driver, which we have already touched on. It means the deployment is two runtimes, it means the driver process is a failure domain you have to supervise, and it rules out several lightweight deployment shapes.

The third limitation is the .NET maturity. The readme asks for Visual Studio 2017 Update 3 and a .NET Core SDK because the tooling has not caught up, and the build instructions are still an open a solution and click build workflow. A port that tracks a Java upstream will also track it in version, which means the .NET release cadence follows whatever the Java project does. The release numbers here, 1.52.2, show the port versioning in step with Aeron itself rather than on a .NET independent schedule.

The realistic alternative is not another high performance transport, it is a broker that speaks a .NET native protocol. Something in the Kafka or RabbitMQ family, where the .NET client is a first class library with an active maintainer and the persistence and acknowledgement semantics you need out of the box. The difference in approach is the trade you are making. Aeron gives you a transport that sits close to the wire, with shared memory between client and driver and no allocation after setup, and asks you to build durability, replay and flow control yourself if you need them. A broker gives you those as the product, at the cost of an extra network hop, a disk in the path, and latency that is measured in milliseconds rather than microseconds. If your workload is a market data feed, a telemetry path or an in-process command bus, Aeron is the right shape. If it is order processing that must not lose an order, it is not.

Editorial conclusion

Adopt Aeron.NET if your .NET system needs sustained high throughput with predictable, measurable latency and you can run the media driver alongside your application. Do not adopt it if you need a broker-based queue with durable storage and per consumer offsets, since Aeron deliberately has none of that, and do not expect a managed-only deployment, because the driver is a separate process. Before you start, confirm you can satisfy the Java 8 JRE requirement for the driver, install the Aeron.Driver package, and read the throughput and ping-pong samples to see the latency profile on your own hardware.

Frequently asked questions

What does Aeron.NET do and what is the Aeron client?

It is a .NET port of the Aeron client, an efficient and reliable transport for UDP unicast, UDP multicast and IPC messaging. The design goal is the highest throughput with the lowest and most predictable latency, achieved by performing no allocations after the initial set up so that less time is spent garbage collecting.

How do I install Aeron.NET and the media driver?

Install the client with `PM> Install-Package Aeron.Client` and the driver with `PM> Install-Package Aeron.Driver`, which creates a directory with a bat file to launch the driver, or run driver/start-media-driver.bat from a source checkout. The driver needs a Java 8 JRE installed, since it is a separate process that talks to the client over shared memory.

How do I publish and subscribe with Aeron.NET?

You connect with Aeron.Connect, add a publication or a subscription for a channel and stream id, and poll the subscription with a fragment handler. The fragment handler is a delegate that receives an IDirectBuffer with an offset and length, and the buffer holds either a whole message or a fragment of one to be reassembled.

What do the Aeron.NET samples demonstrate?

Hello world sends and receives a message, the throughput sample runs two threads publishing and subscribing 32-byte messages over aeron:ipc and prints messages and bytes per second, and the ping-pong sample measures round trip latency and presents an HdrHistogram after a million messages. The samples must be built with scripts/build.bat and need Visual Studio 2017.

Is Aeron.NET maintained and under what licence?

The repository is not archived and the last push was on 2026-09-24, the same day as the 1.52.2 release, after 1.51.0 in June 2026 and 1.49.0 in October 2025. The project is Apache-2.0 licensed and is a port of the Aeron Client from the aeron-io project, so it follows that upstream.

Official sources

  1. AdaptiveConsulting/Aeron.NET on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
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/adaptiveconsulting-aeron-net.svg)](https://hysenlabs.com/projects/adaptiveconsulting-aeron-net)

Was this useful?