When the plan indicates the principal can never access the requested resource for that action, the application should short-circuit rather than send a pointless database query. Returning an empty set or raising an application-specific error depends on product behavior, but the key point is to avoid executing retrieval work when policy already denies access.
Why an ALWAYS_DENIED plan should bypass retrieval work
An ALWAYS_DENIED plan is a policy result, not a query hint. If the policy engine has already determined that the caller can never access the target for the requested action, the application gains nothing by sending a database query that will only reproduce the same denial in a slower, noisier way. Treat the plan as a control decision, then stop.
This distinction matters because retrieval work is not free: it consumes database capacity, adds latency, and can create logging and observability noise that makes real access problems harder to diagnose. It also helps preserve a clean separation between policy evaluation and data access, which makes authorization failures easier to reason about and less likely to leak implementation detail.
- If the denial is absolute for the current action and principal, short-circuit before the data layer.
- If the application contract expects “no rows” for this case, return an empty set consistently rather than simulating a normal query path.
- If product behaviour treats denied access as a user-visible error, raise it at the application boundary, not by querying and then discarding the result.
Where empty result handling is the right abstraction
Returning an empty result is usually appropriate when the caller is allowed to ask the question but not allowed to see any matching data for that action, and the product semantics treat denial as indistinguishable from “nothing available.” That can be a sound API design choice when the goal is to avoid revealing whether a resource exists, while still keeping the application flow simple.
The key is consistency. An ALWAYS_DENIED plan should not sometimes become a query, sometimes become an empty collection, and sometimes become an exception based on incidental code paths. Pick the behaviour that matches the product contract and keep the execution path deterministic so teams do not accidentally reintroduce retrieval work in “no access” cases.
- Use an empty result when the caller-facing contract is list-like or search-like.
- Use an application-specific denial error when the caller must distinguish “not permitted” from “not found.”
- Do not treat the database as the authority for a decision the policy engine already settled.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 address the attack and risk surface, while NIST CSF 2.0 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | PR.AC — Access Control | Hard denial plans are an access-control decision that should block retrieval. |
| Recommendation — Enforce access decisions before data access and return the product-defined denial response. | ||
| CIS Controls v8 | 5 — Account Management | Authorization failures should prevent unnecessary access attempts and limit exposed paths. |
| Recommendation — Apply account and access controls so denied principals cannot reach protected data paths. | ||
| OWASP Non-Human Identity Top 10 | NHI-01 — Secrets and Credential Management | Policy-driven denial reduces needless execution around privileged identities and access paths. |
| Recommendation — Prevent denied identities from triggering downstream retrieval or privileged execution. | ||
Practitioner Guidance
What to verify: Confirm that ALWAYS_DENIED really means the principal can never succeed for that resource-action combination, not merely that the current request lacks one attribute or scope. If future policy conditions could change the answer, the plan is not an unconditional short-circuit signal.
Decision rule: If the plan is a hard denial, make the application return its chosen denial shape directly, and reserve database access for plans that can still produce a meaningful allowed-or-partially-allowed result. That keeps authorization logic authoritative and prevents accidental “query then deny” patterns from spreading.
Practitioner takeaway: Treat ALWAYS_DENIED as an execution stop, not a query optimization hint; the correct behaviour is the one that preserves policy authority, avoids pointless retrieval, and matches the product’s denial contract.
Related resources from NHI Mgmt Group
- What happens when security teams treat detection engineering as a one-time project instead of a continuous process?
- What do teams get wrong when they treat privacy by design as a policy exercise instead of an engineering practice?
- How should product teams decide what feature to build next when they have limited engineering time?
- Why do cloud identity and access decisions become harder when engineering and DevOps teams control resource access?
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 20, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org