diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55bf2089a9914e9f22d9aa1d6a639355935f719c..2219cfd406024469c495ba63fd5a4331b5d930d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1 +1,3 @@
 # v2.14.44
+
+* added `ExponentialBackoff`
diff --git a/docs/time.rst b/docs/time.rst
index efec99eb24b1de87e440f59f0d352e0216523a1d..17613b9671635b431daf1e4f7722b766d9cbc4fa 100644
--- a/docs/time.rst
+++ b/docs/time.rst
@@ -35,3 +35,9 @@ sleep
 -----
 
 .. autofunction:: satella.time.sleep
+
+ExponentialBackoff
+------------------
+
+.. autoclass:: satella.time.ExponentialBackoff
+    :members:
diff --git a/satella/__init__.py b/satella/__init__.py
index e1cb8af304bfca58d40e1da98aeb5e2b91a55a74..5f99ec5814825b96105db74b0fb7b0f1a50f8c76 100644
--- a/satella/__init__.py
+++ b/satella/__init__.py
@@ -1 +1 @@
-__version__ = '2.14.44a1'
+__version__ = '2.14.44'
diff --git a/satella/time.py b/satella/time.py
index 5fa1683f021bb400dec9472d31997ecf22dacab2..6df47795b088892b8bf6866427a85b042f1c4f3e 100644
--- a/satella/time.py
+++ b/satella/time.py
@@ -7,7 +7,7 @@ import warnings
 from concurrent.futures import Future
 from functools import wraps  # import from functools to prevent circular import exception
 
-__all__ = ['measure', 'time_as_int', 'time_ms', 'sleep', 'time_us']
+__all__ = ['measure', 'time_as_int', 'time_ms', 'sleep', 'time_us', 'ExponentialBackoff']
 
 from satella.exceptions import WouldWaitMore
 
@@ -321,3 +321,46 @@ class measure:
         if self.stop_on_stop:
             self.stop()
         return False
+
+
+class ExponentialBackoff:
+    """
+    A class that will sleep increasingly longer on errors. Meant to be used in such a way:
+
+    >>> eb = ExponentialBackoff(start=2, limit=30)
+    >>> while not connect():
+    >>>     eb.failed()
+    >>>     eb.sleep()
+    >>> eb.success()
+
+    :param start: value at which to start
+    :param limit: maximum sleep timeout
+    :param sleep_fun: function used to sleep. Will accept a single argument - number of
+        seconds to wait
+    """
+    __slots__ = ('start', 'limit', 'counter', 'sleep_fun')
+
+    def __init__(self, start: float = 1, limit: float = 30,
+                 sleep_fun: tp.Callable[[float], None] = sleep):
+        self.start = start
+        self.limit = limit
+        self.counter = start
+        self.sleep_fun = sleep_fun
+
+    def sleep(self):
+        """
+        Called when sleep is expected.
+        """
+        self.sleep_fun(self.counter)
+
+    def failed(self):
+        """
+        Called when something fails.
+        """
+        self.counter = min(self.limit, self.counter * 2)
+
+    def success(self):
+        """
+        Called when something successes.
+        """
+        self.counter = self.start
diff --git a/tests/test_time.py b/tests/test_time.py
index cc35dcbb51856baa4915c97fbc305bdb66c9fe11..0699f8f0b90905e1c06de1ffce3d27fb9c9012ff 100644
--- a/tests/test_time.py
+++ b/tests/test_time.py
@@ -4,12 +4,21 @@ import time
 import multiprocessing
 import os
 import sys
-from satella.time import measure, time_as_int, time_ms, sleep
+from satella.time import measure, time_as_int, time_ms, sleep, ExponentialBackoff
 from concurrent.futures import Future
 
 
 class TestTime(unittest.TestCase):
 
+    def test_exponential_backoff(self):
+        with measure() as measurement:
+            eb = ExponentialBackoff()
+            eb.failed()
+            eb.sleep()
+            eb.failed()
+            eb.sleep()
+        self.assertGreaterEqual(measurement(), 2+4)
+
     def test_measure(self):
         with measure(timeout=0.5) as measurement:
             self.assertFalse(measurement.timeouted)