An AI tool in Foundry for analyzing documents and media to classify content, extract entities, and generate structured understanding
Your S0 resource is subject to 1,000 analyzed pages/images per minute and 3,000 operations per minute, so cap aggregate submissions and polling below both limits; Microsoft does not publicly document these Content Understanding quotas as adjustable, so any increase or backend-capacity review must proceed through your existing Azure support case.^1^
What the measurements indicate
The published S0 resource limits are:
| Limit | S0 value |
|---|---|
| Analysis throughput | 1,000 pages/images per minute |
| Operations | 3,000 operations per minute |
Your 120-request test generated both:
- 120 asynchronous
Analyzeoperations. - Up to 120
GetResultrequests every two seconds while those analyses remained active.
At full polling concurrency, the GET traffic alone can reach approximately:
120 operations × 30 polls/minute = 3,600 GetResult calls/minute
That is above the documented 3,000 operations/minute, before counting Analyze submissions and retries. This is consistent with both Analyze and GetResult returning 429 during the burst. Conversely, 24 active operations polling every two seconds generate about 720 GETs/minute, which is consistent with the successful book run.
The page limit must be enforced independently:
submitted parts/minute × pages/part <= 1,000 pages/minute
These calculations are workload planning estimates; the documentation does not define the exact accounting window or whether every rejected attempt is counted identically.
Recommended production controls
- Keep the current 24-analysis concurrency as the initial ceiling. Your real workload already completed successfully at that level.
- Use one global limiter for POST and GET traffic. Do not give each document its own independent 24-request pool; otherwise simultaneous books can multiply resource-wide traffic.
- Budget below 3,000 operations/minute, leaving capacity for retries and other analyzer operations.
- Budget below 1,000 submitted pages/minute.
- Honor
Retry-Afteron every 429, adding jitter so all workers do not retry simultaneously. Queue delayed work rather than holding many blocked workers. Microsoft’s resilience guidance recommends respecting retry headers, bounded retries, and gradual traffic recovery.^2^ - Poll only operations that are still
RunningorNotStarted, and stop immediately at a terminal state. The documented normal interval is one to two seconds, so your two-second interval is valid; it is the aggregate number of pollers that needs limiting.^3^
A minimal urllib wrapper can handle the returned delay:
import random, time
from urllib import request, error
def send(req, attempts=8):
for attempt in range(attempts):
try:
return request.urlopen(req, timeout=120)
except error.HTTPError as exc:
if exc.code != 429 or attempt == attempts - 1:
raise
retry_after = exc.headers.get("Retry-After")
delay = float(retry_after) if retry_after else min(2 ** attempt, 30)
time.sleep(delay + random.uniform(0, 0.25))
Also consider submitting larger PDF ranges instead of fixed 25-page pieces when your processing requirements permit it. Asynchronous PDF analysis now supports up to 2,000 pages and 200 MB, so the 1,610-page book might not require 65 separate Analyze operations if it fits the file-size limit.^1^ Fewer analysis operations also mean fewer independently polled result URLs.
Capture evidence for the support engineer
For API 2025-11-01, add this header to every result GET, not merely the Analyze POST:
x-ms-diagnostics: true
Completed responses can then include result.infos, such as LLMStats latency information. The property is optional and its message should be treated as diagnostic text rather than stable telemetry.^4^
Add the following to the existing case:
- Resource ID and UK South region.
- Exact UTC test windows.
- API version, analyzer ID, S0 tier, and
processingLocation. - Concurrency, page size, submission rate, and polling rate.
- Full 429 response body and
x-ms-error-code. -
Retry-After, request/correlation IDs, and client-generatedx-ms-client-request-id. - Separate counts for Analyze 429s and GetResult 429s.
- Azure Monitor total calls, throttled calls, and latency around the test window.
- A request to confirm whether throttling came from the published resource limits or transient backend capacity.
- A request to confirm whether the two Content Understanding S0 limits are adjustable for this resource and region.
Microsoft Q&A cannot attach an engineer or schedule a call on an existing private support case. Request a callback/Teams session in the case communication, include availability and time zone, and ask for escalation to the Azure AI Content Understanding service team if quota accounting or regional capacity must be inspected.
The REST contract confirms that Analyze is an asynchronous POST returning Operation-Location, followed by result retrieval through the operation URL.^5^
References
- Azure Content Understanding in Foundry Tools service quotas and limits
- Design throttling to improve resilience
- Quickstart: Use Azure Content Understanding in Foundry Tools (programming-language-rest)
- Retrieve diagnostics from Azure Content Understanding in Foundry Tools
- Content Analyzers - Analyze - REST API (Azure Azure AI Services)