Recent searches


No recent searches

App request has been throttled



Posted Mar 30, 2023

Hi,

I'm trying to address an issue with my app which I submitted to the app store, but has blockers. The final blocker is to do with rate limiting. I was given the following instruction:

  • We ask that you include a backoff and proper 429 error messaging for rate limiting. You should implement a custom back off strategy in an exponential fashion (1s, 2s, 5s, 10s, 30s, 5 min intervals).

I have first implemented an error trap for 429 errors. It looks like this:

myURL = "retry"
while(myURL = "retry"){
    myURL = await client.request(settings).then(
        function(data) {
                // DO STUFF
        },
        async function(response) {                    
            if (response.status === 429) {
                const retryAfter = response.headers.get('retry-after')

                console.log("429 error")
                await sleep(retryAfter)
                return "retry"
            }
            else
            {
                // DO SOMETHING ELSE
            }                        
        },
    );
}

I was hoping that this approach would make it unnecessary to implement the exponential back off -- as after the 429 error, it would wait the appropriate amount of time before retrying the API. When testing this I have found that no 429 errors are occurring (or at least no message is going to the console). But I am getting this warning to the console:

... app request has been throttled: /api/v2/search.json?query=...etc

First, would I still need the exponential back-off strategy if I am using the 'wait until', as above.

Second, can anyone explain why I am getting throttling messages but no 429 error.

Help is appreciated.

Thanks.


0

7

7 comments

image avatar

Greg Katechis

Zendesk Developer Advocacy

Hi Simon!

To answer your first question, you could utilize the retry-after strategy that you implemented above, however I believe that the reason we have the exponential back-off recommendation is in the event that the API does not include that header. From what I can recall, there was a point where we may not have always included that and it's also possible that a new API or a change could briefly miss it. To that end, it might be a safe bet to include the back-off as well, but if that feels too cumbersome, I would submit the app without it as that feels sufficient. That decision isn't up to my team though, so you may be told something different.

Regarding the second issue, it's possible that you were throttled by ZAF instead of the API, although that probably should have sent a 429 as well. Does this happen consistently or was it just the one time?

0


Hi Greg Katechis,

Thanks for your reply. I think I will submit the code without the back-off strategy and see if it is accepted.

For the throttling message, I get this every time that I do a test involving many calls to the API. It works fine for a while (presumably because the threshold hasn't been passed) but then I get the throttling messages adding up.

I tried adding "autoRetry: false," option to the request, but I still get the throttling warnings.

I've tried running it in development mode (zat=true) and also installing it on Zendesk, but the results are the same for both.

Thanks.

0


image avatar

Greg Katechis

Zendesk Developer Advocacy

So I checked our logs for any instances of 429s hitting the search endpoints throughout all of the Zendesk for the last week and I only found two accounts and neither of them were yours. Just to be safe, I checked our edge logs to see if it was somehow getting routed through that layer, but nothing came up there either. I even tried simulating by spamming an app with search queries and I couldn't get it to budge.
 
To that end, I'd like to see your implementation of the request just in case there's something funny in the options. If you wouldn't mind passing along the settings you're using for that (and the rest of the block as well), I'll be glad to look into this!

0


Hi Greg Katechis,

Sorry, I didn't see your reply until now.

Here is the function that shows the throttling warnings in the console (note that it never reaches the 429 error code):

 

// ------ Get the IDs of open tickets for users in the list -----
async function getOpenTicketsForUsers(){
  
    userTicketIDs = [];
    
    // loop users and find unclosed tickets for user
    for(u=0;u<userIDs.length;u++){    
        userID = userIDs[u];
        API = "/api/v2/search.json?query=status<closed requester:" + userID;
        
        myURL = encodeURI(API);

        pageCounter = 1;

        while(!(myURL===null)) // loop through until no 'next page'
        {
            var settings = {
                url: myURL,
                type:'GET',
                dataType: 'json',
                autoRetry: false,
            };

            // NEW for rate limiting purposes
            myURL = "retry"
            while(myURL = "retry"){
                myURL = await client.request(settings).then(
                    function(data) {
                        tempIDs = [];
                        txt = getJSONInfo2(data);
                        nextURL = txt.next_page;

                        openTickets = txt.results;
                        recordCount = txt.count; //parseInt(txt.count);
                        if(recordCount>100)
                        {
                            if(nextURL===null)
                            {
                                recordCount = recordCount % 100;
                            }
                            else
                            {
                                recordCount = 100;
                            }
                        }
                        
                        for (t = 0; t < recordCount; t++) {
                            tempIDs.push(openTickets[t].id);
                        }
                        userTicketIDs = userTicketIDs.concat(tempIDs);
                        return nextURL;
                    },
                    async function(response) {
                        showError(response);                        
                        
                        // NEW -- catch 429 error
                        if (response.status === 429) {
                            const retryAfter = response.headers.get('retry-after')
                            console.log("retry 1")
                            await sleep(retryAfter)
                            return "retry"
                        }
                        else
                        {
                            console.log("null 1")
                            return null
                        }                        
                    },
                );
            }
        }
    }
    return userTicketIDs;
}

0


Hi Greg Katechis

Have you managed to look at my throttling issue yet?

Thanks,

Simon.

0


Hi Greg Katechis

Have you managed to look at throttling issue yet?

I have a very similar problem, I would like to see the answer of this thread.

Thanks,

0


Hi Greg Katechis

C.C. Paulo Filho

I've done some load testing on the API, which produced many 'throttling' warning messages, but no 429 errors in the main (I did get a single one at one point, but couldn't reproduce). I feel the throttling is something beyond my control to catch in the code, so I think that the 429 error trap is the best I can do.

I have also modified the error trap (I think either the syntax was wrong for returning the "retry-after" value, or it may not return this for all API calls). The new error trap implements an exponential back-off strategy. Here is a snippet of the code:

if (response.status === 429) {
                    retryAfter = 1000 * Math.pow(2, W);
                    W = W + 1; //exponential increase in wait time.
                    await sleep(retryAfter)
                    return "retry"
}

I should note that I seem to be getting fewer throttling messages in my app since making changes, but this may or may not be due to other factors. Under certain circumstances I may get as many as previously (?).

As far as I'm concerned, we can close this thread. I'm going to mark this post as 'answer'.

Thanks, Simon.

1


Please sign in to leave a comment.

Didn't find what you're looking for?

New post