Homeβ€Ί Blogβ€Ί AWS Architecture Series #103 β€” It does not deny the API; it sets the value…
AWS Architecture AWS Architecture Series

AWS Architecture Series #103 β€” It does not deny the API; it sets the value

An SCP and a declarative policy both arrive from the organization and both stop people doing things, so they get filed together. They work in different places: one decides whether an API call is allowed, the other decides what the service's configuration is. That difference explains which one covers service-linked roles, which one survives a new feature launch, and what happens when you take it away.

Verified against current vendor documentation on 4 November 2026. Pricing, limits and API behaviour were checked against the official docs on that date. Cloud services change fast — if you are reading this much later, treat the specifics as a starting point and re-check the linked sources.

Business Challenge

The distinction is stated in one sentence and it is worth reading twice:

“Declarative policies are enforced in the service's control plane, which is an important distinction from authorization policies such as service control policies (SCPs) and resource control policies (RCPs). While authorization policies regulate access to APIs, declarative policies are applied directly at the service level to enforce durable intent.”

An SCP answers may this principal make this call? A declarative policy answers what is this service's setting? The first is a gate on the path; the second is the value at the destination. Three consequences follow, and none of them is obvious from the policy editor.

1It covers service-linked roles, and the authorization policies do not

AWS's own comparison table has a row that is easy to scroll past. Against “Governs service-linked roles?”, service control policies answer No, resource control policies answer No, and declarative policies answer Yes.

That is a real gap closed. An SCP is evaluated against a principal, and a service-linked role acting on the service's own behalf is outside what it constrains — which is why an estate that believes an SCP covers everything has a category of activity it has never governed. A declarative policy does not care which principal acted, because it is not evaluating a principal. It is asserting what the configuration is.

Fix

If a control genuinely must hold regardless of who or what acts — including AWS services operating in your account — an SCP is the wrong instrument and a declarative policy may be the right one. Check the supported list first; the mechanism only covers the attributes AWS has onboarded.

2It survives the thing that breaks deny lists: a new feature

A deny-based SCP enumerates actions, so it is a statement about the API surface on the day it was written. Ship a new action and the policy silently stops being complete. Declarative policies do not have that failure mode by construction:

“Once attached, the configuration is always maintained when the service adds new features or APIs.”

AWS calls this “Set once and forget”, and extends it in the direction that usually costs estates the most: “The baseline configuration is also maintained when new accounts are added to an organization or when new principals and resources are created”, with “Accounts joining an organization will automatically inherit the declarative policy in the organization.”

That is the answer to the drift problem in #102, where a Regional, account-level setting has to be re-applied in every new account and every new Region to mean anything. The declarative version arrives with the account.

Fix

Where a setting exists in both forms, prefer the declarative one even for a single account, because the property you are buying is not today's value — it is that tomorrow's accounts, Regions and features inherit it without anybody remembering.

3Detaching it does not leave the setting where the policy put it

“If a declarative policy is detached, the attribute state will roll back to its previous state before the declarative policy was attached.”

So a declarative policy is a position held, not a change applied. While it is attached the value is what you declared; remove it and the account returns to whatever it had before — which, for an account that was non-compliant when the policy landed, means returning to non-compliant.

That is the same shape as the block public access settings in #102, and it is worth noticing that AWS has now built the pattern twice: the control suppresses a state rather than overwriting it, and the suppressed state is still underneath. Detaching a declarative policy during an incident to unblock a team does not leave the estate at the declared baseline. It restores the configuration the policy was hiding.

The other half of the same coin, from the services that implement it: “When a declarative policy is in use, you can't modify the setting directly within an account.” While attached, the local switch is gone.

Fix

Treat detaching as a configuration change with a blast radius, not as turning off a guardrail. Before you detach, know what each account's prior state was — the account status report is the tool for that, and the time to read it is before you need it.

Architecture

Diagram: declarative policies are enforced in the service's control plane while service control policies and resource control policies regulate access to APIs. The comparison shows that SCPs control the maximum available access permissions of principals at an API level and do not govern service-linked roles, RCPs do the same for resources and also do not govern service-linked roles, and declarative policies enforce the desired configuration of an AWS service without using API actions and do govern service-linked roles. Once attached, the configuration is always maintained when the service adds new features or APIs, and is maintained when new accounts join the organization, which inherit the policy automatically. If a declarative policy is detached, the attribute state rolls back to its previous state before the policy was attached, so the policy is a position held rather than a change applied, and while it is attached an account cannot modify the setting locally.

Three organization policies, three places they act

Service control policyResource control policyDeclarative policy
What it governs Principals Resources A service's configuration
How “controlling the maximum available access permissions of principals at an API level” The same, “for resources at an API level” “enforcing the desired configuration of an AWS service without using API actions”
Governs service-linked roles? No No Yes
Survives a new API Only if the policy anticipated it Only if the policy anticipated it Yes — “always maintained when the service adds new features or APIs”

The second row is the whole thing. An authorization policy produces a denial at the moment of a call; a declarative policy produces a value that is simply true of the service. That is why the third row can say yes: there is no principal to exempt.

What they can hold, which is the real constraint

Declarative policies are not a general configuration language. They cover the services AWS has onboarded and the attributes within them, and the current set is a good map of where this mechanism is going: EC2, Backup, Tag, chat applications, AI services opt-out, Security Hub, Amazon Bedrock, Amazon Inspector, upgrade rollout, Amazon S3, Shield Network Security Director and Amazon GuardDuty policies.

Three of those have appeared in this series in the past week, which is the clearest signal of how much this mechanism is now carrying. The Allowed Images setting AWS gives as its example policy is the control from Daily #67; the upgrade rollout policy is the middle path in Daily #66; and the S3 and EC2 policies are how the block public access settings in #102 stop being per-account chores.

Inheritance, and the report that tells you what is actually in force

“Declarative policies can be applied to an entire organization, organizational units (OUs), or accounts”, and what lands on an account is the combination: “The effective policy is the set of rules that are inherited from the organization root and OUs along with those directly attached to the account.”

Because the mechanism sets values rather than denying calls, the question what is in force here? has an answer you can read rather than compute: “The account status report allows you to review the current status of all attributes supported by declarative policies for the accounts in scope.” That is a materially better position than SCP evaluation, where the effective permission is the intersection of several documents and a simulation is the only honest way to know.

The failure message is configurable, and that matters more than it sounds

“You can also create customizable error messages, which can help administrators redirect end users to internal wiki pages or provide a descriptive message that can help end users understand why an action failed.”

Anyone who has watched an engineer lose an afternoon to an unexplained AccessDenied from an SCP they cannot read will recognise what this is worth. A control that explains itself at the point of failure is a control that generates fewer tickets and less resentment, and resentment is what gets guardrails removed.

Why This Architecture Holds Up

Enforcing configuration rather than access is the right fix for feature drift

Every deny-list policy decays, because the list is finite and the API surface is not. Moving enforcement into the control plane makes the guarantee about the service's state rather than about an enumeration of calls, and a statement about state does not need updating when a new call appears. That is a genuinely different durability profile, not a convenience.

Rolling back on detach is defensible, and must be understood

The alternative would be for AWS to leave accounts permanently mutated by a policy you removed, which would make attaching one far more frightening than it is. Reverting is the conservative choice. It does mean a declarative policy is a thing you hold rather than a thing you did, and the only real mistake is modelling it as the latter.

Covering service-linked roles closes a gap most people do not know they have

The limits of SCPs around service-linked roles are documented but rarely front of mind, and an estate can run for years believing its guardrails are universal. A mechanism that sidesteps principal evaluation entirely is the clean answer, and putting the comparison in a table beside the authorization policies is the right place to tell people.

Key Architecture Decisions

DecisionChoose thisBecause
Which policy type Declarative for a configuration baseline; SCP for who may act One sets a value “without using API actions”; the other bounds permissions at an API level
A control that must hold against AWS services too Declarative It is the only one of the three that governs service-linked roles
A per-account, per-Region setting Declarative, even for one account New accounts inherit it automatically; the local switch disappears while it is attached
Emergency removal Plan it before you need it Detaching rolls the attribute back to its prior state, which may be the non-compliant one
Explaining a denial Write the custom error message when you attach It is the difference between a guardrail people route around and one they understand

The audit worth running

Pull the account status report and read it as an inventory of what is actually in force. It covers all supported attributes for the accounts in scope, which makes it the one document that answers the question your SCPs cannot answer without simulation.

For every attached declarative policy, record what each account's prior state was. That is the state you return to on detach. Without it, removing a policy is an action whose outcome you cannot predict per account.

Then look at your deny-based SCPs and ask which of them are really configuration statements. A policy that denies every API that could turn a setting off is a deny list approximating a declarative policy, and it will be incomplete the next time the service ships something.

Closing Thought

The useful way to hold these three apart is by the question each one answers. An SCP answers whether a principal may call. An RCP answers whether a resource may be reached. A declarative policy answers what the setting is. Only the third is immune to somebody inventing a new way to ask.

The cost of that immunity is the rollback on detach. Because the mechanism asserts a value rather than changing one, the account's own value is still underneath, waiting. That is the same design as the block public access settings in #102, and seeing it twice in a week suggests it is becoming the house pattern for AWS guardrails: suppress, do not overwrite, and make removal safe by making it reversible.

Which is fine, as long as nobody reads compliant while the policy is attached as compliant.

Next in this series

Security & Identity — AWS Organizations tag policies: what a tag policy evaluates, what it does when a resource does not comply, and where the boundary sits between reporting and preventing.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent