Bounded idempotency reservations and optional response replay for .NET developers building minimal APIs.
- Stop concurrent retries from reaching the same handler while a reservation is live.
- Scope client keys by caller, verb, and route template.
- Start locally, then select a shared SQL or Redis ledger without changing endpoint declarations.
Use a .NET 10 ASP.NET Core project.
dotnet new web -f net10.0 -n PackageDemo
cd PackageDemo
dotnet add package DKNet.AspCore.IdempotencyReplace Program.cs with the example, then run dotnet run.
using DKNet.AspCore.Idempotency;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddIdempotentKey();
var app = builder.Build();
app.MapPost("/orders", () => Results.Ok(new { Accepted = true }))
.RequiredIdempotentKey();
await app.RunAsync();Send POST /orders with X-Idempotency-Key: order-1. The first call returns 200; an immediate retry returns 409. A missing header returns 400. This example keeps keys in one process; use a provider for shared storage.
The filter runs inside the host. The default store owns one process-local dictionary; provider registrations replace it with a singleton adapter to shared storage. Business data writes remain separate from the idempotency ledger.
Invalid keys return 400 before storage. A duplicate in flight always returns 409. The reservation is time-bounded, so a long-running handler can outlive it; successful completion does not create an exactly-once business transaction.
- Protect endpoints and route groups — Choose which individual endpoints and group verbs require keys.
- Validate client keys — Set the header name, accepted length, and bounded regular expression.
- Isolate keys by caller — Choose caller isolation and understand route-template key identity.
- Choose duplicate responses and retention — Choose 409 versus replay and configure reservation and result lifetimes.
- Choosing a store — Compare backends and understand first-explicit-store registration.
- Implement a custom reservation store — Implement the atomic reservation and completion contract.
- MsSqlStore — choose it for a SQL Server ledger.
- NpgsqlStore — choose it for PostgreSQL.
- RedisStore — choose it for Redis TTLs.
- Relational — read the shared SQL protocol.
- Tasks — use it for work triggered at host start.
- Extensions — use it for endpoint discovery and request helpers.