{
  "id": 12283118,
  "title": "The silent retry bug killing ASP.NET Core reliability (and how idempotency keys save you)",
  "url": "https://urgent.news/2026/10/06/the-silent-retry-bug-killing-asp-net-core-reliability-and-how",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-06T02:31:16.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/developerimranahmed/the-silent-retry-bug-killing-aspnet-core-reliability-and-how-idempotency-keys-save-you-1lhj"
  },
  "original_language": "en",
  "account": "When working with distributed systems in C# and ASP.NET Core, network issues like timeouts and service unavailability are common. The conventional solution is to use Polly, a library for resilience and transient fault handling, by adding retry policies. However, retries without idempotency can lead to data inconsistency. For instance, retrying a POST or PUT request might change the system state, leading to issues like double charges in a payment system or duplicate orders in an e-commerce platform. This problem is referred to as the \"duplicate-state problem,\" which is a hidden threat to system reliability.\n\nMost retry strategies, including those from Polly, Hangfire, and Azure Service Bus, operate on the \"at least once\" delivery guarantee. This means they will retry if something seems to have failed, but without idempotency, a successful first call followed by a failed second call (or vice versa) can result in inconsistent data.\n\nThe solution to this issue is the use of Idempotency Keys. This involves generating a unique identifier (typically a GUID) for the operation, attaching it to the HTTP request (often in the Idempotency-Key header), and having the server check if this key has been seen before. If it's new, the server executes the business logic, saves the result, and records the key-result pair with a Time-To-Live (TTL). If the key is already present, the server skips the business logic and returns the stored result.\n\nIn ASP.NET Core, implementing this involves checking for existing results in a fast, distributed cache like Redis, executing the business logic if no existing result is found, and storing the key-result pair in the cache. It's recommended to encapsulate this logic in middleware or a filter for uniform application across all endpoints.\n\nUsing Polly, you can ensure that every retryable HTTP call includes the idempotency key, either by adding the header automatically for specific clients or by ensuring clients always provide it. For background jobs in Hangfire or Azure Functions, the same principle applies—ensure the underlying HTTP calls are idempotent to maintain data integrity during retries.\n\nIn summary, resilience in distributed systems isn't just about avoiding crashes; it's about maintaining data integrity during failures. Implementing Idempotency Keys for all state-changing endpoints and using a distributed cache to store these keys can safeguard your system against the \"duplicate-state problem.\" Always test your retry logic by simulating scenarios like timeouts after successful writes to ensure your system doesn't create duplicate data.",
  "summary": "The Silent Retry Bug: Why Your Resilient .NET System Is Actually Fragile If you’ve spent any time working with distributed systems in C# and ASP.NET Core, you know the drill: network calls fail, timeouts happen, and services become temporarily unavailable. The standard advice? Use Polly. Add a retry policy. Make it resilient. But here’s the hard truth: retries without idempotency are dangerous.…",
  "key_points": [
    "Distributed systems in ASP.NET Core experience network issues like timeouts.",
    "Conventional retry policies from Polly can cause data inconsistency.",
    "Idempotency Keys prevent duplicate-state problem by ensuring state-changing requests are unique."
  ],
  "editors_take": "Implementing idempotency keys in ASP.NET Core ensures that retrying failed requests doesn't lead to data inconsistencies, thereby safeguarding system reliability and maintaining data integrity during failures.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}