Caudal.Diagnostics 0.1.0-preview.2

This is a prerelease version of Caudal.Diagnostics.
dotnet add package Caudal.Diagnostics --version 0.1.0-preview.2
                    
NuGet\Install-Package Caudal.Diagnostics -Version 0.1.0-preview.2
                    
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="Caudal.Diagnostics" Version="0.1.0-preview.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Caudal.Diagnostics" Version="0.1.0-preview.2" />
                    
Directory.Packages.props
<PackageReference Include="Caudal.Diagnostics" />
                    
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 Caudal.Diagnostics --version 0.1.0-preview.2
                    
#r "nuget: Caudal.Diagnostics, 0.1.0-preview.2"
                    
#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 Caudal.Diagnostics@0.1.0-preview.2
                    
#: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=Caudal.Diagnostics&version=0.1.0-preview.2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Caudal.Diagnostics&version=0.1.0-preview.2&prerelease
                    
Install as a Cake Tool

<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="docs/assets/banner-dark.svg"> <img src="docs/assets/banner-light.svg" alt="Caudal — bounded, observable async pipelines for .NET" width="560"> </picture> </p>

<p align="center"> <a href="https://github.com/nicoseijas/Caudal/actions/workflows/ci.yml"><img src="https://github.com/nicoseijas/Caudal/actions/workflows/ci.yml/badge.svg" alt="ci"></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT license"></a> </p>

Caudal (Spanish): the volume of water flowing through a channel per unit of time.

Caudal is a .NET library for building bounded, cancellable, observable async pipelines. It is aimed at the code most services end up writing by hand — a SemaphoreSlim to limit concurrency, Task.WhenAll to fan out, a Channel<T> to connect stages — and at the four problems that code keeps getting wrong:

  1. Bounded concurrency — never more in-flight work than you asked for.
  2. Real backpressure — a fast producer blocks instead of filling memory.
  3. Correct cancellation and shutdown — no orphaned tasks, no swallowed exceptions.
  4. Operational diagnostics — you can explain a slow pipeline without adding logs to your own code.

Status: pre-release. The full 0.1–0.3 API surface from the roadmap is implemented and tested (151 tests, all packages build warning-clean) and preview packages are on NuGet. The contracts in docs/SEMANTICS.md stay open to change until 1.0 — preview releases break deliberately when a contract needs fixing. The build order and exit criteria are in ROADMAP.md.

What it looks like

await source
    .ToFlow(capacity: 128)          // bounded buffer: producer waits when full
    .SelectAsync(
        ProcessAsync,
        concurrency: 8)             // at most 8 concurrent invocations, always explicit
    .ForEachAsync(
        SaveAsync,
        cancellationToken);         // one token stops producer, workers, and sink

Pipelines are built on IAsyncEnumerable<T> at the edges and Channel<T> internally. Channel<T> is an implementation detail and is not part of the public API.

The operator that best shows why Caudal exists is LatestByKey, for real-time feeds where stale items should be replaced rather than queued:

priceUpdates
    .ToFlow(capacity: 1_024)
    .LatestByKey(x => x.Symbol, maximumKeys: 1_000)  // at most one pending item per key, bounded to 1,000 keys; newer replaces older
    .SelectAsync(CalculateIndicatorsAsync, concurrency: 8)
    .Batch(maximumSize: 100, maximumDelay: TimeSpan.FromMilliseconds(50))
    .ForEachAsync(UpdateDashboardAsync, ct);

Design principles

The full contract is in docs/SEMANTICS.md. The short version:

  • No buffer is unbounded by default.
  • Every operation accepts a CancellationToken.
  • Concurrency is always explicit — there is no default parallelism.
  • Ordering is never preserved by accident; you opt in with PreserveOrder.
  • An exception cannot disappear silently. Error handling is a per-stage policy: Stop, Skip, or Capture (failures become FlowResult<T> values).
  • Completing a pipeline means every internal task has finished or been cancelled.
  • Telemetry never changes semantics.
  • Each operator documents its behavior under saturation.

Time-based operators (Debounce, Throttle, Sample, IdleTimeout) depend on TimeProvider, so they are testable with a fake clock and no real delays. Resilience is an integration with Microsoft.Extensions.Resilience, not a reimplementation of Polly.

When not to use Caudal

Caudal is deliberately small: the goal is around ten operators with precise semantics, not a partial Rx. It is the wrong tool when:

  • the work is small, sequential, CPU-bound loops — a plain loop wins;
  • the collection is small and already materialized — Task.WhenAll is fine;
  • you need concurrency but no backpressure, batching, or per-key semantics — Parallel.ForEachAsync is enough;
  • you need a full reactive event system — use Rx.

The benchmark suite under benchmarks/Caudal.Benchmarks measures the cost of the abstraction against all of these; see docs/when-not-to-use.md for the full reasoning and docs/benchmarks.md for how to run the suite and read its results honestly.

Packages

Package Contents
Caudal.Core Sources, operators, sinks, error model
Caudal.Diagnostics OpenTelemetry metrics, FlowSnapshot, pipeline visualization
Caudal.Resilience Polly v8 / Microsoft.Extensions.Resilience integration
Caudal.RateLimiting RateLimit / RateLimitBy over System.Threading.RateLimiting
Caudal.Testing Controlled sources, AsyncGate, virtual time, pipeline assertions

Documentation

  • docs/SEMANTICS.md — the behavioral contract: backpressure, errors, cancellation, completion, ordering.
  • ROADMAP.md — phases, exit criteria, and what ships in each version.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  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 Caudal.Diagnostics:

Package Downloads
Caudal.Testing

Deterministic testing utilities for Caudal flows: controlled sources, async gates, virtual time, and pipeline assertions that reproduce races stably.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-preview.2 77 7/31/2026