Guide Python Intermediate

Python Rate Limit Safety Lab

Pace requests with a monotonic clock and test timing without a network service.

2 min read

Prerequisites

Complete the retry lab. This simulation uses Python’s standard library in a single process.

Sample input and task

Send 50 simulated requests at no more than 10 starts per second by leaving at least 0.1 seconds between starts. Use a monotonic clock so wall-clock adjustments cannot change the pacing.

Expected output

Print Sent 50 requests. The final start occurs at least 4.9 seconds after the first. Real scheduling may be slower. Do not sleep after the last request.

HintTrack the next permitted start. A slow request must not cause a catch-up burst. Validate the rate before computing its reciprocal.
Show solution
import math
import time


def paced_calls(send, count, rate, clock=time.monotonic, sleep=time.sleep):
    if count < 0 or not math.isfinite(rate) or rate <= 0:
        raise ValueError("Count must be nonnegative and rate positive and finite")
    interval = 1.0 / rate
    next_start = clock()
    for number in range(count):
        while True:
            delay = next_start - clock()
            if delay <= 0:
                break
            sleep(delay)
        next_start = clock() + interval
        send(number)


if __name__ == "__main__":
    sent = []
    paced_calls(sent.append, count=50, rate=10)
    print(f"Sent {len(sent)} requests")

Check your work

Use a fake clock to avoid waiting during tests:

now = [0.0]
starts = []


def clock():
    return now[0]


def sleep(seconds):
    now[0] += seconds


paced_calls(lambda number: starts.append(clock()), 50, 10, clock, sleep)
assert len(starts) == 50
assert starts[-1] >= 4.9 - 1e-9
assert all(b - a >= 0.1 - 1e-9 for a, b in zip(starts, starts[1:]))

Also test zero requests, invalid rates, and a send function that advances time by 0.3 seconds. Slow calls must not cause a catch-up burst.

Knowledge check and challenge

Does this enforce a shared limit across workers? No. Each process has its own schedule. Shared quotas need coordination.

Extend the simulation with a rate-limit response that specifies a retry delay. Respect that delay. Real APIs can use fixed windows, sliding windows, or token buckets; validate the service policy instead of treating this example as a universal limiter.

Continue to the inventory capstone.

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form