BuildingBlocks.Idempotency 1.0.1

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

BuildingBlocks.Idempotency

ASP.NET Core Idempotency-Key for MVC and Minimal API. Host-owned IDistributedCache, optional Redis lock, opt-in request fingerprint, RFC 9457 ProblemDetails on conflicts, optional ActivitySource.

NuGet GitHub Release .NET License: MIT

Requires .NET 8, .NET 9, or .NET 10.

What's new in 1.0.1

  • Package icon for NuGet listing parity with other BuildingBlocks
  • System.Text.Json for the cache envelope and MVC ObjectResult body capture (dropped Newtonsoft.Json). Minimal API already used STJ. No public API change from 1.0.0.

Install

dotnet add package BuildingBlocks.Idempotency

Features

  • Shared gate for MVC ([Idempotent]) and Minimal API (WithIdempotency)
  • Cache HTTP 2xx envelopes (status, content-type, body) and replay them
  • Processing lease (ProcessingTtl) with abandoned recovery; Completed window (EntryTtl)
  • Per-endpoint TTL overrides (ProcessingTtlSeconds / EntryTtlSeconds)
  • Optional Redis SET NX lock around GetOrCreate (.UseRedisLock())
  • Opt-in fingerprint: SHA-256(method + "\n" + path + "\n" + body)
  • Key validation (ULID by default, MaxKeyLength, reject empty / control characters)
  • DuplicateCompletedBehavior: Replay (default) or Conflict
  • ProblemDetails errors with stable type URIs
  • Optional telemetry (.UseTelemetry()); host AddSource("BuildingBlocks.Idempotency")
  • System.Text.Json only (cache + MVC + Minimal API)

Quick start

// Host must already register IDistributedCache.
// For UseLock, also register IConnectionMultiplexer.
builder.Services.AddBuildingBlocksIdempotency(o =>
{
    o.ProcessingTtl = TimeSpan.FromMinutes(2); // keep longer than worst-case handler
    // o.EnableRequestFingerprint = true;
    // o.UserIdFallback = "anonymous"; // when NameIdentifier is missing
})
.UseRedisLock()      // optional
.UseTelemetry();     // optional

// MVC
[HttpPost]
[Idempotent(useLock: true)]
public async Task<ActionResult<OrderResponse>> Create([FromBody] CreateOrder request) { ... }

// Minimal API
app.MapPost("/orders", CreateAsync).WithIdempotency(useLock: true);

Aliases still work: AddRedisIdempotencyLock(), AddIdempotencyTelemetry().

Behavior

Situation Result
New key Execute; on 2xx store Completed envelope
Same key, Completed (default) Replay envelope + X-Idempotent-Response
Same key, Completed + DuplicateCompletedBehavior.Conflict ProblemDetails (default 409)
Same key, Processing (lease active) ProblemDetails (default 409)
Same key, Processing expired Miss — may execute again
Fingerprint enabled + method/path/body mismatch ProblemDetails (default 422)
Missing / invalid key ProblemDetails 400
Missing caller identity (no UserIdFallback) ProblemDetails 401
Non-2xx or exception Remove cache entry (retry allowed)
UseLock and lock not acquired ProblemDetails 500

Cache key: {KeyPrefix}_{optionalScopeClaims}_{userId}_{key} (default prefix Idempotency).

Replay header name is configurable (CachedResponseHeader, default X-Idempotent-Response).

ProblemDetails

Conflicts and validation failures return application/problem+json. Stable type values:

Suffix Typical status
key-invalid 400
unauthorized 401
processing 409
fingerprint-mismatch 422
duplicate 409
lock-failure 500

Base: https://buildingblocks.dev/errors/idempotency/.

TTL

Setting Default Role
ProcessingTtl 2 min In-flight lease
EntryTtl 30 min Completed replay window
Attribute / WithIdempotency seconds 0 Use global; > 0 overrides

After ProcessingTtl expires, another request with the same key may run while a slow first request is still in flight. The optional lock covers GetOrCreate only.

Fingerprint

Off by default (same key replays even if the body changes). When EnableRequestFingerprint is true, the hash includes HTTP method, path, and raw body bytes (not canonical JSON).

Options (common)

Option Default Notes
HeaderName Idempotency-Key Request header
RequireUlid true Set false for opaque strings (still length/control checks)
MaxKeyLength 256 Always enforced
KeyScopeClaimTypes empty Extra claims in the cache key (e.g. tenant)
UserIdFallback null Missing user claim → 401 unless set
DuplicateCompletedBehavior Replay Or Conflict
FingerprintConflictStatusCode 422 Configurable
ProcessingConflictStatusCode 409 Configurable
DuplicateConflictStatusCode 409 When Conflict strategy

Telemetry

.UseTelemetry() registers ActivitySource BuildingBlocks.Idempotency. Outcomes: executed, replayed, processing_conflict, fingerprint_conflict, duplicate_conflict, bad_key, unauthorized, lock_failure. Cache keys are not tagged unless IncludeCacheKeyInTelemetry is true.

This package does not depend on BuildingBlocks.Telemetry — add AddSource("BuildingBlocks.Idempotency") on the host.

Host requirements

  • IDistributedCache (required)
  • IConnectionMultiplexer when using .UseRedisLock() / UseLock: true
  • No references to BuildingBlocks.Mcp, Mediator, Telemetry, or EventBus

Not this package

MCP tool write idempotency (UseMemoryIdempotency / IMcpIdempotencyStore) is part of BuildingBlocks.Mcp.

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 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 is compatible.  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

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.1 40 9/4/2026
1.0.0 47 9/4/2026

1.0.1: package icon; System.Text.Json for cache + MVC ObjectResult (drop Newtonsoft.Json). https://github.com/Maxofpower/FeatureFusion/blob/main/CHANGELOG.md