Algori...nential(3pm)
๐ NAME ๐
Algorithm::Backoff::Exponential โ bestie, it backs off exponentially. That's the whole vibe. It's a Perl module (you'll find it filed under 3pm, the User Contributed Perl Documentation manual, which is why the header is all squished like Algori...nential(3pm) โ the terminal ate the middle of her name ๐ญ).
๐ VERSION ๐
This doc is describing version 0.010 of Algorithm::Backoff::Exponential, which ships in the Perl distribution Algorithm-Backoff, released on 2024-02-24. Yes she's got a birthday, and yes she's thriving. ๐
โจ SYNOPSIS โจ
Okay so first you instantiate her, then you feed her successes and failures and she hands you back a number of seconds to wait. Like a little delay oracle. ๐ฎ
use Algorithm::Backoff::Exponential;
# 1. instantiate
my $ab = Algorithm::Backoff::Exponential->new(
#consider_actual_delay => 1, # optional, default 0
#max_actual_duration => 0, # optional, default 0 (retry endlessly)
#max_attempts => 0, # optional, default 0 (retry endlessly)
#jitter_factor => 0.25, # optional, default 0
initial_delay => 5, # required
#max_delay => 100, # optional
#exponent_base => 2, # optional, default 2 (binary exponentiation)
#delay_on_success => 0, # optional, default 0
);
# 2. log success/failure and get a new number of seconds to delay, timestamp is
# optional but must be monotonically increasing.
# for example, using the parameters initial_delay=5, max_delay=100:
my $secs;
$secs = $ab->failure(); # => 5 (= initial_delay)
$secs = $ab->failure(); # => 10 (5 * 2^1)
$secs = $ab->failure(); # => 20 (5 * 2^2)
$secs = $ab->failure(); # => 33 (5 * 2^3 - 7)
$secs = $ab->failure(); # => 80 (5 * 2^4)
$secs = $ab->failure(); # => 100 ( min(5 * 2^5, 100) )
$secs = $ab->success(); # => 0 (= delay_on_success)
And here's her serving looks from the command line via show-backoff-delays โ that's 10 failures followed by 3 successes:
% show-backoff-delays -a Exponential --initial-delay 1 --max-delay 200 \
0 0 0 0 0 0 0 0 0 0 1 1 1
1
2
4
8
16
32
64
128
200
200
0
0
0
Look at her go. 1, 2, 4, 8, 16, 32, 64, 128, then she hits the 200 ceiling twice and just chills there, and the second a success rolls in she's back at 0. Character development. ๐
๐ธ DESCRIPTION ๐ธ
So the way this backoff algorithm does math is:
initial_delay * exponent_base ** (attempts-1)
Only initial_delay is required โ everything else is optional, she's low maintenance like that. exponent_base defaults to 2 (that's the binary exponential situation). On the very first failure attempt (when attempts = 1) the delay is just the initial delay, and from there she doubles, quadruples, and keeps on climbing (with that default exponent base of 2, obviously).
There are ceilings, bestie โ limits on how many attempts you get (max_attempts) and how long the whole thing can drag on (max_actual_duration).
Pro tip from the docs themselves: add a jitter factor, like 0.25, to sprinkle in some randomness and dodge the "thundering herd problem". ๐๐๐
๐ง METHODS ๐ง
new
Usage, exactly as she comes:
new(%args) -> obj
This function is not exported. So you're calling it as a method, not importing it. Noted. ๐
The arguments, where * means required (no skipsies):
consider_actual_delay=> bool (default: 0) โ whether to consider actual delay.
If you set this one to true, she takes the actual delay into account (that's the timestamp difference). Example time: with the Constant strategy of delay=2, if you call failure() again right after the previous failure() (same timestamp, no shame), failure() returns roughly 2+2 = 4 seconds. But if you actually waited 2 seconds before calling failure() again (timestamp 2 seconds bigger than the last one), failure() returns 2 seconds. And if you waited 4 seconds or more? failure() hands you 0. Iconic behavior honestly. โจ
delay_on_success=> ufloat (default: 0) โ number of seconds to wait after a success.exponent_base=> ufloat (default: 2) โ (No description). She's mysterious, she's just vibing, the docs say nothing and that's fine. ๐initial_delay*=> ufloat โ the initial delay for the first attempt after a failure, in seconds. This one's required, bestie, don't forget her.jitter_factor=> float โ how much randomness to add.
If you set this to anything larger than 0, the actual delay lands somewhere in a random number between original_delay * (1-jitter_factor) and original_delay * (1+jitter_factor). Jitters get added to avoid the so-called "thundering herd" problem. And this jitter applies to the delay on failure as well as on success. Equal opportunity jitter. ๐ฒ
max_actual_duration=> ufloat (default: 0) โ maximum number of seconds for all of the attempts (0 means unlimited).
If you set it to a positive number, she caps how many seconds the whole set of attempts can take. It's how you say "I'm only willing to spend this much time on this task." Example: with the Exponential strategy of initial_delay=3 and max_attempts=10, the delays go 3, 6, 12, 24, .... If failures get logged along those suggested delays and max_actual_duration is set to 21 seconds, then the third failure() returns -1 instead of 24, because 3+6+12 >= 21 โ even though max_attempts was never exceeded. She said "we're done here." ๐
max_attempts=> uint (default: 0) โ maximum number of consecutive failures before giving up.
0 means retry endlessly, forever, never giving up, the grind never stops. 1 means give up after a single failure (so, zero retry attempts). 2 means retry once after a failure. And heads up: after a success the attempt count resets (as you'd expect). So if max_attempts is 3 and you fail twice and then succeed, then on the next failure she starts the whole retry thing over again for up to 3 times. Fresh start, new era. ๐
max_delay=> ufloat โ maximum delay time, in seconds.min_delay=> ufloat (default: 0) โ maximum delay time, in seconds. Yep, that's literally what the docs say, word for word โ "Maximum delay time, in seconds." on themin_delayentry too. I'm not touching it, I'm just reporting. ๐ซถ
Return value: (obj)
๐ฆ HOMEPAGE ๐ฆ
Please go visit the project's homepage, she'd love that:
<https://metacpan.org/release/Algorithm-Backoff>
โญ SOURCE โญ
The source repository lives at:
<https://github.com/perlancar/perl-Algorithm-Backoff>
๐ SEE ALSO ๐
- <https://en.wikipedia.org/wiki/Exponential_backoff>
Algorithm::Backoff- All the other
Algorithm::Backoff::*classes โ it's a whole friend group. ๐
๐ AUTHOR ๐
perlancar <perlancar@cpan.org>
๐ง CONTRIBUTING ๐ง
Wanna contribute? You can send patches by email / via RT, or send pull requests on GitHub. She welcomes you with open arms. ๐ซถ
Most of the time you do not need to build the distribution yourself. You can just modify the code and then test it like:
% prove -l
If you do want to build the distribution (say, to try installing it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla- and/or Pod::Weaver plugins. Any extra steps required beyond that are considered a bug and you can report them. No cap.
๐ COPYRIGHT AND LICENSE ๐
This software is copyright (c) 2024, 2019 by perlancar <perlancar@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Slay, legally. โ๏ธโจ
๐ BUGS ๐
Please report any bugs or feature requests on the bugtracker website:
<https://rt.cpan.org/Public/Dist/Display.html?Name=Algorithm-Backoff>
And when you submit a bug or a request, please include a test-file or a patch to an existing test-file that shows off the bug or the desired feature. Help her help you, bestie. ๐
And that's the whole page, mwah ๐
โ this was Algorithm::Backoff::Exponential, served to you from perl v5.40.1 on 2025-05-04, and that header up top that looked like Algori...nential(3pm) was just her name with the middle cut out, but we all know who she is. ๐ Go forth and back off exponentially. ๐
๐ฆ where this page comes from
- debian trixie: libalgorithm-backoff-perl 0.010-2 ยท Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libalgorithm-backoff-perl 0.010-2 ยท Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libalgorithm-backoff-perl 0.010-2 ยท Artistic-1.0-Perl OR GPL-1.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms