Skip to content

GCRA Rate Limiter#14826

Merged
minchopaskal merged 17 commits intoredis:unstablefrom
minchopaskal:gcra
Mar 18, 2026
Merged

GCRA Rate Limiter#14826
minchopaskal merged 17 commits intoredis:unstablefrom
minchopaskal:gcra

Conversation

@minchopaskal
Copy link
Copy Markdown
Collaborator

@minchopaskal minchopaskal commented Feb 27, 2026

What

Implement rate limiting functionality via GCRA algorithm.

Introduce a new command GCRA to facilitate it.

The implementation is heavily based on the popular redis-cell module (by brandur) with small changes in the API.

Why

Rate limiting is a very common use case of redis and GCRA is one of the most popular algorithms used because of its simplicity and speed. Currently rate limiting with GCRA is possible via lua scripts or even client libraries via the relatively recent SET IFEQ/DIGEST commands (redis-py example). Implementing it directly inside redis gives us even faster performance.

API

GCRA key max_burst requests_per_period period [NUM_REQUESTS count]

Description

Rate limit via GCRA. requests_per_period are allowed per period at a sustained rate. Thus we have a minimum spacing(emission interval) of period/requests_per_period seconds between each request. max_burst allows for occasional spikes by granting up to max_burst additional requests to be consumed at once. See more in the GCRA wiki.

Options

KEY - key related to specific rate limiting case
MAX_BURST - maximum number of tokens allowed as a burst (in addition to the sustained rate). Min: 0
REQUESTS_PER_PERIOD - number of requests allowed per PERIOD. Min: 1
PERIOD - period in seconds as floating point number used for calculating the sustained rate. Min: 1.0
NUM_REQUESTS - cost (or weight) of this rate-limiting request. A higher cost drains the allowance faster. Default: 1

Note

In redis-cell module and most other modules that are based on it PERIOD is given in seconds as integer. We decided to use floating point for greater flexibility. Internally time periods are calculated in microsecond granularity.

Reply

Reply is identical to reply of redis-cell

127.0.0.1:6379> GCRA <key> <max_burst> <requests_per_period> <period> NUM_REQUESTS <count>
1) <limited> # 0 or 1
2) <max-req-num> # max number of request. Always equal to max_burst+1
3) <num-avail-req> # number of requests available immediately
4) <reply-after> # number of seconds after which caller should retry. Always returns -1 if request isn't limited.
5) <full-burst-after> # number of seconds after which a full burst will be allowed

Note

Medium Risk
Adds a new write command that mutates keys and rewrites itself for replication/expiry, which could affect correctness under replication and edge cases (time/overflow/type handling). Scope is contained but touches core command execution and persistence semantics.

Overview
Introduces a new GCRA command for server-side rate limiting using the Generic Cell Rate Algorithm, with support for fractional period and optional NUM_REQUESTS cost.

The implementation stores the theoretical arrival time in a string key, sets an expiry based on the computed next-allowed time, and rewrites the command to a SET ... PXAT for replication safety; it also adds command metadata (commands.def + new commands/gcra.json), wires the new object into the server build (Makefile, server.h), and includes a dedicated unit test suite covering validation, limiting behavior, overflow handling, wrong-type errors, and replication rewriting.

Written by Cursor Bugbot for commit 4c3101c. This will update automatically on new commits. Configure here.

@augmentcode
Copy link
Copy Markdown

augmentcode bot commented Feb 27, 2026

🤖 Augment PR Summary

Summary: This PR adds a built-in GCRA (Generic Cell Rate Algorithm) rate limiter to Redis via a new GCRA command, aiming to provide a fast, native alternative to Lua/client-side implementations.

Changes:

  • Introduces src/gcra.c implementing gcraCommand, storing the “theoretical arrival time” in a string value and using key expiry to let limiter state self-clean.
  • Registers the new command in src/commands.def with key specs, flags (WRITE, DENYOOM), ACL category, and argument metadata.
  • Adds command documentation/spec in src/commands/gcra.json, including a 5-element array reply schema compatible with redis-cell’s shape.
  • Updates the server build (src/Makefile) and public prototypes (src/server.h) to include the new command.
  • Adds unit coverage in tests/unit/gcra.tcl for argument validation and basic rate-limit behavior (burst, retry timing, multi-token requests, recovery, and key independence).

Technical Notes: The implementation uses microsecond time internally (server.ustime) and derives an emission interval from period/requests_per_period, updating the key’s value and TTL on allowed requests.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 5 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

@sundb sundb added this to Redis 8.8 Feb 28, 2026
@sundb sundb added the release-notes indication that this issue needs to be mentioned in the release notes label Feb 28, 2026
@minchopaskal minchopaskal added the state:needs-doc-pr requires a PR to redis-doc repository label Mar 4, 2026
Copy link
Copy Markdown

@shahsb shahsb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain how TTL is set on the rate‑limiter key? Does it automatically expire after some idle time, or is it managed differently? What happens if a user manually deletes the key?

@minchopaskal
Copy link
Copy Markdown
Collaborator Author

Could you explain how TTL is set on the rate‑limiter key? Does it automatically expire after some idle time, or is it managed differently? What happens if a user manually deletes the key?

TTL is set to the amount of time until the next TAT, i.e we don't worry for managing it. After the TTL has passed the next TAT has arrived so we don't need the stored TAT info hence why we automatically delete it. User should be careful to preserve the key before that if the key is to be used for rate limiting again.

@minchopaskal minchopaskal removed the request for review from skaslev March 9, 2026 11:18
@minchopaskal
Copy link
Copy Markdown
Collaborator Author

Hey, @brandur since this implementation is heavily based on redis-cell we though you might want to take a look

@brandur
Copy link
Copy Markdown

brandur commented Mar 11, 2026

@minchopaskal Thanks Mincho! I read through this. My C-fu is weak enough that I'm not likely to catch any major problems, but it looks good to me — thanks for keeping the same command usage as redis-cell as that'll enable an easy migration for anyone who'd been using that.

A ton of people are going to find Redis built-in rate limiting really useful including multiple companies I've worked for in the past.

mgravell added a commit to StackExchange/StackExchange.Redis that referenced this pull request Mar 12, 2026
add comments, more minor overflow issues
minchopaskal and others added 3 commits March 16, 2026 14:18
Co-authored-by: debing.sun <debing.sun@redis.com>
Co-authored-by: debing.sun <debing.sun@redis.com>
Co-authored-by: debing.sun <debing.sun@redis.com>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

@minchopaskal minchopaskal merged commit 31a4356 into redis:unstable Mar 18, 2026
19 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in Redis 8.8 Mar 18, 2026
michael-grunder added a commit to phpredis/phpredis that referenced this pull request Mar 20, 2026
mgravell added a commit to StackExchange/StackExchange.Redis that referenced this pull request Mar 23, 2026
mgravell added a commit to StackExchange/StackExchange.Redis that referenced this pull request Mar 25, 2026
* Implement GRCA (redis/redis#14826)

* Flag [SER006]; remove [SER001]

* release notes

* Update ReleaseNotes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes indication that this issue needs to be mentioned in the release notes state:needs-doc-pr requires a PR to redis-doc repository

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants