• Explore. Learn. Thrive. Fastlane Media Network

  • ecommerceFastlane
  • PODFastlane
  • SEOfastlane
  • AdvisorFastlane
  • LifeFastlane

Implementing API Rate Limits In Your App


This is a complementary blog post to a video from the ShopifyDevs YouTube channel. This is the third post from a four-part series created by Zameer Masjedee, a Solutions Engineer with Shopify Plus. 

In the first part of this series, An Introduction to Rate Limits, we covered what exactly an API rate limit is, and how Shopify uses the leaky bucket algorithm. We followed up with a second post, API Rate Limits and Working with GraphQL, to explore the many benefits of GraphQL. 

In this post, I’ll take all the principles introduced to you in the first two parts of this series, and apply them in a practical application in a development store. First, I’ll walk you through what you’ll need to get started. Then, I’ll teach you how to make some key real-time requests to the Shopify API. 

By the end of this article you’ll have a practical understanding of how to make real requests to the Shopify API and how to responsibly consume your rate limit without running into any errors.

Note: All images in this article are hyperlinked to the associated timestamps of the YouTube video, so you can click on them for more information.

What you’ll need to get started

Today, we’re going to take some of the best practices and ideas we previously learned and implement them, all while employing some essential business logic. All this will be done in an application that we’re going to be working on for a development store. I’ll be using VS Code but feel free to use whatever IDE you like working in. 

Our example use case

In the example store that I’ve created, we have a bunch of products that are all associated with a commodity. They’re gold bracelets, and as we know, the price of gold fluctuates. In our development store, we create products whenever orders come in, so we need to ensure that we’re charging the right amount for them. As the price of gold changes, the price of our products also needs to change. There will be recurring time intervals where we have to take the entire product catalog and update the prices based on the most recent price of gold on the market.

There are a few steps we need to take to achieve this goal. First, we’re going to use a Node application to take a look at the products in my shop that might be impacted by an adjustment in the price of gold. Then, we’re going to implement some best practices in order to update those prices. We’re going to do all this in a way that respects the API rate limit and ensures your app isn’t getting throttled.

Before we proceed, If you’re new to GraphQL, I’d highly recommend checking out the GraphQL video series on the ShopifyDev’s YouTube Channel by my good friend Chuck Kosman. He walks you through all of those elements, including aliases, variables, and anything that I discuss in this post that might be unfamiliar. You can watch the first video of his series below, or read our accompanying tutorial.

We’re using GraphQL to control our variables, and its request package to be able to make some requests pretty simply. 

For this tutorial, I’m not going to build an official Shopify app. That would mean going through the app CLI tool and configuring it that way. We ultimately just want to test it out to see what it would look like if we did have this business logic in our application.

Build apps for Shopify merchants

Whether you want to build apps for the Shopify App Store, offer custom app development services, or are looking for ways to grow your user base, the Shopify Partner Program will set you up for success. Join for free and access educational resources, developer preview environments, and recurring revenue share opportunities.

Sign up

How to retrieve product information

The first thing that we’re going to do is make a request. This is demonstrated in the below highlighted query to Shopify.

Implement API rate limit: screenshot taken from Youtube video that shows a request to retrieve the first 200 products that match the query.

The request products(first: 200, query: “tag:gold”) is requesting to retrieve the first 200 products that match our query. In this case, we’re interested in any product that has been tagged as gold. We’re also asking for the id of those products. This is an easy way for us to identify the relevant products out of the entire catalog.

We’re interested in adjusting the price, and we know that the price in Shopify lives on the variant, so we need to take a look at the variant associated with that product. Finally, we’re going to issue a request for the ID and weight, because that’s what we’re going to use to calculate the new price. We need the weight to determine what to charge going forward. 

Another thing to note is that I’m cheating a little bit in the above example when I say variants(first: 1). I know that every single one of my products only has a single variant, because that’s how I’ve set up my store. You might have to play around with a larger number and take a look to see if products have more than one variant. We support up to 100 variants on Shopify, and that would result in some pagination, as you’re building a more nested query. For our purposes, variants(first: 1) works fine. 

Implement API rate limit: gif made made from timestamped Youtube video

The above shows that we’re making a request, graphQLClient.request, with our straightforward query. We’re going to capture those results (catch((error) => console.log(error)) and print them onto our console, console.log(JSON.stringify(queryData, undefined, 2))

Let’s take a look at what happens when I execute this query: 

Implement API rate limit: gif taken from timestamped Youtube video

You can see that the request yielded 200 different products. If we run another request for 10 products, it will yield 10 products. It’s important to understand that the response we get starts with the products key in JSON, and then we get our edges.

Implement API rate limit: giff taken from time stamped Youtube video

Each of these edges represents the object or the node that we’re interested in, which happens to be a product. For each of these nodes, we have the id and the variantss that are also associated with that product. This is the information I need to be able to implement my app. 

How to identify the API rate limit of your app

We know from the previous tutorials that there are costs associated with making a query or issuing updates. When doing so, we want to be able to get a sense of how much room we have left in our API rate limit. Shopify will provide this information to you in the form of an extension to your response. The only thing is, we aren’t necessarily able to grab it with the original library above by making a standard request, so we’ll have to issue a rawRequest.

Issuing a rawRequest to capture metadata and available rate limit

Below our standard request, we have an additional form.  

Implement API rate limit: Giff taken from timestamped Youtube video

This form uses the rawRequest input, which makes the exact same request with the same query, but with some additional information. Instead of getting just a data set back, we’re also getting the extensions, headers, errors, and statuses that are part of that request.

In this example, I’m making the exact same request as above, but also capturing and printing out the available rate limit after this request goes through.

When we issue that request:

Implement API rate limit: Screenshot image take from time stamped Youtube video showing an issued request

We see that we have 958 rate limit points available, in addition to the data we’re capturing. Recall that our bucket fills up at 1,000 points, so we have a lot of room left. 

Updating your products with individual mutations

The next step we want to take in our process is to update these products. To do so, we’ll make a mutation for each of these products individually.

Remember that when working with GraphQL, you’re charged one point for every nested property or data field that you’re capturing. On the other hand, running a mutation costs 10 points, meaning each of these different products is going to cost 10 rate limit points.

You can see how if I’m going to be making a number of requests, I would run through 958 rate limit points pretty quickly. 

Recall that we’ve requested our data. The next thing that we’re going to want to do is action it. We want to take every single one of the product Ids that are returned, and run them with a mutation on them. I need to be able to fetch the product Id from the request. 

How are we going to do that? 

You might also like: An Introduction to Rate Limits

Step 1: Indexing into your array by defining a new variable 

We see that our request outputs an array of different JSON objects, so we could index into that array. We’re going to do so by defining a new variable.

Implement API rate limit: gif taken from Youtube video

I’m going to call it const edges = data.products.edges. I could even call this const productedges = data.products.Edges. That submits a request to look at all that data, which comprises an entire object, including products, and then edges. 

Step 2: Building out our for loop

Now, what we want to do is loop through each one of these edges so that we can access each product independently. We do that by writing a for loop. 

for (let edge = 0; edge < productEdges.length; edge++) 

This for loop allows us to index into each of the individual arrays that we get back. But there’s some particular data that we need. So, under our for loop we’re going to write the following code: 

const productId = productEdges[edge].node.id 

This is saying that I want the productId which is actually equal to (=) our productEdges. Then I need to index into the node key, and then the id key. 

The next thing we’re requesting is the variantId, written in the following code:

const variantId = productEdges[edge].node.variants.edges[0].node.id 

This is saying that similarly, we're going to request productEdges, nest again into the node, but this time into variants and edges as well. Keep in mind that edges is still an array.

Ideally, this request would be paginated over a couple of different options, but remember I’m cheating and I know that we only have a single variant, so I'm going to go and grab the first one, [0]. Finally, we’re going to go into the node to get the id

The request for variantWeight looks similar to the request for variantId. It’ll look something like this:

const variantWeight = productEdges[edge].node.variants.edges[0].node.weight 

Implement API rate limit: screenshot take from timestamped Youtube video

Now we’ve written in all of our specifications. This allows us to access all the different data points that I know from my objects I wouldn't need to actually implement the mutation. Next, we’re going to look at how to update the price of the new product. 

How to update your products prices

There are a few steps involved in responsibly updating the prices of your products, which are outlined below. 

First we want to update the price of the product. Updating the price of the product looks like this:

Implement API rate limit: giff made from time stamped Youtube video

This is basically saying that updatedPrice is equal to (=) the weight (variantWeight) of the product multiplied by (*) how much it weighs (goldPricePerGram).

We’re actually going to fix it to two decimal points (toFixed(2)), representing cents, because Shopify expects a double in terms of the data type in the request input. 

Linking the mutation to your for loop

Next we’re going to have to pull up the mutation to update the price of a product. For simplicity's sake I’ve copied that, so I'm going to insert it into our function and our for loop. 

Implement API rate limit: gif taken from timestamped youtube video

Now I’ve created a variable called productUpdateMutation, and I know that within Shopify, this mutation is called productUpdate. It expects an input field of type ProductInput. It will also return to us the id of the product that's been updated, because that's what we're requesting.

Fantastic. There we have the mutation. 

Creating the productInput object 

The next thing we need to do is create the input. We can actually take a look in our productInput documentation for more information on what this looks like. It outlines all the different input fields that we can get access to, including the id, metafields or publications. 

For this example, all we’re interested in is the variants, [ProductVariantIntput ! ] because that's where the price lives.

Implement API rate limit: Gif made of user navigating the shopify API documentation

The documentation tells us that we’re going to have to provide an id, a variants key, and then the properties associated with the product variant. That's going to be another id, this time the price key.

Let’s take a shot at implementing this.

Writing your productInput

Implement API rate limit: giff taken from timestamped Youtube video

We’ll create an input, const productInput =. Then we'll insert an id: productID, and then we're also going to have variants. Now, variant is actually an array because there are multiple and each of them are a map of their own.

So we’ll put id: variantId, in that map, and also price: updatedPrice for this particular edge or product, because we're looping through them all, as outlined above.

Every time we're calculating our updatedPrice here, it's for one particular product and we have that captured within our productInput.

Now we have everything we need to be able to execute this mutation, which is fantastic! 

You might also like: How to Build a Shopify App: The Complete Guide.

The final step: calling your mutation

The last thing we want to do is to go ahead and call this mutation. Doing so looks something like this:

Implement API rate limit: giff taken from time stamped Youtube video

To call it, we’re going to say constant mutationData = I'm going to synchronously wait for the response of the GraphQL client (await graphQLClient.).

Then we’re going to make a standard request, request(productUpdateMutation, productInput).

We also want to be able to catch and log any errors that might happen, catch((error)=> console.log(error))

Before running that, you might also want to log the stringified version of the mutationData. The extra parameters help with formatting and keeping things clean by adding some white space around the new lines. The code for that looks like this:

console.log(JSON.stringify(mutationData, undefined, 2)) 

We’ve followed the productInput format laid out in the documentation, however it all needs to be nested within a map, where we specify that it is indeed an input. Otherwise there is confusion around that component. So we’ll just add that in like below:

Implement API rate limit: giff taken from timestamped Youtube video

Once you’ve done that, save and hit run. You should expect to see the for loop going through each one of those products and making an update to the price. This is what your terminal should look like:

 Implement API rate limit: Screenshot taken from video of successfully looping code

Success! It's looping through each of our products, retrieving the values, and then it's making that update. We’re also seeing no errors and getting our productId back, so that’s fantastic.

Where do we go from here?

Now what are we missing? So far, we don't know how much rate limit we still have available when making these requests. We have no idea when we might run into an error. So stay tuned for the next post in this series, where you’ll learn how to capture information, optimize, and responsibly use your app's rate limit. 

Build for the world’s entrepreneurs

Want to check out the other videos in this series before they are posted on the blog? Subscribe to the ShopifyDevs YouTube channel. Get development inspiration, useful tips, and practical takeaways.


Special thanks to our friends at the Shopify Partner Blog for their insights on this topic.
Data Snacks Video — Cost Per Click (CPC)

Data Snacks Video — Cost Per Click (CPC)

Sustainable Marketing For A Greener Future

Sustainable Marketing For A Greener Future

You May Also Like
Share to...