The Decision Engine
Every single API call made to AWS — whether from the console, CLI, or SDK — passes through the IAM policy evaluation engine. This engine combines every policy that could possibly apply to your request and produces a single binary answer: Allow or Deny.
Understanding this evaluation order is not just academic. It is the mental model you use every time you debug an AccessDenied error.
The Evaluation Order
1. Explicit Deny — The Veto
AWS scans every applicable policy for any statement with "Effect": "Deny". If one exists, the request is rejected immediately and unconditionally. No other policy can override an explicit deny. This is the most powerful statement in IAM.
2. Implicit Deny — The Default
If no explicit deny exists, the default answer is still No. AWS does not grant permissions unless something explicitly says to. This "default closed" posture means a brand-new IAM user with no policies attached can do absolutely nothing.
3. Explicit Allow — The Permission
An explicit allow in an applicable policy overrides the implicit deny. The request proceeds — but only if it also clears the Permission Boundary and SCP checks (covered in the next sections).
The hierarchy in one line:
Explicit Deny > Explicit Allow > Implicit Deny (default)
What Counts as an "Applicable Policy"?
AWS considers all of the following simultaneously:
| Policy Type | Where It Lives | What It Controls |
|---|---|---|
| Identity Policy | Attached to User/Role/Group | What the identity can do |
| Resource Policy | Attached to the resource (S3, KMS, etc.) | Who can access this resource |
| Service Control Policy (SCP) | AWS Organizations | Account-level ceiling |
| Permission Boundary | Attached to User/Role | Maximum effective permissions |
| Session Policy | Passed at AssumeRole time |
Temporary scope reduction |
A senior engineer's instinct when seeing AccessDenied is to mentally walk through this table and ask: "Which layer is blocking this?"