Note: Introduced in 0.1.0.

The retries plugin allows requests to be retried when certain errors happen.


You can set how many times a request can be retried by passing the max_retries option (or method), which by default is 3 times:

session = HTTPX.plugin(:retries)

# or
session.get(URL, max_retries: 10)


In case you need to wait before retrying again, you can use the retry_after option, which receives the number of seconds after which you retry, or alternatively, a callable which receives the last failed request and returns the number of seconds to wait (in handy if you want to do exponential backoff):

session = HTTPX.plugin(:retries, retry_after: 2)

session.get(URL, retry_after: 3)
# or, for own exponential back-off
retries = 0
session.get(URL, retry_after: ->(*) { (retries += 1) * 2 })


(since v0.18.0)

When using the :retry_after option, some jitter will be applied to it, thereby not making the retry interval necessarily exact, but applying enough “randomness” in order to make it more resilient to “thundering herd” events.

If you would like to insert your own “jitter” calculation algorithm, you can use this option and pass it a proc:

session = HTTPX.plugin(:retries, retry_after: 2, retry_jitter: ->(interval) { interval + rand }) # ...

(In case you would like to turn off jitter calculation altogether, you can set the following env var: HTTPX_NO_JITTER=1).


In order for you to decide on when to retry, you can use the retry_on option, a callable which receives the failed response, to determine whether the request should be retried.

session = HTTPX.plugin(:retries, retry_on: ->(res) { res.error.is_a?(TimeoutError)})

session.get(URL, body: "body") # only retries if it times out...

Attention! The retry_on callback accepts request and response only since v0.10.0. If you’re using a previous version, the callback only accepts the response.


By default, only idempotent requests are retried (GET, PUT…). If you also want, p. ex. POST requests to be retried on, you can pass this option:

session = HTTPX.plugin(:retries), body: "body", retry_on: ->(res) { res.error.is_a?(TimeoutError)} ) # won't retry, because it's a POST request

# instead

session = HTTPX.plugin(:retries, retry_change_requests: true), body: "body", retry_on: ->(res) { res.error.is_a?(TimeoutError)} ) # now it can be retried!


The request object has a method, #retries, which returns the number of times the request has been retried.


Unless you’re using the retry_on option, requests will be retried only when connection type errors happen, like network errors (IOError…), TLS errors (OpenSSL::SSL::SSLError…) or timeout errors. A 500 HTTP response will, therefore, be considered a valid response.

Next: Cookies