cloops.nats 2.0.0

dotnet add package cloops.nats --version 2.0.0
                    
NuGet\Install-Package cloops.nats -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="cloops.nats" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="cloops.nats" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="cloops.nats" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add cloops.nats --version 2.0.0
                    
#r "nuget: cloops.nats, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package cloops.nats@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=cloops.nats&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=cloops.nats&version=2.0.0
                    
Install as a Cake Tool

CLOOPS NATS SDK

CI NuGet License: MIT

A modern, annotation-based SDK for building reliable distributed systems with NATS. Define your message consumers with simple attributes and let the framework handle the complexity.

Why NATS?

NATS is a powerful messaging system that enables you to build sophisticated, fault-tolerant distributed systems that are location-transparent and globally distributed.

  • Faster than HTTP - Binary protocol with lower overhead
  • Fewer hops - Direct communication without load balancers or API gateways
  • Globally distributed - Deploy applications worldwide without DNS or complex load balancing. Learn more about NATS super clusters

πŸ’‘ Learn more: Check out this podcast from nats.fm for insights into NATS architecture.

Why This SDK?

Modern developers expect annotation-based definitions and dependency injectionβ€”the same developer experience you get with REST frameworks like ASP.NET Core. This SDK brings that same simplicity to NATS, so you can focus on your business logic instead of boilerplate.

What You Get

  • ✨ Annotation-based consumers - Define subscribers with simple attributes
  • πŸ›‘οΈ Built-in backpressure - Automatic handling of traffic spikes
  • βš–οΈ Flexible load balancing - Choose between broadcasting or load balancing strategies
  • πŸš€ JetStream support - Build temporally decoupled systems with persistent messaging
  • πŸ”§ Dependency injection - Seamless integration with .NET's DI container
  • βœ… Automatic message validation - Messages with a Validate() method are automatically validated before processing. Invalid messages are never sent to your handlers
  • πŸͺ Consumer interceptors - Inspect, replace, or reject messages before handlers run
  • 🧯 Consumer exception handlers - Map handler exceptions to a NatsAck for consistent JetStream ack/nak and Core request/reply responses, while still logging the original exception and recording the invocation as a failure

🎯 Building microservices? Check out our microservices-focused SDK built on top of cloops.nats and makes building microservices a breeze!

Quick Start

Installation

Add the cloops.nats package to your .csproj file:

<PackageReference Include="cloops.nats" Version="*" />

Run dotnet restore to install the package.

πŸ’‘ Tip: For Connection Loops standard messages and subjects, you may also need cloops.nats.schema.

Examples

Broadcast Pattern (Kubernetes/Docker)

Ensure each pod/instance receives all messages by using runtime placeholders in the queue group name:

/// <summary>
/// Broadcast: Each pod gets a unique queue group, so all pods receive all messages
/// Supported placeholders: {POD_NAME}, {HOSTNAME}, {MACHINE_NAME}, {ENV:VAR_NAME}
/// </summary>
[NatsConsumer("test.broadcast", QueueGroupName = "pod-{POD_NAME}")]
public Task<NatsAck> BroadcastHandler(NatsMsg<string> msg, CancellationToken ct = default)
{
    Console.WriteLine($"[Pod {Environment.GetEnvironmentVariable("POD_NAME")}] Received: {msg.Data}");
    return Task.FromResult(new NatsAck(true));
}

Load Balancing Pattern

Distribute messages across multiple instances using the same queue group:

[NatsConsumer("test.lb", QueueGroupName = "workers")]
public async Task<NatsAck> HandleMessage(NatsMsg<string> msg, CancellationToken ct = default)
{
    Console.WriteLine($"Instance received: {msg.Data}");
    await Task.Delay(100, ct).ConfigureAwait(false); // Simulate work
    return new NatsAck(true);
}

Runtime Placeholders

The SDK resolves placeholders dynamically:

  • {POD_NAME} β†’ POD_NAME env var, falls back to HOSTNAME or machine name
  • {HOSTNAME} β†’ HOSTNAME env var, falls back to machine name
  • {MACHINE_NAME} β†’ Machine name
  • {ENV:VAR_NAME} β†’ Any environment variable (e.g., {ENV:MY_CUSTOM_VAR})

πŸ“ Note: QueueGroupName is optional. If omitted, an empty string is used, which still enables load balancing. JetStream subscriptions are always load-balanced (no broadcast support).

Timeouts and logging

CloopsNatsClient runs with NATS.Net defaults unless you pass a CloopsNatsClientOptions. Two of those defaults bite production services:

  • RequestTimeout is 5 seconds and also bounds the wait for a JetStream publish acknowledgement. A service that publishes to JetStream from a request path and is briefly starved (thread-pool, GC) can miss that window even though the server replied, and gets NatsJSPublishNoResponseException.
  • LoggerFactory is a NullLoggerFactory, so NATS.Net's own connect, reconnect, ping and retry diagnostics are discarded.

Always pass a logger factory, and raise RequestTimeout to 15-30 seconds for services that publish to JetStream from request paths:

var cnc = new CloopsNatsClient(
    url: "nats://dev.nats.cloops.in:4222",
    name: "my-service",
    creds: natsCreds,
    options: new CloopsNatsClientOptions
    {
        RequestTimeout = TimeSpan.FromSeconds(30),   // JetStream publish ack wait, request/reply
        LoggerFactory = loggerFactory,               // surfaces NATS.Net's internal diagnostics
        // CommandTimeout, ConnectTimeout are available too; anything else via the escape hatch:
        Configure = o => o with { MaxReconnectRetry = -1 },
    });

logger.LogInformation("NATS RequestTimeout={Timeout}", cnc.Connection.Opts.RequestTimeout);

Every property is optional and an unset property keeps the NATS.Net default, so existing callers using the three argument constructor are unchanged. With a LoggerFactory set (directly or through Configure) the client also logs the connection lifecycle events (ConnectionOpened, ConnectionDisconnected, ReconnectFailed, MessageDropped, LameDuckModeActivated) under the CLOOPS.NATS.CloopsNatsClient category; set LogConnectionEvents = false if you subscribe to them yourself. The client sets SubPendingChannelFullMode = Wait, so a full subscription channel applies backpressure instead of dropping messages and MessageDropped will rarely if ever fire under normal operation. The effective options are exposed as cnc.Options.

Upgrading to 2.x (NATS.Net 3.x)

cloops.nats 2.x depends on NATS.Net 3.3 (every NATS.Client.* package on the same 3.x line). 1.x depended on NATS.Net 2.6, and a service that also referenced a NATS.Net 3.x package (for example NATS.Client.OpenTelemetry) ended up with a mixed graph that fails at runtime (MissingMethodException from ordered consumers). The cloops.nats API itself is unchanged, but the NATS.Net types it exposes (Connection, JsContext, KvContext, NatsOpts in Configure) now follow NATS.Net 3.x:

  • JetStream ConsumeAsync / FetchAsync / NextAsync yield INatsJSMsg<T> instead of NatsJSMsg<T>. Code using var compiles unchanged; code naming NatsJSMsg<T> must switch to INatsJSMsg<T>.
  • Request-reply defaults to NatsRequestReplyMode.Direct, and the default subscription pending capacity is 16384 (was 1024). cloops.nats still sets SubPendingChannelFullMode = Wait.
  • Classes that implement INatsJSContext, INatsJSStream, INatsJSConsumer or INatsSvcServer themselves (test doubles) must implement the members NATS.Net 3.2 / 3.3 added.
  • Any other NATS.Client.* package the service references directly must move to 3.x as well; prefer the same version as cloops.nats (3.3.0).

See the NATS.Net 3.0 release notes for the full list.

Changelog

Every release and change is recorded in CHANGELOG.md, newest first. Every change or PR to this repository must add an entry there; see AGENTS.md for the format.

Learn More

  • πŸ“– Examples - See real-world usage patterns
  • πŸ“š Full Documentation - Detailed guides, setup instructions, and API reference

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on cloops.nats:

Package Downloads
cloops.microservices

Opinionated SDK to effortlessly build lean highly performant cloud native microservices

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 1,072 10/12/2026
1.4.13 72 10/12/2026
1.3.12 322 9/13/2026
1.2.11 214 9/7/2026
1.1.9 2,391 7/26/2026
1.1.8 139 7/26/2026
1.1.7 868 7/8/2026
1.1.6 6,711 12/14/2025
1.1.5 236 12/14/2025
1.1.4 236 12/14/2025
1.1.3 189 12/14/2025
1.1.2 190 12/14/2025
1.1.1 196 12/13/2025
1.0.42 391 11/17/2025
1.0.41 302 11/9/2025
1.0.40 239 11/9/2025
1.0.39 181 11/8/2025
1.0.38 215 11/8/2025
1.0.37 204 11/8/2025
1.0.36 253 10/12/2025
Loading failed