TL;DR: Externalized authorization pushes access decisions out of application code and into a policy engine, then uses query planning to filter data at the database layer instead of row-by-row in the app, according to Cerbos. That pattern reduces waste, but it also makes policy expressiveness, fallback post-filtering, and query planning discipline core IAM design concerns.
NHIMG editorial — based on content published by Cerbos: externalized authorization in Convex and query plan filtering
Questions worth separating out
A: Security teams should centralise policy in a dedicated engine, then translate the resulting decision or query plan into database-native filtering wherever possible.
Q: Why do query plans improve authorization performance for data-heavy applications?
A: Query plans let the authorization engine describe the conditions for access once, then let the database apply those conditions using its own indexes and execution engine.
Q: Where does externalized authorization fail in practice?
A: It fails when teams treat the policy engine as separate from data access and allow broad post-filtering or duplicate logic in the application.
Practitioner guidance
- Map policy attributes to queryable fields first Align principal, resource, and action attributes with database columns or filterable properties before writing policies so the query layer can enforce access without broad client-side reads.
- Minimise post-filter usage for sensitive datasets Review any policy that depends on unsupported string or collection operators and decide whether the exposure created by reading data before full evaluation is acceptable.
- Separate policy evaluation from application logic Remove duplicate authorization checks from code paths and make the policy engine the single source of truth for permit, deny, and query-plan generation.
What's in the full article
Cerbos' full article covers the implementation detail this post intentionally leaves for the source:
- Concrete code examples for queryPlanToConvex, including how filter and postFilter are returned in practice
- Operator-by-operator breakdown of what Convex can push to the database and what must be evaluated in JavaScript
- Working policy and query snippets showing how attribute mapping drives query planning
- Guidance on when allowPostFilter should be enabled and what the safety trade-off looks like
👉 Read Cerbos' guide to externalized authorization and Convex query plans →
Externalized authorization in Convex: are your filters in the right place?
Explore further