惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
The GitHub Blog
The GitHub Blog
Recent Announcements
Recent Announcements
博客园 - Franky
D
DataBreaches.Net
B
Blog
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
人人都是产品经理
人人都是产品经理
WordPress大学
WordPress大学
P
Proofpoint News Feed
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
月光博客
月光博客
宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
F
Fortinet All Blogs
博客园 - 【当耐特】

Cerbos - All Posts

Authentik vs Keycloak: Self-hosted IdP comparison Mapping business requirements to authorization policy for automotive Fine-grained authorization for AI gateways EIC 2026: Stop counting agents, protect what they can touch Agent skill for writing authorization policies in Claude Desktop Identity security in 2026 EIC 2026 takeaways: the identity stack built for humans will not hold up for AI agents Already have authentication? Here's the authorization layer you still need. Tokens are authorization decisions: a guide to policy-driven token issuance What is a Runtime Authorization Platform It's a dimmer switch, not a kill switch. How CISOs are rethinking AI agent governance From maps to bitmaps (and from bitmaps to bitmaps) AuthZEN, Shared Signals, SCIM Events, IPSIE: Notes from the OpenID Enterprise Panel How do you update authorization policies without redeploying your application? IIW42 recap: Where agent authorization got real Cerbos PDP v0.52.0/v0.53.0: Engine performance, security hardening, and CEL path functions Authorization Management Platforms: what they do, how they work, and where they fit PocketOS AI coding agent deleted a production database in 9 seconds Non-Human Identity management still has a blind spot Supabase alternative in 2026: Best open source auth options Benefits of on-premise authorization: Why enterprises are moving toward self-hosted Authorization policies: How to write, test, and validate them (faster with AI) Agent skill for writing authorization policies How much does it cost to build authorization in-house? Why centralized authorization governance reduces incident response time OPA alternative Why AI agents make authorization a right now problem Modernizing legacy application authorization: why it’s your biggest security blind spot How to add authorization to legacy applications without code changes 5 authorization blind spots auditors find, and how to fix them
Don't fetch that. A developer's guide to pre- vs. post-fi...
Alex Olivier · 2025-06-26 · via Cerbos - All Posts

So you’ve done the hard work. You’ve decoupled your application logic from your authorization logic, moving your policies to a centralized service. Your codebase is cleaner, and your security posture is stronger. But a new, critical question emerges: how do you actually filter the data you send to users?

You need to ensure that when a user asks for a list of "documents," "projects," or "invoices," they only see the ones they’re truly allowed to see. This brings you to a fork in the road. Do you fetch a broad set of data and filter it in your app, or do you filter it at the source? This is the core dilemma of post-filtering versus pre-filtering.

The "fetch-then-filter" trap. The post-filtering approach

The most common starting point is post-filtering. It’s conceptually simple:

  1. Your application receives a request, say GET /expenses.
  2. It queries the database: SELECT * FROM expenses;.
  3. It then iterates through every single expense record and, one by one, asks the authorization service, “Can the current user view this specific expense?”
  4. If the answer is "yes," it keeps the record. If "no," it's tossed out.

Why it's tempting: This approach feels straightforward. The logic is easy to follow, and for a small-scale application or a prototype, it gets the job done without much fuss.

Why it breaks down: In the real world, this model quickly becomes a performance and security nightmare.

  • Massive over-fetching: You're pulling potentially thousands of records into your application's memory just to throw most of them away. This puts an unnecessary load on your database, clogs network bandwidth, and slows your application to a crawl.
  • The pagination puzzle: How do you implement pagination? If a user asks for page 2 with 10 items, you can't just LIMIT 10 OFFSET 10. You might have to fetch 10,000 records just to find 10 that the user is allowed to see on that "page." It’s inefficient and unpredictable.
  • A security risk: For a brief moment, sensitive data the user shouldn't access is sitting in your application's memory. Even if it's filtered before being sent, this momentary exposure can be an unacceptable risk in secure environments.

A smarter way. Pre-filtering with a query plan

What if, instead of asking for permission for each item, you could ask your authorization service, “What are the conditions for a user to see any item?”

This is the power of pre-filtering. It flips the script entirely:

  1. Your application receives a request: GET /expenses.
  2. It first asks the authorization service, "Generate a query plan for a user trying to view expenses."
  3. The authorization service, instead of returning a simple "allow" or "deny," returns a set of conditions.
  4. Your application takes these conditions and integrates them directly into the database query.
  5. The database does what it does best—filtering—and returns only the data the user is authorized to see.

With a stateless authorization engine like Cerbos, this is done via a partial evaluation of your policies. For example, imagine a policy where users can view their own expenses, and managers can view all expenses in their department. If a manager named "sara" in the "engineering" department requests the list, Cerbos would return a query plan containing a filter. That filter would have a condition object representing the abstract syntax tree (AST) of the rules.

It would look like this:

{
  "filter": {
    "kind": "KIND_CONDITIONAL",
    "condition": {
      "expression": {
        "operator": "or",
        "operands": [
          {
            "expression": {
              "operator": "eq",
              "operands": [
                { "variable": "request.resource.attr.ownerId" },
                { "value": "sara" }
              ]
            }
          },
          {
            "expression": {
              "operator": "eq",
              "operands": [
                { "variable": "request.resource.attr.department" },
                { "value": "engineering" }
              ]
            }
          }
        ]
      }
    }
  }
}

Your application’s data layer can then traverse this structure to translate it into a native SQL WHERE clause: WHERE ownerId = 'sara' OR department = 'engineering'. The logic is generated dynamically based on the user and the policies in effect.

The clear wins:

  • Maximum efficiency: The database only returns the precise data needed. No over-fetching, no wasted resources.
  • Rock-solid security: Sensitive data the user isn't authorized to view never leaves the database. It’s never loaded into the application's memory.
  • Pagination that just works: Since the filtering is done at the source, pagination is as simple and reliable as it should be.
  • Built to scale: This approach is designed for the complexity of modern applications, handling large datasets and intricate rules without breaking a sweat.

The bulletproof hybrid. Pre-filter and verify

For applications where you absolutely cannot compromise, think high-security or mission-critical systems, there's an even more robust pattern: the hybrid approach.

It’s simple: you do both.

First, you use the highly efficient pre-filtering method with a query plan to fetch the initial dataset from the database. Then, as a final check, you run the results through the authorization PDP one last time before sending the data on its way.

This provides the ultimate safety net. It combines the performance of pre-filtering with the explicit verification of post-filtering, protecting against any subtle misconfigurations or complex edge cases in your policies.

Make the right choice for your architecture

While the initial simplicity of post-filtering is alluring, it’s a solution with a ceiling. It creates performance bottlenecks and security concerns that are difficult to engineer your way out of later.

For modern, scalable, and secure applications, pre-filtering is the clear winner. By pushing the authorization conditions down to the data layer, you build a system that is performant, secure by design, and ready for future growth. And for those who need absolute certainty, the hybrid approach offers truly bulletproof authorization.

If you want to dive deeper, check out Cerbos Hub, join one of our engineering demos or check out our in-depth documentation.