# limits Documentation

limits provides utilities to implement rate limiting using various strategies and storage backends such as redis & memcached.

# Quickstart

Initialize the storage backend:

    from limits import storage
    memory_storage = storage.MemoryStorage()

Initialize a rate limiter with the Moving Window strategy:

    from limits import strategies
    moving_window = strategies.MovingWindowRateLimiter(memory_storage)

Initialize a rate limit using the Rate limit string notation:

    from limits import parse
    one_per_minute = parse("1/minute")

Initialize a rate limit explicitly using a subclass of `RateLimitItem`:

    from limits import RateLimitItemPerSecond
    one_per_second = RateLimitItemPerSecond(1, 1)

Test the limits:

    assert True == moving_window.hit(one_per_minute, "test_namespace", "foo")
    assert False == moving_window.hit(one_per_minute, "test_namespace", "foo")
    assert True == moving_window.hit(one_per_minute, "test_namespace", "bar")

    assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
    assert False == moving_window.hit(one_per_second, "test_namespace", "foo")
    time.sleep(1)
    assert True == moving_window.hit(one_per_second, "test_namespace", "foo")

Check specific limits without hitting them:

    assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
    while not moving_window.test(one_per_second, "test_namespace", "foo"):
        time.sleep(0.01)
    assert True == moving_window.hit(one_per_second, "test_namespace", "foo")

Clear a limit:

    assert True == moving_window.hit(one_per_minute, "test_namespace", "foo")
    assert False == moving_window.hit(one_per_minute, "test_namespace", "foo")
    moving_window.clear(one_per_minute", "test_namespace", "foo")
    assert True == moving_window.hit(one_per_minute, "test_namespace", "foo")

# Development

Since limits integrates with various backend storages, local development and running tests can require some setup. Basic redis & memcached installations are expected to be available in your environment. If you are working with Redis Cluster, Redis with Sentinel or Memcached on Google App Engine you can use the makefile `Makefile.tests` to help with setting up development dependencies:

    make -f Makefile.tests redis-start memcached-gae-install
    # hack hack hack
    # run tests
    make -f Makefile.tests redis-stop

# Projects using limits

- Flask-Limiter : Rate limiting extension for Flask applications.

- djlimiter: Rate limiting middleware for Django applications.

- sanic-limiter: Rate limiting middleware for Sanic applications.

# References

- Redis rate limiting pattern #2

- DomainTools redis rate limiter

## Contributions

- Timothee Groleau

- Zehua Liu

- David Czarnecki