The RCP quota for AWS Organizations has doubled, so I checked the limit of 2,000
This page has been translated by machine translation. View original
Introduction
On July 22, 2026, the per-organization limit for Resource Control Policies (RCPs) in AWS Organizations was raised from 1,000 to 2,000.
| Item | Before | After |
|---|---|---|
| RCP limit (per organization) | 1,000 | 2,000 |
Below are the quotas and API rate limits related to RCPs.
| Item | Value |
|---|---|
| RCP policy size limit | 5,120 characters |
| RCP attach limit (per root/OU/account) | 5 (including RCPFullAWSAccess) |
| CreatePolicy/DeletePolicy/AttachPolicy/DetachPolicy | rate 2/sec, burst 3 |
Details for each quota are summarized in the documentation.
Verification Details
Verification Environment
| Item | Value |
|---|---|
| Execution source | Test Organization management account |
| Region | us-east-1 (Organizations API endpoint) |
| CLI | AWS CLI v2 (latest) |
| RCP policy type | Enabled |
| Test Organization | All features enabled, isolated environment |
Pre-check
At the start of verification, the only existing RCP was the AWS managed policy RCPFullAWSAccess. The created RCPs were not attached anywhere.
Content of Policies to Create
The following minimal Deny statement was used for the 2,000 RCPs to be created. It specifies a non-existent region xx-nonexistent-1 as a condition, making it safe content that would not affect actual operations even if accidentally attached.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyNonexistentRegionNoOp",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "xx-nonexistent-1"
}
}
}
]
}
Creating 2,000 RCPs
Taking into account the CreatePolicy rate limit (rate 2/sec, burst 3), a script with a 0.5-second sleep per item and exponential backoff (up to 30 seconds) on ThrottlingException was used to attempt creating 2,001 policies.
Full creation script
#!/usr/bin/env bash
# RCP 2,001 creation script (expects success up to #2,000 → quota error on #2,001)
set -uo pipefail
ARTICLE_DIR="/path/to/article"
POLICY_CONTENT="$ARTICLE_DIR/logs/rcp-policy-content.json"
RAW_DIR="$ARTICLE_DIR/logs/raw"
MILESTONE_LOG="$ARTICLE_DIR/logs/raw/milestones.log"
SUMMARY_LOG="$ARTICLE_DIR/logs/raw/create-loop-summary.tsv"
TOTAL=2001
START_INDEX=1
REGION="us-east-1"
echo -e "index\thttp_status_or_error\telapsed_ms\tpolicy_id\tthrottled_retries" > "$SUMMARY_LOG"
: > "$MILESTONE_LOG"
start_all=$(date +%s.%N)
throttle_count=0
for i in $(seq $START_INDEX $TOTAL); do
name="rcp-quota-test-$(printf '%04d' "$i")"
backoff=1
retries=0
t0=$(date +%s.%N)
while true; do
out=$(aws organizations create-policy \
--name "$name" \
--description "RCP quota test policy #$i" \
--type RESOURCE_CONTROL_POLICY \
--content "file://$POLICY_CONTENT" \
--region "$REGION" \
--output json 2>&1)
rc=$?
if [ $rc -eq 0 ]; then
break
fi
if echo "$out" | grep -q "ThrottlingException\|TooManyRequestsException"; then
throttle_count=$((throttle_count+1))
retries=$((retries+1))
sleep "$backoff"
backoff=$((backoff * 2))
if [ $backoff -gt 30 ]; then backoff=30; fi
continue
else
# Other error (quota exceeded, etc.) → exit loop and record
break
fi
done
t1=$(date +%s.%N)
elapsed_ms=$(awk "BEGIN {printf \"%.0f\", ($t1 - $t0) * 1000}")
if [ $rc -eq 0 ]; then
policy_id=$(echo "$out" | grep -o '"Id": "p-[^"]*"' | head -1 | sed 's/"Id": "//;s/"//')
echo -e "${i}\tSUCCESS\t${elapsed_ms}\t${policy_id}\t${retries}" >> "$SUMMARY_LOG"
echo "$out" > "$RAW_DIR/create-$(printf '%04d' "$i").json"
else
echo -e "${i}\tERROR\t${elapsed_ms}\t-\t${retries}" >> "$SUMMARY_LOG"
echo "$out" > "$RAW_DIR/create-$(printf '%04d' "$i")-error.json"
echo "[$i] ERROR: $out" >> "$MILESTONE_LOG"
fi
if [ "$i" -eq 1000 ]; then
echo "[MILESTONE] #1000 index=$i rc=$rc elapsed_ms=$elapsed_ms" >> "$MILESTONE_LOG"
fi
if [ "$i" -eq 1001 ]; then
echo "[MILESTONE] #1001 (breaking old limit) index=$i rc=$rc elapsed_ms=$elapsed_ms" >> "$MILESTONE_LOG"
fi
if [ "$i" -eq 2000 ]; then
echo "[MILESTONE] #2000 (reaching new limit) index=$i rc=$rc elapsed_ms=$elapsed_ms" >> "$MILESTONE_LOG"
fi
if [ "$i" -eq 2001 ]; then
echo "[MILESTONE] #2001 (expected error) index=$i rc=$rc elapsed_ms=$elapsed_ms" >> "$MILESTONE_LOG"
fi
# Basic sleep considering rate 2/sec, burst 3
sleep 0.5
done
end_all=$(date +%s.%N)
total_elapsed=$(awk "BEGIN {printf \"%.1f\", ($end_all - $start_all)}")
echo "[SUMMARY] total_elapsed_sec=$total_elapsed throttle_count=$throttle_count" >> "$MILESTONE_LOG"
echo "DONE total_elapsed_sec=$total_elapsed throttle_count=$throttle_count"
| Milestone | index | Result | elapsed_ms |
|---|---|---|---|
| Creation of #1,000 | 1000 | Success | 1187 |
| Creation of #1,001 (breaking old limit of 1,000) | 1001 | Success | 1158 |
| Creation of #2,000 (reaching new limit) | 2000 | Success | 1149 |
| Creation of #2,001 (expected error) | 2001 | Failure | 1047 |
No individual quota increase request was submitted for this verification environment. The fact that creation beyond 1,000 was possible without a request, and that creation succeeded up to #2,000, confirms that the new limit is in effect in this verification environment.
Confirming the Error on #2,001
The following error was returned for the 2,001st policy.
An error occurred (ConstraintViolationException) when calling the CreatePolicy operation:
You have exceeded the allowed number of policies.
Additional error details:
Reason: POLICY_NUMBER_LIMIT_EXCEEDED
Since the 2,000th creation succeeded and this error was returned on the 2,001st, it confirms that the custom RCP limit per organization is 2,000.
At this point, the total count from list-policies --filter RESOURCE_CONTROL_POLICY was 2,000 custom RCPs + 1 AWS managed policy (RCPFullAWSAccess) = 2,001 in total. From this result, it can be determined that RCPFullAWSAccess is not counted toward the 2,000 custom RCP creation limit per organization.
Throttling Measurements
The measured values are as follows.
| Item | Value |
|---|---|
| Number of throttling occurrences | 0 |
| Average response time per policy | Approx. 1.1–1.2 seconds |
| Sleep within loop | Fixed 0.5 sec/item (no backoff triggered) |
| Total elapsed time (2,001 attempts) | 3,314.1 seconds (approx. 55 min 14 sec) |
| Effective throughput | Approx. 0.60 items/sec |
This time, sequential execution caused approximately 1.1 seconds per API response, so the actual request interval including the fixed 0.5-second sleep was approximately 1.6 seconds. No throttling occurred under these conditions. The expected time for bulk creation is roughly (API latency + sleep) × number of items.
Cleanup
After verification was complete, all 2,000 created RCPs (excluding RCPFullAWSAccess) were deleted.
Summary
With the RCP limit expanded to 2,000, there is more room to design finer-grained guardrails per OU, account, and protected resource.
However, when increasing the number of policies toward the limit, the time required for maintenance and updates cannot be ignored. In this verification, sequential creation achieved approximately 0.60 items/sec, meaning processing at the scale of 2,000 items cannot be completed in a short time. Similarly for update operations, an execution plan that accounts for API response times and Organizations API rate limits will be necessary.
Performance and throttling behavior when increasing parallelism were not verified in this article. Therefore, when beginning to design with the assumption of 2,000 policies, it is advisable to evaluate in advance not only the number of policies, but also how quickly full updates, incremental changes, and emergency fixes can be performed.
Although the RCP policy count limit has increased, rather than consolidating all controls into RCPs, please consider appropriately combining RCPs with SCPs and other mechanisms based on their respective use cases, update frequency, and management costs.



