Dotnet resilience handler retries POST: Sume key rule

The .NET standard resilience handler retries every HTTP method by default, POST included. How to keep a paid Sume submit from running twice.

5 min readSume
All posts

Short answer

Yes. According to Microsoft Learn, the .NET standard resilience handler retries all HTTP methods by default, including POST, with 3 retries, exponential backoff, jitter and a 2 second base delay. A Sume submit is a paid request, so either switch POST retries off or send the same Idempotency-Key on every attempt.

The Sume TypeScript client draws the same line: it retries GET and HEAD always, and POST only when the request carries an Idempotency-Key header.

What the handler does out of the box

The standard handler stacks a rate limiter, a total timeout, a retry strategy, a circuit breaker and an attempt timeout. The retry strategy fires on HTTP 500 and above, 408, 429, HttpRequestException and TimeoutRejectedException. Those are the right triggers for a Sume call. The method scope is the problem.

Standard resilience handler defaults, per Microsoft Learn (read 2026-10-03)
SettingDefault
Max retries3
BackoffExponential, jitter on, 2 s delay
Total request timeout30 s
Attempt timeout10 s
Circuit breaker10% failure ratio, minimum throughput 100, 30 s sampling, 5 s break
Retried methodsAll, unless you disable them

Option 1: stop retrying POST

The same page documents the opt-out. Call options.Retry.DisableFor with HttpMethod.Post and HttpMethod.Delete, or call DisableForUnsafeHttpMethods(), which covers POST, PATCH, PUT, DELETE and CONNECT. Your own code then decides whether to resubmit.

This is the conservative choice if you do not control key generation. The cost is that a dropped connection on submit surfaces as an exception, and you are back to deciding by hand whether the first attempt was accepted.

Option 2: keep retries, pin one key

If you want automatic retries, generate the Idempotency-Key once, before the call, and put it on the request so every attempt carries the same value. Do not mint a fresh GUID inside a retry callback; that makes each attempt look like a new request.

On a Format run, Sume then answers a repeat with the same key and the same body with 200 and idempotency_hit: true, and no second run is created. The same key with a different body is 409 idempotency_conflict, and two concurrent requests with one key give 409 idempotency_key_in_use, which is retryable. See Create a run for the full table.

The 30 second wait versus the 10 second attempt timeout

Sume's sync mode holds the HTTP request for up to 30 seconds (wait_timeout_seconds, maximum 30). The handler's default attempt timeout is 10 seconds, so a sync submit can be cut off and retried while the server is still waiting. Submit with mode async instead, which returns a 202 and a job id at once, then poll the status URL.

Polling is where the defaults help. GET retries are safe, 429 is retried, and the status response carries next_poll_after_seconds, which you should honor over the handler's own delay. Sume documents that a client-side timeout does not cancel a job, so never resubmit a new paid request just because a local attempt gave up. See Jobs and results.

Checklist

Before shipping a .NET client against the Sume API:

  • Use async mode for generation submits and poll status.
  • Either disable POST retries or fix one Idempotency-Key per logical submit.
  • Keep the 10 second attempt timeout for status reads, which return quickly.
  • Treat a 402 or 400 as final; neither is in the retry set.
  • Stop polling on completed, failed or canceled.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume