EdgeSync.Buffer 1.0.2

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

EdgeSyncBuffer

Offline-first IoT data pipeline for .NET — guaranteed ordered delivery despite connectivity interruptions.

NuGet NuGet Downloads CI License: MIT


The Problem

When an IoT device at a branch location loses connectivity to the cloud, what happens to the telemetry it generates?

In most .NET IoT deployments — it is silently dropped.

MQTTnet's ManagedClient reconnects automatically, but there is no built-in mechanism to:

  • Buffer messages locally during outages
  • Persist them to disk across process restarts
  • Replay them in guaranteed chronological order when connectivity returns

In compliance-sensitive environments — financial institution surveillance, healthcare monitoring, industrial safety — that silent loss has real regulatory and operational consequences.


The Solution

EdgeSyncBuffer provides an offline-first write guarantee:

Write always succeeds locally
         ↓
Entries buffered in-memory + persisted to disk
         ↓
Connectivity restored → all entries delivered to cloud
         ↓
Guaranteed sequence-number ordering — not FIFO, not timestamp order

Why sequence numbers instead of timestamps?

Clock drift at edge devices during connectivity outages is common. A device that reconnects after an NTP correction may have timestamps that appear out of sequence. Sequence numbers are assigned at write time and are immune to clock drift — ensuring correct ordering regardless of device clock state.

This is the key insight missing from most IoT buffer implementations.


Installation

dotnet add package EdgeSync.Buffer

Requires .NET 8.0 or later.


Quick Start

using EdgeSync;

// 1. Define your telemetry type
public record CameraEvent(
    string CameraId,
    string EventType,
    DateTime Timestamp,
    float Confidence) : ITimestamped;

// 2. Define your cloud upload function
Task<SyncResult> UploadToCloud(IEnumerable<CameraEvent> batch, CancellationToken ct)
{
    // Your Azure IoT Hub, AWS IoT Core, or REST API call here
    await myCloudService.SendBatchAsync(batch, ct);
    return SyncResult.Ok();
}

// 3. Create the buffer
await using var buffer = new EdgeSyncBuffer<CameraEvent>(
    options: new EdgeSyncOptions
    {
        MaxCapacity = 100_000,
        BatchSize   = 500,
        PersistPath = "/var/iot/camera_events.jsonl", // survives restarts
    },
    uploadFn: UploadToCloud,
    logger:   new ConsoleEdgeSyncLogger());

// 4. Write — always succeeds, even when offline
await buffer.WriteAsync(new CameraEvent("CAM001", "MotionDetected", DateTime.UtcNow, 0.95f));

// 5. When connectivity returns — ordered sync happens automatically
await buffer.OnConnectivityRestoredAsync();

// 6. When connectivity is lost — subsequent writes buffer locally
buffer.OnConnectivityLost();

Configuration

var options = new EdgeSyncOptions
{
    // Maximum entries in memory before oldest are evicted
    MaxCapacity = 100_000,          // default

    // Entries per cloud upload batch
    BatchSize = 500,                // default

    // JSON Lines file for disk persistence (null = memory-only)
    PersistPath = null,             // default — set a path to enable

    // Evictions before dead-letter alert fires
    DeadLetterThreshold = 1_000,    // default
};

// Convenience factory methods
var memoryOnly   = EdgeSyncOptions.Default;
var withDisk     = EdgeSyncOptions.WithPersistence("/var/iot/buffer.jsonl");

Dead-Letter Alerting

// Raise an alert when entries are being evicted (buffer pressure)
buffer.OnDeadLetterThresholdExceeded += async stats =>
{
    await alertService.SendAsync(
        $"IoT buffer under pressure: {stats.EvictionRate}% eviction rate. " +
        $"Pending: {stats.CurrentPending}");
};

Statistics

var stats = buffer.Stats;

Console.WriteLine($"Written:  {stats.TotalWritten}");
Console.WriteLine($"Synced:   {stats.TotalSynced}");
Console.WriteLine($"Evicted:  {stats.TotalEvicted}");
Console.WriteLine($"Pending:  {stats.CurrentPending}");
Console.WriteLine($"SyncRate: {stats.SyncRate}%");

Custom Logging

Implement IEdgeSyncLogger to route to your existing logging infrastructure:

// With Microsoft.Extensions.Logging
public class MsExtLogger<T> : IEdgeSyncLogger
{
    private readonly ILogger<T> _inner;
    public MsExtLogger(ILogger<T> logger) => _inner = logger;
    public void LogDebug(string msg)       => _inner.LogDebug(msg);
    public void LogInformation(string msg) => _inner.LogInformation(msg);
    public void LogWarning(string msg)     => _inner.LogWarning(msg);
    public void LogError(string msg)       => _inner.LogError(msg);
}

Design Decisions

Why JSON Lines for persistence?

  • Zero dependencies beyond System.Text.Json (already in .NET)
  • Append-only — each write is a single file operation
  • Human-readable for debugging
  • Simple compaction — rewrite file minus synced entries

For high-throughput scenarios, replace with SQLite via Microsoft.Data.Sqlite.

Why ConcurrentQueue<T> not Channel<T>?

Channel<T> is excellent for producer/consumer pipelines but requires a dedicated consumer task. ConcurrentQueue<T> allows the buffer to be written from any thread without a background consumer — matching IoT scenarios where writes come from device event callbacks on arbitrary threads.

Why not use the cloud SDK's built-in retry?

Cloud SDK retries address transient HTTP failures. EdgeSyncBuffer addresses connectivity outages — periods where no network path exists. These are different failure modes requiring different solutions.


Contributing

Issues and pull requests are welcome. Please open an issue describing the problem before submitting a PR for significant changes.

# Run tests
dotnet test

# Build package locally
dotnet pack src/EdgeSyncBuffer/EdgeSync.Buffer.csproj --configuration Release


License

MIT — see LICENSE


Author

Ram Budithe — Lead Software Engineer, Global Security Technology
LinkedIn · GitHub

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.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 101 5/8/2026
1.0.1 93 5/7/2026