Skip to content

feat(ai-rate-limiting): support redis policy for shared counters#13670

Open
shreemaan-abhishek wants to merge 3 commits into
apache:masterfrom
shreemaan-abhishek:feat/ai-rate-limiting-redis
Open

feat(ai-rate-limiting): support redis policy for shared counters#13670
shreemaan-abhishek wants to merge 3 commits into
apache:masterfrom
shreemaan-abhishek:feat/ai-rate-limiting-redis

Conversation

@shreemaan-abhishek

Copy link
Copy Markdown
Contributor

Description

The ai-rate-limiting Plugin currently keeps token counters only in per-worker shared memory (policy = "local"). In a multi-node deployment the counters are not shared across nodes, so the effective quota scales with the number of gateway nodes and over-allows.

This PR adds a Redis-based counter policy to the Plugin, reusing the existing limit-count Redis backends, so counters can be centralized and a single quota is enforced across all nodes.

Changes:

  • Export policy_to_additional_properties from apisix/plugins/limit-count/init.lua so the Plugin can reuse the shared Redis schema branches.
  • Add policy (local / redis / redis-cluster / redis-sentinel) and allow_degradation schema fields, plus the Redis attribute wiring in transform_limit_conf.
  • Document the new attributes and add a Redis example to docs/en/latest/plugins/ai-rate-limiting.md.
  • Add schema-validation and Redis rate-limiting test cases.

The default remains local, so existing configurations are unaffected.

Which issue(s) this PR fixes:

Fixes #

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

…licy

By default the plugin keeps token counters in per-worker shared memory,
so in a multi-node deployment counters are not shared and the effective
quota scales with the node count. Add a redis-based policy path (reusing
limit-count's redis backends) to centralize counters across nodes.

- export policy_to_additional_properties from limit-count/init.lua
- add policy + allow_degradation schema fields and redis attr wiring
- document the new attributes and a redis example
- add schema and redis rate-limiting tests
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request labels Jul 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the ai-rate-limiting plugin to support Redis-backed counter policies (reusing limit-count’s Redis backends) so token quotas can be enforced consistently across multiple APISIX nodes instead of per-worker local memory.

Changes:

  • Reuses limit-count Redis schema branches by exporting policy_to_additional_properties.
  • Adds policy / allow_degradation and Redis config wiring to ai-rate-limiting (plus schema validation).
  • Updates plugin documentation and adds Redis-focused test coverage.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
t/plugin/ai-rate-limiting.t Adds schema validation and Redis policy integration tests for shared counters.
docs/en/latest/plugins/ai-rate-limiting.md Documents new policy/Redis configuration options and provides a Redis example.
apisix/plugins/limit-count/init.lua Exposes Redis policy schema branches for reuse by other plugins.
apisix/plugins/ai-rate-limiting.lua Adds policy fields + conditional Redis schema and transforms config to use Redis backends.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +163 to 170
["else"] = {
["if"] = {
properties = { policy = { enum = { "redis-sentinel" } } },
},
["then"] = policy_to_additional_properties["redis-sentinel"],
},
},
}
Comment thread apisix/plugins/ai-rate-limiting.lua Outdated
Comment on lines 277 to 287
elseif plugin_conf.policy == "redis-sentinel" then
limit_conf.redis_sentinels = plugin_conf.redis_sentinels
limit_conf.redis_master_name = plugin_conf.redis_master_name
limit_conf.sentinel_username = plugin_conf.sentinel_username
limit_conf.sentinel_password = plugin_conf.sentinel_password
limit_conf.redis_role = plugin_conf.redis_role
limit_conf.redis_connect_timeout = plugin_conf.redis_connect_timeout
limit_conf.redis_read_timeout = plugin_conf.redis_read_timeout
limit_conf.redis_keepalive_timeout = plugin_conf.redis_keepalive_timeout
limit_conf.redis_database = plugin_conf.redis_database
end
Comment thread t/plugin/ai-rate-limiting.t
@membphis

membphis commented Jul 8, 2026

Copy link
Copy Markdown
Member

I think this should be fixed before merge.

ai-rate-limiting now exposes Redis credential fields by reusing the limit-count Redis schemas, but its own plugin schema does not declare those fields in encrypt_fields. APISIX config encryption is driven by each plugin schema's encrypt_fields, so redis_password / sentinel_password would be stored as plain plugin config here, while comparable plugins such as limit-count, limit-req, and ai-cache encrypt Redis passwords.

There is also a sentinel wiring gap: the schema accepts Redis master credentials for redis-sentinel, and the backend uses redis_username / redis_password for the Redis master connection, but transform_limit_conf only forwards the sentinel credentials and does not pass redis_username / redis_password in the sentinel branch. A valid sentinel config with Redis master auth can pass validation but fail at runtime.

Suggested fix: add encrypt_fields = {"redis_password", "sentinel_password"} to the ai-rate-limiting schema, forward redis_username / redis_password for redis-sentinel, and add coverage for encrypted Redis credentials plus sentinel master auth.

… master auth

- declare encrypt_fields for redis_password / sentinel_password so the
  credentials are encrypted at rest, matching limit-count / limit-req
- forward redis_username / redis_password in the redis-sentinel branch so
  a Redis master with ACL/requirepass can be authenticated
- add sentinel master-auth schema coverage and a redis_password encryption test
@shreemaan-abhishek

Copy link
Copy Markdown
Contributor Author

Thanks @membphis, good catches. Fixed in the latest commit:

  • Added `encrypt_fields = {"redis_password", "sentinel_password"}` to the plugin schema so the Redis credentials are encrypted at rest, matching `limit-count` / `limit-req`.
  • Forwarded `redis_username` / `redis_password` in the `redis-sentinel` branch of `transform_limit_conf` so a Redis master with ACL/requirepass can be authenticated.
  • Added a schema test for a sentinel config with Redis master auth, and a test asserting `redis_password` is encrypted at rest.

membphis
membphis previously approved these changes Jul 9, 2026

@membphis membphis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

Comment thread apisix/plugins/ai-rate-limiting.lua Outdated
The per-policy hand-copy dropped redis_keepalive_timeout / redis_keepalive_pool
for the redis and redis-cluster policies (silently falling back to the hardcoded
10000 / 100 in limit-count), since neither branch forwarded them even though the
schema accepts them. Copy every field defined by the policy's schema branch
instead, matching the group-whitelist pattern in limit-count, so no field can be
missed as the schema evolves.
@membphis

Copy link
Copy Markdown
Member

The attributes table in docs/en/latest/plugins/ai-rate-limiting.md is missing redis_keepalive_pool, and it documents redis_keepalive_timeout as sentinel-only (default 60000).

However, the redis and redis-cluster schema branches also define redis_keepalive_timeout (default 10000) and redis_keepalive_pool (default 100), and both fields are forwarded to limit-count by the schema-driven copy in transform_limit_conf, so they take effect for all three redis policies.

Please complete the doc table to cover these two fields for redis / redis-cluster as well, with the correct defaults.

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

Labels

enhancement New feature or request size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants