Skip to content

Comments

Add exponential backoff to the retry algorithm of WebCmdlets#26782

Open
mkht wants to merge 6 commits intoPowerShell:masterfrom
mkht:issue19632-expbackoff-2
Open

Add exponential backoff to the retry algorithm of WebCmdlets#26782
mkht wants to merge 6 commits intoPowerShell:masterfrom
mkht:issue19632-expbackoff-2

Conversation

@mkht
Copy link
Contributor

@mkht mkht commented Feb 11, 2026

PR Summary

Add a new parameter -RetryMode to Invoke-WebRequest and Invoke-RestMethod to add the ability to retry with exponential backoff strategy.

The type of -RetryMode is [WebRequestRetryMode] enum and users can select one from two modes.

  • Fixed: Use fixed retry interval. The interval follows the value of -RetryIntervalSec. This is the default mode.

  • Exponential: Use exponential backoff strategy. The retry interval is expressed as RetryIntervalSec * (2 ^ retryCount).

Note 1:
If we select Exponential, the interval will never exceed 600 seconds. This prevents the interval from becoming excessively long. 600 seconds is used by curl.

Note 2:
This is not a breaking change, since the default mode is Fixed. It does not change the behavior of existing scripts.

PR Context

This PR resolves #19632

PR Checklist

@mkht mkht requested a review from a team as a code owner February 11, 2026 13:16
@microsoft-github-policy-service microsoft-github-policy-service bot added the Review - Needed The PR is being reviewed label Feb 19, 2026
@mkht
Copy link
Contributor Author

mkht commented Feb 21, 2026

I've implemented the two feedback points into the code. Since I thought the code readability had decreased, I added comments.

// When MaximumRetryCount is not specified, the totalRequests is 1.
if (totalRequests > 1 && ShouldRetry(response.StatusCode))
{
WebSession.RetryIntervalInSeconds = RetryMode switch
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WebSession.RetryIntervalInSeconds shouldn't be changed. WebSession is for keeping arguments between calls to the cmdlet.
retryIntervalInSeconds is that we should define before the retry loop and re-calculate here.
Also we could divide by 2 its initial value to avoid extra condition for first pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting adding a new variable within the do-while loop to store the previous retry interval?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, if we initialized retryIntervalInSeconds before the retry loop we could retryIntervalInSeconds /= 2.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the initial value is 5 and we will lose precision.

Copy link
Collaborator

@iSazonov iSazonov Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we use retryIntervalInSeconds * 1000 - it is converting to ms. So we still can divide by 2 at init time if we convert to ms in the same time.

int retryIntervalInMilliseconds = WebSession.RetryIntervalInSeconds * 1000 / 2;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the initialization of retryIntervalInSeconds outside the loop and simplified the backoff calculation logic.
Also, I changed the type of retryIntervalInSeconds from int to float to prevent loss of precision.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed an issue in one edge case.
The logic that doubles the retry interval after each previous retry may conflict with the logic that always prioritizes the Retry-After header value for 429 errors.

Consider a scenario where the user sets RetryIntervalSec to 4 and MaximumRetryCount to 3. Suppose the remote endpoint returns errors in the following sequence for three requests:

  1. 409 Conflict
  2. 429 Too Many Requests (Retry-After: 100 sec)
  3. 409 Conflict

The actual retry intervals under the current logic are:
4 sec > 100 sec > 200 sec
This may differ from the user's expectation.

The user likely expects:
4 sec > 100 sec > 16 sec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review - Needed The PR is being reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add exponential backoff to the retry algorithm of WebCmdlets

3 participants