Compute an exponential backoff schedule for retries
See exactly how long each retry waits: a base of 250 with multiplier 2 and a cap of 2000 gives 250, 500, 1000, 2000, 2000 and 2000 over 6 retries, with no random jitter hiding the policy. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
This exponential backoff schedule calculator turns four retry settings into an exact list of delays. Provide the delay before the first retry, the growth multiplier, the maximum permitted delay, and the number of attempts. The result shows the wait before every retry in the same time unit you supplied. It is useful for checking configuration, documenting client behavior, comparing policies, and catching unexpectedly long recovery windows before retry logic reaches production.
Define the retry policy in one consistent unit
Start with the base delay, which is the wait before retry attempt one. Choose a unit that matches the system you are configuring, such as milliseconds or seconds, and use that same unit for the maximum delay. The calculator deliberately leaves the unit open because exponential backoff has the same arithmetic in every unit.
The multiplier controls how quickly the uncapped delay grows. A multiplier of two doubles each successive wait, while one produces a constant interval. Finally, attempts means retry attempts, not the initial operation: entering five produces five delay records numbered one through five.
Keeping that distinction explicit prevents a common off-by-one error in runbooks and configuration reviews. The base delay must be positive, the multiplier must be at least one, the maximum must be positive, and the attempt count must be a whole number from one through one thousand. These constraints keep the schedule meaningful and its output bounded.
If your application accepts values in milliseconds, label copied results accordingly so nobody later interprets them as seconds.
Understand growth and the maximum-delay cap
For retry number n, the uncapped delay is the base delay multiplied by the multiplier raised to n minus one. The returned delay is the smaller of that value and the maximum delay. For example, a base of 250, multiplier of two, and maximum of 2,000 yields 250, 500, 1,000, 2,000, and then 2,000 again for all later attempts.
The cap applies even when it is below the base delay, so a base of ten with a maximum of three returns three from the first attempt onward. That behavior mirrors a strict maximum and makes unusual configurations visible instead of silently rewriting them. The implementation advances iteratively rather than relying on an unbounded exponent, and it stops growth once the cap has been reached.
The schedule contains no random jitter. That is intentional: it exposes the underlying deterministic policy that jitter would modify, making the result suitable for tests, documentation, and comparisons. Add jitter separately according to your client library's precise rules.
Apply the schedule without creating a retry storm
Use the output to review the timing envelope before you ship a retry policy. A short base delay may look harmless, yet a high multiplier can quickly push later attempts to the cap and stretch the total recovery window. Compare the individual waits with request timeouts, queue visibility periods, rate-limit reset times, and the maximum duration users will tolerate.
The calculator reports waits before retries; it does not include the duration of the original request or the work performed during each failed attempt. Sum those durations separately when estimating a complete worst-case operation. In distributed systems, deterministic schedules can cause many clients to retry simultaneously after a shared outage.
Production clients commonly add bounded random jitter to spread that load, while preserving the computed schedule as the upper bound or central value. This capability does not execute requests, sleep, contact a service, or decide whether an error is retryable. It only computes the arithmetic schedule, with no network access or stored state.
That separation makes it safe to use in configuration generators and automated policy checks.
What you can do with it
Document incident recovery timing
Include an exact attempt-by-attempt schedule in a runbook without calculating powers by hand.
Test configuration generators
Compare generated retry policies against deterministic capped schedules in automated checks.
FAQ
Does attempts include the initial request?
No. It is the number of retries after the initial request, and the schedule has exactly that many entries.
Does the result include jitter?
No. It computes the deterministic exponential schedule. Apply jitter separately using the rules of your retrying client.
What unit are the delays in?
The same unit you type, milliseconds or seconds alike, because the arithmetic is identical in every unit. Use one unit for the base delay and the maximum, and label copied results so nobody later reads milliseconds as seconds.
How is each delay calculated?
For retry number n, the base delay is multiplied by the multiplier raised to n minus one, and the result is capped at the maximum. With 250, 2 and 2000, the waits double until they reach 2000 and then stay there.
What if the maximum is lower than the base delay?
The maximum still wins, from the very first retry. A base of ten with a maximum of three returns three every time, so an unusual setting stays visible instead of being silently rewritten.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev2/retry-backoff-schedule \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"base_delay":250,"multiplier":2,"max_delay":8000,"attempts":6}'const res = await fetch("https://api.kit.forhosting.com/dev2/retry-backoff-schedule", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"base_delay": 250,
"multiplier": 2,
"max_delay": 8000,
"attempts": 6
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev2/retry-backoff-schedule",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"base_delay": 250,
"multiplier": 2,
"max_delay": 8000,
"attempts": 6
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev2/retry-backoff-schedule", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"base_delay":250,"multiplier":2,"max_delay":8000,"attempts":6}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"base_delay":250,"multiplier":2,"max_delay":8000,"attempts":6}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev2/retry-backoff-schedule", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"base_delay": 250,
"multiplier": 2,
"max_delay": 8000,
"attempts": 6
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev2.retry_backoff_schedule",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_attempts | 1000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Understand growth and the maximum-delay cap
This keeps very large multipliers deterministic without allowing an infinite intermediate value to leak into the JSON result.
Apply the schedule without creating a retry storm
Browser execution is free, while API automation is charged at $0.002 per request.
Integration use cases
Review SDK retry settings
Turn proposed retry parameters into concrete waits before approving a client configuration.
Technical questions
What time unit does the calculator use?
Any consistent unit works. If base_delay is in milliseconds, every returned delay and max_delay are also in milliseconds.
Is the maximum applied before the first retry?
Yes. Every returned delay is capped, including the first, so max_delay can be lower than base_delay.
What happens when the cap is reached?
The delay remains at max_delay for that retry and every later retry in the requested schedule.