ACL, or "Access Control List", in its colloquial usage, is synonymous with the word "permission". ACL filtering is simply filtering a list of objects by whether or not a particular user has access to the items in the list.
Put another way, this is the answer to the question "What are all the things that this user has access to?".
There are a variety of ways that this can be accomplished, deeply depending on the implementation of the authorization system. This document differentiates between prefilters that filter results before the data is fetched from a database/service and postfilters which filter results after they have been fetched.
A prefilter API is currently a work-in-progress. Prefilters query Authzed to return the list of objects that a user can access. The results of this query can be used as the input to a query for selecting items out of a database.
Postfilters query the data source first and feed results into a
filter() function provided by an Authzed client library.
This function performs Check requests for each item fed into it.
In order to make this strategy efficient, each language's implementation of
filter() has performance optimizations such as laziness, batching, and performing check requests in parallel.
Because postfilters are implemented in the authzed client libraries, they have varying functionality based on which library is used.
To achieve better performance, if a perfectly consistent view of the results is not required, a combination of both filters can be used. The results of a Pre-Filter can be cached and have a Post-Filter ran over them to ensure that nothing has changed since the results were cached. This will exclude new items, but will not return any items that the user has lost access to.
Policy Engines perform can only filter potential results by executing polices on each result in a Post-Filter. This can cause many polices to be executed, but performance overhead can be dealt with by batching and performing execution in parallel.
Homegrown authorization systems that have been modelled in the same relational database as the application usually filter by performing SQL JOINs. This comes with the trade-off that relationships have to be stored in a denormalized form in the database so that JOINs are possible. The more complex the relationships, the harder it is to design, maintain, and keep performant a system based on JOINs.