Your App Just Got Throttled. Now What?
Every Shopify developer has experienced it. Your app is humming along, syncing products, processing orders, updating inventory, and then it stops. A 429 status code appears in your logs. "Too Many Requests." Your app has hit Shopify's API rate limit, and until you handle it properly, your users are stuck waiting. Rate limiting is one of the most critical concepts for any developer building on the Shopify platform, yet it remains one of the least well-understood. The limits vary dramatically between plans, between API types, and between operation patterns — and getting the details wrong can mean the difference between an app that scales gracefully and one that breaks under load.
This guide breaks down Shopify's rate limiting system comprehensively. We cover every plan tier, both REST and GraphQL throttling mechanisms, the special rules for Storefront API, the techniques that experienced developers use to maximize throughput while staying within limits, and the best practices that will keep your app running smoothly as your merchants grow. Whether you are building your first Shopify app or optimizing an existing one that has outgrown its current architecture, understanding rate limits at a deep level is essential for building reliable, scalable Shopify integrations.
Rate Limits by Plan: The Numbers That Matter
Shopify's rate limits are not uniform across all merchants. They vary significantly based on the merchant's subscription plan, and understanding these differences is crucial for building apps that work well for all your users. For the GraphQL Admin API, which is the primary API for most Shopify app development, the limits break down as follows. Merchants on the Basic plan receive 50 points per second of query cost capacity. Standard plan merchants get 100 points per second. Advanced plan merchants receive 200 points per second. And Shopify Plus merchants — the enterprise tier — get 500 points per second, ten times the allocation of a Basic plan merchant.
These differences have profound implications for app design. An inventory sync that runs comfortably within rate limits for a Plus merchant might constantly hit throttling for a Basic plan merchant. A product catalog import that completes in minutes on an Advanced plan could take hours on a Basic plan if rate limits are not carefully managed. Your app needs to adapt its behavior based on the merchant's plan, either by detecting the available capacity dynamically or by building conservative defaults that work for the lowest tier.
REST API: The Leaky Bucket Algorithm
Shopify's REST Admin API uses a leaky bucket algorithm for rate limiting. The concept is straightforward: imagine a bucket that can hold a certain number of requests. Each API call you make adds a drop to the bucket. The bucket "leaks" at a constant rate, draining requests over time. As long as you add drops slower than the bucket leaks, your bucket never overflows and you never get throttled. But if you send requests faster than the bucket can drain, it eventually fills up and new requests are rejected with a 429 status code until space becomes available.
For standard Shopify plans, the bucket holds 40 requests and leaks at a rate of 2 requests per second. This means you can burst up to 40 rapid requests, but your sustained throughput is limited to 2 requests per second. For Shopify Plus merchants, the bucket is significantly larger — holding 400 requests with a leak rate of 20 requests per second. This ten-fold increase in both bucket size and leak rate is one of the most compelling technical reasons for merchants to upgrade to Plus, especially those with large catalogs or high transaction volumes that require heavy API usage.
Every REST API response includes headers that tell you the current state of your bucket. The X-Shopify-Shop-Api-Call-Limit header shows how many requests are currently in your bucket versus the bucket's maximum capacity — for example, "32/40" means you have used 32 of your 40 available slots. Smart apps monitor these headers on every response and adjust their request rate dynamically, slowing down as the bucket fills and speeding up as it drains.
GraphQL Admin API: Cost-Based Throttling
The GraphQL Admin API uses a fundamentally different rate limiting approach: cost-based throttling. Instead of counting individual requests, Shopify assigns a cost to each query based on the complexity of the data being requested. Simple queries that fetch a single object might cost just 1-2 points. Complex queries that request lists of objects with nested connections and multiple fields can cost hundreds of points. The actual cost of a query is returned in every response under the extensions.cost field, which includes both the requested cost, the actual cost after execution, and the throttle status showing your current bucket state.
This cost-based approach has important implications for how you structure your queries. A query that fetches 100 products with their variants, images, and metafields will cost significantly more than a query that fetches 10 products with just their titles and prices. Smart developers optimize their queries to request only the fields they actually need, use pagination to control the size of list queries, and batch related queries together to minimize overhead. The maximum single query cost is 1,000 points, which means that extremely complex queries may need to be broken into smaller pieces regardless of your available capacity.
The restore rate — how quickly your capacity regenerates — follows the same plan-based tiers as the total capacity. A Basic plan merchant's bucket refills at 50 points per second, while a Plus merchant's bucket refills at 500 points per second. When your app gets throttled, the response includes a Retry-After header indicating how many seconds to wait before retrying. Implementing proper retry logic with exponential backoff and jitter is essential for handling throttling gracefully without degrading the user experience.
Storefront API: A Different Beast Entirely
The Storefront API operates under a completely different rate limiting model that catches many developers by surprise. Unlike the Admin API, the Storefront API has no request-count-based rate limit. You will not receive a 429 error for making too many requests per second. Instead, the Storefront API is protected by Shopify's global infrastructure throttling, which focuses on overall bandwidth and server load rather than per-request counting. This makes sense given the Storefront API's purpose — it serves customer-facing traffic where spiky access patterns during sales events and promotions are normal and expected.
However, this does not mean the Storefront API has unlimited capacity. Extremely aggressive query patterns, very large payloads, or queries that trigger expensive server-side computations can still be throttled at the infrastructure level. The Storefront API also has complexity limits on GraphQL queries similar to the Admin API. The practical takeaway is that while you do not need to implement the same careful request-pacing logic for the Storefront API that you need for the Admin API, you still need to write efficient queries and handle the possibility of throttling in your error handling code.
Handling 429 Errors: The Right Way
When your app receives a 429 status code, how it responds determines whether your users experience a brief hiccup or a catastrophic failure. The single most important rule is to respect the Retry-After header. This header, included in every 429 response, tells you exactly how many seconds to wait before making another request. Ignoring this header and immediately retrying will only make the situation worse, as Shopify may extend your throttling period in response to aggressive retry behavior.
The recommended approach combines the Retry-After header with exponential backoff and jitter. Exponential backoff means increasing your wait time with each consecutive failed attempt — for example, waiting 1 second after the first 429, then 2 seconds, then 4 seconds, and so on. Jitter adds a random component to the wait time to prevent the "thundering herd" problem, where multiple instances of your app all retry at the exact same moment and trigger another round of throttling. A good jitter implementation adds or subtracts a random percentage of the backoff time, spreading retries across a wider time window.
Beyond reactive 429 handling, proactive rate limit management is the hallmark of well-engineered Shopify apps. Monitor your API response headers continuously, track your consumption rate against your available capacity, and throttle your own requests before Shopify does it for you. This approach prevents 429 errors from occurring in the first place, resulting in smoother performance and more predictable behavior for your users.
Bulk Operations API: Bypassing Rate Limits for Large Datasets
For operations that involve large datasets — full catalog syncs, comprehensive order exports, bulk inventory updates — Shopify offers the Bulk Operations API, which effectively bypasses the standard rate limiting system. Instead of making thousands of individual API calls to fetch or update records one by one, you submit a single bulk operation query that describes what data you need. Shopify processes the operation asynchronously on their servers and provides a JSONL file URL when the results are ready for download.
As of early 2026, the Bulk Operations API supports up to 5 concurrent operations, which was increased from the previous limit of 1 concurrent operation. This is a significant improvement for apps that need to perform multiple types of bulk operations simultaneously — for example, syncing products and orders at the same time. The tradeoff is that bulk operations are not instant; depending on the dataset size, they can take anywhere from seconds to hours to complete. But for large-scale data operations, the throughput improvement is enormous compared to paginating through the standard API within rate limits.
Smart apps use the Bulk Operations API as their primary data-fetching mechanism for initial syncs and periodic full refreshes, while using the standard API for real-time incremental updates triggered by webhooks. This hybrid approach maximizes throughput while maintaining real-time responsiveness.
Webhooks vs. Polling: Reducing API Consumption by 40-60%
One of the most effective strategies for staying within rate limits is minimizing the number of API calls your app makes in the first place. Webhooks are the primary tool for achieving this. Instead of polling Shopify's API at regular intervals to check for new orders, product changes, or inventory updates, you register webhooks that tell Shopify to push notifications to your app when events occur. This eliminates the vast majority of "nothing has changed" API calls that polling-based architectures generate.
In practice, switching from a polling-based architecture to a webhook-driven architecture reduces API consumption by 40-60%, depending on the specific use case and the frequency of changes. A product sync that previously required polling every 5 minutes — making 288 API calls per day just for change detection — can be replaced by webhooks that only fire when actual changes occur, which might be a handful of times per day for most merchants.
It is worth noting that Shopify deprecated the REST-based webhook subscription format in October 2024, and all new webhook subscriptions should be created using the GraphQL API. The webhook payload format and delivery mechanism remain the same, but the management API for creating, updating, and listing webhook subscriptions is now GraphQL-only. Make sure your app has been updated to use the GraphQL subscription management endpoints.
Best Practices for Production Shopify Apps
Building production-ready Shopify apps that handle rate limits gracefully requires a combination of architectural decisions and implementation details. First, always use GraphQL over REST when possible. The cost-based throttling model gives you more predictable behavior and better throughput for complex operations. Second, implement request queuing with adaptive rate control that monitors response headers and adjusts throughput in real time. Third, use webhooks as your primary change detection mechanism and fall back to polling only when webhooks are unavailable or unreliable.
Fourth, leverage the Bulk Operations API for any operation that touches more than a few hundred records. Fifth, implement proper circuit breaker patterns that gracefully degrade functionality when rate limits are consistently hit rather than hammering the API with retries. Sixth, cache API responses aggressively — product data, collection data, and shop configuration rarely change and can be cached for minutes or even hours. Seventh, design your data model to minimize the need for API calls by storing relevant data locally and syncing incrementally via webhooks.
How ITX E-commerce Solutions Can Help
At ITX E-commerce Solutions, we build Shopify integrations and custom apps that are engineered from the ground up to handle rate limits intelligently. Whether you need a custom app that syncs inventory across multiple sales channels, a migration tool that moves your catalog from another platform to Shopify, or an integration with your ERP or warehouse management system, our team designs architectures that maximize API throughput while staying comfortably within Shopify's rate limits. We implement proper queuing, adaptive throttling, webhook-driven updates, and bulk operations to ensure your integrations are fast, reliable, and scalable across every Shopify plan tier. Contact us to discuss your Shopify integration requirements.