The Kladde can send mail, synchronize appointments, store files and post messages. In operation, what shows is whether it still does so on a bad day: when Graph throttles, when a service answers and you do not know whether the request arrived, when a permission is missing or a secret expires. This lesson makes the calls of lessons W4.2.1 through W4.3.1 fit for operation. It does not repeat what K2 and K3 teach: the rules for retries and the unclear outcome (lesson 2.8.3, “Retrying without sending twice”), the outbox (lesson 2.8.4, “The outbox pattern”), tests without a network (lesson 2.8.1, “HttpClientFactory and an external API”), the managed identity (lesson 3.3.1, “No keys: managed identity”), the retry handlers (lesson 3.9.2, “Retrying with care”) and telemetry (lessons 3.4.1 through 3.4.5). It applies them to Graph.
On the status of this lesson. None of it was run against a Microsoft 365 tenant: not run against a tenant. Requests, responses, commands and permissions come from pages of Microsoft Learn (at the end under “Further reading”); what they do not answer is marked “open”. Whatever needs a tenant runs only in a test tenant, never in a production tenant, and every such exercise has a part that runs without a tenant.
Throttling: 429, 503 and Retry-After
Graph limits how much an application may ask for at once. If it crosses a threshold, the service limits further requests from that application for a while, answers with 429 Too Many Requests, the requests fail, and the response names a
suggested wait in the Retry-After header. The thresholds depend on the kind and number of requests: writes are throttled sooner than reads, and write calls can be throttled while read calls are not. According to Microsoft, the most common causes are
many requests from all applications of a tenant and many requests from one application across all tenants. The response looks like this (Microsoft's example; the timestamp is made up):
HTTP/1.1 429 Too Many Requests
Retry-After: 10
{
"error": {
"code": "TooManyRequests",
"innerError": { "code": "429", "date": "2020-08-18T12:51:51", "message": "Please retry after", "request-id": "94fb3b52-452a-4535-a601-69e0a90e3aa2", "status": "429" },
"message": "Please retry again later."
}
}
What Microsoft advises for dealing with it, in the order in which the Kladde implements it:
- React to
429, not to the text: wait the seconds fromRetry-After, then retry. If429comes again, you are still throttled: keep waiting as the service advises. The service keeps counting while a client is throttled; immediate retries make it worse, because all requests go on your account. - If
Retry-Afteris missing, Microsoft recommends retrying with a growing pause (exponential backoff). 503 Service Unavailableyou treat similarly (wait, often withRetry-After), and you send new retries over a new HTTP connection. The “Best practices” page says so explicitly.- Ask less: fewer operations per request, ask less often. Anyone who constantly polls for changes or regularly searches resources in full is throttled sooner. That is what delta queries and change notifications are for (lesson W4.2.3).
- Large volumes do not belong in REST calls: for those Microsoft points to Microsoft Graph Data Connect, which is not subject to the throttling limits. That is not part of this course.
The limits per service are on a page of their own (“Service-specific limits”). This lesson gives no number from it because it was not read.