docs: add sliding window rate limiter example notebook - #4248
docs: add sliding window rate limiter example notebook#4248YashwinReddy29 wants to merge 1 commit into
Conversation
Signed-off-by: Yashwin Reddy Lakkireddy <yashwinlakkireddy@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af4f39ecf1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| " limit: int,\n", | ||
| " window_seconds: int,\n", | ||
| ") -> bool:\n", | ||
| " result = sliding_window(\n", |
There was a problem hiding this comment.
Execute the script on the supplied client
When this helper is copied and called with any client other than the global r used during setup (for example a different DB, host, cluster client, or test fixture), this call still runs the registered script against r, so the passed client argument is ignored and the rate-limit key is checked/mutated on the wrong connection. Pass client=client to the Script call or register the script on the provided client.
Useful? React with 👍 / 👎.
| " await async_client.aclose()\n", | ||
| "\n", | ||
| "\n", | ||
| "asyncio.run(main())" |
There was a problem hiding this comment.
Use top-level await in the notebook
Because this code lives in a Jupyter notebook, this cell runs inside an IPython event loop; asyncio.run(main()) raises RuntimeError in that environment instead of executing the async example. The existing async notebook examples use top-level await, so this should end with await main() to keep the notebook runnable.
Useful? React with 👍 / 👎.
| " _, count = await pipe.execute()\n", | ||
| "\n", | ||
| " if count < limit:\n", | ||
| " await client.zadd(key, {str(uuid.uuid4()): now})\n", |
There was a problem hiding this comment.
Keep the async limiter atomic under concurrency
For async apps with concurrent workers, this repeats the non-atomic check-then-add pattern after the notebook has introduced the Lua script as the concurrency-safe implementation: two callers can both observe count < limit here and then both add, exceeding the configured limit. Either show an async version of the Lua script or explicitly mark this async helper as having the same race as the first sorted-set example.
Useful? React with 👍 / 👎.
| "cell_type": "code", | ||
| "execution_count": null, | ||
| "metadata": {}, | ||
| "outputs": [], |
There was a problem hiding this comment.
Prevent docs from auto-executing the notebook
Because every code cell is committed without stored outputs and docs/conf.py does not override nbsphinx_execute, nbsphinx's default auto mode executes the notebook during the Sphinx build; the later example cells call r.delete(...) against localhost:6379, so invoke build-docs fails anywhere Redis is not already running. Store executed outputs or set notebook metadata to skip execution.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
Reviewed by Cursor Bugbot for commit af4f39e. Configure here.
| " keys=[key],\n", | ||
| " args=[time.time(), window_seconds, limit, str(uuid.uuid4())],\n", | ||
| " )\n", | ||
| " return bool(result)" |
There was a problem hiding this comment.
Ignored Redis client parameter
Medium Severity
The is_allowed_atomic function accepts a client argument, but the registered sliding_window script isn't executed with it. This causes the rate limit logic to always run on the client used during script registration, potentially leading to operations on an unintended Redis connection or database.
Reviewed by Cursor Bugbot for commit af4f39e. Configure here.
| " await async_client.aclose()\n", | ||
| "\n", | ||
| "\n", | ||
| "asyncio.run(main())" |
There was a problem hiding this comment.
asyncio.run breaks notebook cell
Medium Severity
The async example's use of asyncio.run(main()) causes a RuntimeError in Jupyter/IPython environments because an event loop is already active. This prevents the async demonstration from running as intended.
Reviewed by Cursor Bugbot for commit af4f39e. Configure here.


What this adds
A new Jupyter notebook
docs/examples/rate_limiter_sliding_window.ipynbshowing two sliding window rate limiter implementations using Redis:
multi-instance deployments
Why it's useful
The existing examples cover data structures, search, pipelines, and
connections. There is no example showing rate limiting — a very common
Redis use case. The sliding window pattern is more accurate than fixed
window and is the pattern most teams reach for in production.
Context
Built this pattern in production for a distributed rate limiting
microservice handling high-throughput concurrent traffic.
Note
Low Risk
Documentation-only addition; no runtime, library, or production code paths change.
Overview
Adds
docs/examples/rate_limiter_sliding_window.ipynb, a new documentation example for sliding-window rate limiting with Redis.The notebook walks through a sorted-set limiter (
ZREMRANGEBYSCORE/ZCARD/ZADDwith key TTL), an atomic Lua variant viaregister_scriptfor multi-instance safety, and anredis.asynciopipeline version. Each section includes a small demo (e.g. 5 requests per 10 seconds) and documents expected allow/reject output.Reviewed by Cursor Bugbot for commit af4f39e. Bugbot is set up for automated code reviews on this repo. Configure here.