Question about throttling/quotas/design

We have a third party customer-facing returns portal. Their webhooks are incredibly unreliable, so I just use hit up their API once a day. These need matching RMAs in Shiphero. Easy.

First step is figuring out the Shiphero IDs on all those orders. Brain-dead simple query, great.

Our customers create about 300 returns per day. Each lookup costs 101 credits…restore 15 credits per second…hold on. That’s 32 and a half minutes, just to fetch the order IDs; then an additional half-hour to submit the mutations.

This is roughly the 4th project I’ve tried to work your graphql into. Every time, the throttling has been so intense that I’ve just pursued alternate data sources.

Am I missing something huge here? I’m so confused, 6.73 seconds budgeted to look up a single order property? Say 200ms round trip on the request, my method will be idle 97% of the time when chain requesting. With lambdas capping at 15 minutes, I guess I’ll just split that into 12 invocations with 2 hour windows.

Hi @askthebird!
Would get many order id’s work for you?
This would be, making the orders query and filtering by created date. Then you could get more than one at a time

These quota restrictions are ridiculous. I don’t even know how many times to call the API until one of them comes back with “hasNextPage” false. What used to take me literally a second in the REST API is going to take me… well, I don’t know! 10 orders at a time, with a minute and 10 seconds between each call. Could be half an hour, could be 45 minutes.
Have you considered adding in a “total Pages” or a “total” on the orders request? If not, then you should definitely raise the quota instead of giving us advice that you know isn’t going to solve the actual question asked.

Hi @SS_Adam!
Absolutely!, I just made a Feature Request for this to be added, I will let you know as soon as I get a response back about it.

It would look something like this:

pageInfo{
          hasNextPage
          hasNextPage
          totalPages
        } 

Does that sound good?

On the other hand, do you happen to have a request_id for that orders query? Maybe I could see if we can optimize it and getting it to consume fewer credits.
Thanks in advance!
Tom

Yes, querying for multiple order IDs at the same rated complexity would speed up this workflow.

Though, to be honest, I think the current credit return rate is impractically low. A common use case for a lot of your API users is going to be querying stuff on the scale of their daily order volume in a batched job. For a 200 order per day business, that’s still 22 minutes of hardware idling for the most basic queries.

Even if this theoretical task could be done on-demand with webhooks, it won’t be long before these users will need to implement queues to schedule/prioritize requests to prevent congestion.

Another example – with some back-of-the-envelope calculations, if you applied these throttling limits to yourselves then calculating this page for very basic columns over 25 shipments then the load time would go up to ~3 minutes.

Perfect, maybe that approach helps if you just need the ids for those orders @askthebird

On the other hand, when you mentioned this:

Do you happen to have the query for getting the order info? It should not be consuming that many credits, maybe you could add the first filter on the line items section?

We are currently working on speeding up that report (actually making one new on our endeavour screen) so there should be updates soon. It is taking time to load right now, but we are working on that.

Thanks again!
Tom

The query is:

query {
            orders(partner_order_id: "${shopify_id}") {
                complexity
                data {
                    edges {
                        node {
                            id
                        }
                    }
                }
            }
        }

It was my understanding that all queries had a minimum cost of 101 credits.

Edit: I wasn’t complaining about the actual report. I was saying (as an example) that if I used the new API to do the same thing as that report, the required queries would take about 3 minutes of real time due to throttling.

Oh sorry I misunderstood, I thought you were referring to the Order query (which if you are getting one order at a time it should be 1)

All queries have a minimum cost of 1, but you can see it using the analyze field, for example:

query {
  order(id: "111111112222", analyze: true) {
    complexity
    data {
      id
    }
  }
}

Should return you something like this

{
  "data": {
    "order": {
      "complexity": 1,
      "data": null
    }
  }
}

And this should not consume your credits, it should just show you the cost that the query will have if you don’t include the analyze or set it as analyze:false

Is the quoted cost for my query correct? 101 to look up legacy_id, starting from order_number? Is there a more efficient way to do this?

That query also returns a complexity of 101 for me too. On the old system, within a second or two, I could have a list of every order that happened yesterday, along with the line items those orders contained, all in one easy-to-parse JSON bundle.

That is correct, with that Query (orders) of complexity 101 you should be able to get 100 Order ids back, however, if you are using the partner_order_id then you would need to use first

query {
            orders(partner_order_id: "${shopify_id}") {
                complexity
                data(first:1) {
                    edges {
                        node {
                            id
                        }
                    }
                }
            }
        }

Which will only return you one order and the complexity should be of 2
This is assuming you just need this one order back

Let me know if that doesn’t help
Thanks again!

Wow. Yeah, that first:1 helps. 20x less credits used. Thank you!
That’s kind of unexpected that specifying the number of results does this.

1 Like

Yes, that might not be that intuitive, all of the fields/connections when not including a first filter it will default to the maximum amount allowed to return, which is 100.
And as the complexity is calculated before getting the results, it will calculate it using 100, even though there will return only 1 result that matches that criteria

hey @askthebird, we were talking internally about hosting some developer q&a session to go over some of the helpful tips working with graphql. Heads up that’s coming soon :slight_smile:

2 Likes

Hi @SS_Adam
I apologize for the delayed response. I got a response from our engineering team about the request and they explained to me that it won’t be possible to add a totalPages field on the Query, right now, the pagination will need to be made using the hasNextPage value and using the cursors.
I apologize for any inconvenience and please let me know if there is anything else I could assist you with.
Thanks again!
Tom