Every call a custom Shopify app makes to Shopify's APIs - fetching orders, updating inventory, syncing customer data, triggering fulfilment - counts against a rate limit. Exceed that limit and Shopify throttles or blocks further requests until the limit resets.
For low-volume stores processing a handful of orders per hour, this is rarely a problem. For merchants processing hundreds of orders during a peak period, or running nightly syncs that touch thousands of products, API limits become a critical engineering consideration.
This article explains how Shopify's rate limits work, what happens when you hit them, and how well-architected custom apps handle them reliably.
How Shopify's API rate limiting works
The REST Admin API - leaky bucket model
Shopify's REST Admin API uses a leaky bucket model. Your app has a bucket with a capacity of 40 requests. The bucket drains at a rate of 2 requests per second. If your app makes requests faster than the bucket drains, it fills up. When the bucket is full, Shopify returns a 429 Too Many Requests error and your app must wait before retrying.
The practical implication: a well-behaved app can sustain approximately 2 requests per second indefinitely. A burst of up to 40 requests can happen instantly, after which the app must slow to the sustainable rate.
The GraphQL Admin API - calculated query cost
The GraphQL Admin API uses a cost-based system. Each query has a calculated cost based on the fields requested and the data complexity. Your app has a cost budget of 1,000 points that refills at 50 points per second.
Simple queries cost relatively little. Queries that request many fields across many objects - fetching 250 orders with all their line items, customer data, and fulfilment details in a single call - can cost several hundred points. Structure your queries to request only what you need.
The Storefront API
The Storefront API has separate rate limits from the Admin API. It is designed for higher-volume, customer-facing operations and is generally more permissive. However, it exposes a narrower set of data and is not appropriate for backend operations that need access to order management or inventory.
Webhooks
Webhooks are Shopify's push mechanism - Shopify sends a notification to your app when something happens. They do not count against your API rate limit for the receiving side, but your app still needs to respond within 5 seconds or Shopify marks the delivery as failed and retries.
Webhook delivery is not guaranteed. Shopify retries failed deliveries up to 19 times over 48 hours, but if your app is down or unresponsive for longer than that, those events are lost. Apps that depend on webhooks for critical data flows need a reconciliation mechanism.
When API limits become a problem
High-volume order processing
A merchant processing 500 orders per hour across multiple fulfilment partners, each requiring API calls to read order data, check inventory, and trigger fulfilment, can easily exceed the sustainable rate during peak periods. Without rate limit handling, the integration fails exactly when it is most needed.
Large-scale data syncs
Nightly syncs that push product data from a PIM to Shopify - updating prices, inventory, descriptions, and variants across a catalogue of 10,000 products - require careful API call planning. At 2 requests per second for the REST API, a naive implementation that makes one API call per product update takes over 80 minutes. A well-designed implementation using bulk operations reduces this to minutes.
Multi-store architectures
Merchants operating multiple Shopify stores with a shared backend need to manage API limits per store. Each store has its own independent rate limit bucket. An app managing 5 stores simultaneously needs to manage 5 separate rate limit states.
Real-time integrations
Integrations that need to respond in real time - checking stock before confirming an order, fetching a customer's account balance during checkout, updating inventory the moment a sale completes - have no tolerance for rate limit delays. These require architectures that cache data locally and update asynchronously, rather than making synchronous API calls at the point of need.
How well-architected apps handle rate limits
Exponential backoff and retry logic
Every API call in a properly built app is wrapped in retry logic. When a 429 response is received, the app waits - starting with a short delay and doubling it on each subsequent retry up to a maximum. This is exponential backoff. Without it, an app that hits a rate limit either fails completely or hammers the API with immediate retries, making the situation worse.
Request queuing
Rather than making API calls immediately when an event occurs, a well-designed app places requests in a queue and processes them at a rate that respects the API limit. The queue absorbs traffic spikes and ensures smooth, reliable operation even during peak periods.
Bulk operations for large data sets
Shopify's Bulk Operations API allows apps to request large data sets asynchronously. Instead of fetching 10,000 products in batches of 250 with many API calls, a bulk operation fetches all 10,000 in a single request that Shopify processes in the background and delivers as a file. This is dramatically more efficient for large-scale data operations.
Caching frequently-accessed data
Data that is read frequently but changes infrequently - product catalogues, customer segments, price lists - should be cached locally rather than fetched from the API on every request. A cache with a sensible TTL (time to live) reduces API call volume significantly and makes the integration more resilient to rate limit events.
Webhook reconciliation
Apps that depend on webhooks for critical data flows should implement a reconciliation process - a periodic batch job that queries the API directly to identify any events that webhooks may have missed. This ensures data consistency even when webhook delivery fails.
What this means when evaluating a custom app proposal
When you receive a proposal for a custom Shopify app, the quality of the rate limit handling is one of the clearest signals of the developer's experience level. Questions to ask:
- How do you handle 429 rate limit responses? What is your retry strategy?
- For large data syncs, do you use the Bulk Operations API?
- How do you handle webhook delivery failures? Is there a reconciliation process?
- Have you load-tested the integration against the volumes we expect during peak periods?
- What happens to orders during a period when the API is unavailable?
Developers who have not built apps at scale often have good answers for normal operating conditions and poor answers for failure modes. The failure modes are what matter most in production.
An app that works in testing and fails under peak load is not a delivered app. Rate limit handling is not optional engineering - it is the difference between a custom integration that is a business asset and one that is an operational liability.
