Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 9, 2025

Enforcement with 40,000+ policies using RBAC and wildcard matching (keyMatch2) was taking ~500ms for 10 checks due to O(n) sequential policy iteration.

Changes

Policy Indexing Infrastructure

  • Added policyIndexMap in Assertion to map subjects to policy indices
  • Auto-maintained on policy add/remove/update operations
  • Opt-in via enableAutoBuildPolicyIndex() flag

IndexedEnforcer Class

  • Pre-fetches user roles before enforcement to warm role cache
  • Leverages existing g() function memoization for faster role checks
  • Falls back to full scan when indexing unavailable
  • ~30-40% faster than standard Enforcer with large policy sets

Performance

  • With 4,200 policies: 568ms → 408ms (1.4x improvement)
  • Improvement scales with policy count

Usage

import { newIndexedEnforcer } from 'casbin';

// Same API as regular Enforcer, indexing enabled by default
const enforcer = await newIndexedEnforcer('model.conf', 'policy.csv');
const allowed = await enforcer.enforce('john', '/finding/438/33/44/3', 'read');

Or enable on existing enforcer:

const enforcer = await newEnforcer('model.conf', 'policy.csv');
enforcer.enableAutoBuildPolicyIndex(true);
enforcer.buildPolicyIndex();

Full documentation in docs/IndexedEnforcer.md.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Question] Performance issue with wildcard rbac, is there a better way to do this?</issue_title>
<issue_description>Want to prioritize this issue? Try:

issuehunt-to-marktext


What's your scenario? What do you want to achieve?

I want to find a better way to implement this setup, as performance is really really bad as is.

Your model:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && r.act == p.act

Your policy:

p | ["program-manager-438", "/program/438", "delete"]
p | ["program-manager-438", "/program/438", "read_mappings"]
p | ["program-manager-438", "/audit/438/:auditId", "create"]
p | ["program-manager-438", "/audit/438/:auditId", "delete_attachment"]
p | ["program-manager-438", "/audit/438/:auditId", "Treatment.Completed"]
p | ["program-manager-438", "/audit/438/:auditId", "Archived.Completed"]
p | ["program-manager-438", "/vendor/438/:vendorId", "upload_attachment"]
p | ["program-manager-438", "/requirement/438/:frameworkOrAuditId/:requirementId", "download_attachment"]
p | ["program-manager-438", "/requirement/438/:frameworkOrAuditId/:requirementId", "Draft.In-scope"]
p | ["program-manager-438", "/assessment/438/:auditId/:assessmentId", "delete_mappings"]
p | ["program-manager-438", "/evidence-request/438/:auditId/:assessmentId/:evidenceRequestId", "read"]
p | ["program-manager-438", "/evidence-request/438/:auditId/:assessmentId/:evidenceRequestId", "read_mappings"]
p | ["program-manager-438", "/evidence-request/438/:auditId/:assessmentId/:evidenceRequestId", "Archived.Draft"]
p | ["program-manager-438", "/finding/438/:auditId/:assessmentId/:findingId", "delete"]

g | john, program-manager-438

Your request(s):

john, finding/438/33/44/3, read ---> true

Essentially the goal is to have roles that have wildcard rules like this. But also roles that are more specific that use exact ids instead. This works with the implementation above, but has atrocious performance.

Currently, if you have around 40000 rules, this takes ~500ms to check 10 permissions, and ~1000ms to check 20 permissions...that makes me think that the enforcer is checking them synchronously?

FYI: My setup is nodejs with postgres adapter.</issue_description>

Comments on the Issue (you are @copilot in this section)

@hsluoyz @jjh-reciprocity see benchmark: https://casbin.io/docs/benchmark . I think it's reasonable to have 50ms time overhead for 40000 rules

You can try performance optimization: https://casbin.io/docs/performance</comment_new>


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI and others added 4 commits December 9, 2025 17:26
Co-authored-by: mserico <140243407+mserico@users.noreply.github.com>
Co-authored-by: mserico <140243407+mserico@users.noreply.github.com>
…PolicyIndex, add logging

Co-authored-by: mserico <140243407+mserico@users.noreply.github.com>
Co-authored-by: mserico <140243407+mserico@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve performance of wildcard RBAC implementation Add IndexedEnforcer for RBAC performance optimization with large policy sets Dec 9, 2025
Copilot AI requested a review from mserico December 9, 2025 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Question] Performance issue with wildcard rbac, is there a better way to do this?

3 participants