Skip to content

Retry After

DodaTech 2 min read

title: "Retry-After Header — Telling Clients When to Retry" description: "The Retry-After header tells API clients how long to wait before retrying a failed request, essential for rate limiting and service recovery scenarios." date: 2026-06-28 lastmod: 2026-06-28 weight: 28 tags: [apis, error-handling] }

The Retry-After response header tells clients how many seconds to wait before retrying a request, commonly used with 429 (rate limit) and 503 (service unavailable) responses.

What You'll Learn

  • Retry-After header format and usage
  • Client-side retry strategies
  • Combining Retry-After with other headers

Why It Matters

Without Retry-After, clients guess when to retry. They may retry too early (overloading the server) or too late (wasting time).

Code Examples

# Setting Retry-After header
@app.errorhandler(429)
def rate_limit_error(error):
    retry_after = error.retry_after  # seconds
    response = jsonify({
        "error": "RATE_LIMIT_EXCEEDED",
        "message": f"Rate limit exceeded. Retry after {retry_after} seconds",
        "retry_after_seconds": retry_after
    })
    response.status_code = 429
    response.headers['Retry-After'] = str(retry_after)
    return response

# Retry-After with HTTP-date format
from email.utils import formatdate

retry_date = datetime.utcnow() + timedelta(hours=1)
response.headers['Retry-After'] = formatdate(
    time.mktime(retry_date.timetuple()), usegmt=True
)
// Client handling Retry-After
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const res = await fetch(url, options);
    if (res.status !== 429 && res.status !== 503) {
      return res;
    }
    const retryAfter = parseInt(res.headers.get('Retry-After')) || 60;
    await new Promise(r => setTimeout(r, retryAfter * 1000));
  }
  throw new Error('Max retries exceeded');
}

Common Mistakes

1. Using Seconds Format Incorrectly

Retry-After can be seconds (integer) or HTTP-date. Pick one and use it consistently.

2. No Upper Bound on Client Wait

Clients should cap wait time (e.g., max 300 seconds) to avoid infinite waits.

3. Not Respecting Retry-After Header

Rate limit errors without Retry-After force clients to implement their own backoff.

4. Dynamic Retry-After Values

Increase Retry-After proportionally for persistent offenders.

5. Inconsistent Retry-After with Rate Limit Reset

The Retry-After value should match the rate limit window reset time.

Practice Questions

  1. What are the two formats for Retry-After?
  2. What status codes typically use Retry-After?
  3. How should clients handle Retry-After?
  4. Why should Retry-After values increase for repeat offenders?
  5. What is the maximum sensible Retry-After value?

Answers:

  1. Seconds (integer) or HTTP-date (RFC 1123 format).
  2. 429 Too Many Requests and 503 Service Unavailable.
  3. Wait the specified seconds before retrying, with a maximum cap.
  4. To discourage aggressive retry behavior from misconfigured clients.
  5. 24 hours (86400 seconds). Longer values suggest permanent blocks.

Challenge: Implement a server that returns Retry-After headers for rate limiting and a client that respects them with exponential backoff up to a maximum delay.

FAQ

Can Retry-After be used with other status codes?

: Yes. It's also used with 503 for maintenance windows.

What happens if Retry-After is missing from a 429?

: Clients should implement exponential backoff starting at 1 second.

Should Retry-After be an integer?

: Yes, representing seconds. HTTP-date format is less reliable with dynamic values.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro