4000+ Line Permission Filter Choking Directus Performance - Need Help Optimizing

Hey Directus community,

I have a massive 4000+ line permissions filter on directus_files that’s making my app unusable for regular users.

The Problem:

  • Admin user : No filter → works fine
  • Regular user : 4000+ line filter → everything slows down
  • Filter checks if users can see files based on whether they have access to items that have comments that have files

My Architecture:

  • Users get access to business items (clients, processes, etc.)
  • If user can see an item, they can see comments on that item
  • If user can see a comment, they can see files uploaded to that comment
  • This creates a huge filter with tons of _or conditions through multiple relationships

Performance Impact:

  • Testing locally on Acer Nitro Ryzen 5 2500U with 16GB RAM
  • This single filter consumes 3+ GB of RAM and maxes out all CPU cores
  • Making the entire machine unresponsive during filter evaluation

Filter works correctly but performance is terrible
I have uploaded the filter in a .txt format(could not upload the .json format)
filter.txt (88.5 KB)

Follow-up: More Details About My Setup (4000+ Line Permission Filter Issue)

Hey @jonathanwagner, thanks for the reply!
Here are more details about my setup and why the filter gets so large.


My Role and Policies

Each role in my system is linked to multiple policies. For example, one of my roles includes:

  • Colaborador oficina/Base permissions
  • Universal/Basic/See item revisions
  • Universal/Basic/Trigger manual flows
  • Universal/Basic/All file relation permissions
  • Colaborador oficina/Folders they can see
  • Colaborador oficina/File permissions to see other users' files
  • Colaborador oficina/File permissions for their own files and folders they can upload in
  • Universal/See all clients
  • Universal/Update clients non relational fields
  • Colaborador oficina & dueño/Comment permissions
  • Internos/Identifier

Each policy grants access to several collections.
For example, a single role might have full access to around 10 collections.


Relationship Logic

If a user has permission to add comments (directus_comments), they can also attach files to those comments.

(This is part of a custom Directus build — we’ve extended Directus to support file attachments in comments.)

So when we generate dynamic permissions for directus_files, the system builds filters based on which collections the user can see.
For example, if the user has access to collections abc and xyz, the generated filter looks like this:

{
  "_and": [
    {
      "_or": [
        { "comments": { "comment_id": { "collection": { "_eq": "abc" } } } },
        { "comments": { "comment_id": { "collection": { "_eq": "xyz" } } } }
      ]
    }
  ]
}

This is fine when access is straightforward (full access to entire collections).
However, things get complicated when access is conditional.


Example of Conditional Access

Let’s say the read permission on a collection named xyz is defined like this:

{
  "_and": [
    {
      "_or": [
        { "created_by": { "_eq": "$CURRENT_USER" } },
        { "status": { "_eq": "published" } }
      ]
    }
  ]
}

Now, for directus_files, our system must replicate that logic through all the linked relationships:

{
  "_and": [
    {
      "_or": [
        {
          "comments": {
            "comment_id": {
              "linked_items": {
                "item:xyz": {
                  "created_by": { "_eq": "$CURRENT_USER" }
                }
              }
            }
          }
        },
        {
          "comments": {
            "comment_id": {
              "linked_items": {
                "item:xyz": {
                  "status": { "_eq": "published" }
                }
              }
            }
          }
        }
      ]
    }
  ]
}

The Core Problem

As the number of collections and conditions increases, the generated filter grows exponentially.
Each role can have multiple policies, each policy can reference multiple collections, and each collection can include nested conditional access rules.

So by the end, the resulting filter for directus_files ends up being over 4000 lines long, with thousands of nested _or and _and conditions.

This massive filter works correctly, but it absolutely kills performance.


Any insights or ideas on how to handle this more efficiently would be greatly appreciated :folded_hands: