What is API Idempotency?
Idempotency is a crucial concept in API design where making the same request multiple times produces the same result as making it once. This is especially important for operations that modify data (POST, PUT, PATCH, DELETE) where accidental duplicate requests could cause problems like double charges or duplicate records.
Why Implement Idempotency?
Before we dive into code, let’s understand why idempotency matters:
- Network reliability: Clients might retry requests if they don’t receive a response
- User experience: Users might double-click buttons
- Distributed systems: Microservices might need to retry failed calls
Basic Implementation Approach
Here’s a simple way to implement idempotency in ASP.NET Core:
1. Create an Idempotency Filter
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Concurrent;
public class IdempotencyFilter : IActionFilter
{
private static readonly ConcurrentDictionary<string, bool> _processedRequests = new();
public void OnActionExecuting(ActionExecutingContext context)
{
// Check for Idempotency-Key header
if (!context.HttpContext.Request.Headers.TryGetValue("Idempotency-Key", out var idempotencyKey))
{
context.Result = new BadRequestObjectResult("Idempotency-Key header is required");
return;
}
var key = idempotencyKey.ToString();
// If we've already processed this key, return conflict
if (_processedRequests.ContainsKey(key))
{
context.Result = new ConflictObjectResult("This request has already been processed");
return;
}
// Mark this key as being processed
_processedRequests.TryAdd(key, true);
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Cleanup if needed
}
}
2. Register the Filter
In your Program.cs
:
builder.Services.AddControllers(options =>
{
options.Filters.Add<IdempotencyFilter>();
});
3. Using the Idempotent API
POST /api/orders
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"productId": 123,
"quantity": 2
}
Best Practices
- Key generation: Clients should generate unique keys (GUIDs work well)
- Key length: Keep it reasonable (128-256 characters max)
- Expiration: Set appropriate expiration times (hours/days depending on use case)
- HTTP methods: Typically only needed for POST, PUT, PATCH, DELETE
- Response caching: Cache successful responses to return identical responses for duplicate requests
Implementing idempotency in your ASP.NET Core APIs helps make them more reliable and resilient to duplicate requests.
Remember that the exact implementation might vary based on your specific requirements, but this gives you a solid foundation to build upon.
Happy Coding 🙂