Error Medic

How to Fix Shopify Rate Limit (HTTP 429 Too Many Requests) and Related API Errors

Resolve Shopify API rate limit (429), timeout (503), and webhook errors. Learn to implement leaky bucket algorithms, handle GraphQL costs, and fix 401/403s.

Last updated:
Last verified:
1,054 words
Key Takeaways
  • Shopify API rate limits (HTTP 429) occur when exceeding the leaky bucket capacity (REST: 40 calls/app/store, GraphQL: 1000 points).
  • HTTP 5xx errors (500, 502, 503) often accompany high concurrency or indicate temporary Shopify platform degradation, requiring exponential backoff.
  • Webhook delivery failures and timeouts are almost always caused by slow app response times (>3s) or synchronous payload processing.
  • Implement robust retry logic utilizing the 'Retry-After' header and transition to the GraphQL API or Bulk Operations for data-heavy tasks.
Fix Approaches Compared
MethodWhen to UseTime to ImplementRisk Level
Exponential BackoffHandling HTTP 429 and 5xx errors across REST and GraphQLMediumLow
GraphQL MigrationHigh-volume data fetching or deeply nested mutationsHighMedium
Webhook Background QueueingFixing webhook timeout and delivery failuresMediumLow
Bulk Operations APIExporting or importing massive datasets (>10k records)HighLow

Understanding Shopify API Errors

When scaling a Shopify application, developers inevitably encounter a barrage of HTTP errors. The most infamous is the HTTP 429 Too Many Requests, indicating that you have hit Shopify's rate limit. However, a misconfigured integration will also trigger HTTP 401 (Unauthorized), 403 (Forbidden), and a suite of 5xx errors (500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable).

The Leaky Bucket Algorithm

Shopify does not use strict per-minute rate limits. Instead, it employs a "leaky bucket" algorithm.

For the REST API (Standard Tier):

  • Bucket Size: 40 requests
  • Leak Rate: 2 requests per second

If you burst 40 requests instantly, the bucket fills. Any subsequent request before the bucket "leaks" will result in an HTTP 429 Too Many Requests error. The response header X-Shopify-Shop-Api-Call-Limit will read 40/40.

For the GraphQL API (Standard Tier):

  • Bucket Size: 1000 points
  • Leak Rate: 50 points per second

GraphQL limits are based on query complexity. A simple query might cost 1 point, while fetching a deeply nested product catalog could cost 500 points.

Diagnosing 401, 403, and Webhook Failures

  • HTTP 401 Unauthorized: The provided X-Shopify-Access-Token is invalid, expired, or the merchant uninstalled your app.
  • HTTP 403 Forbidden: The app's access token is valid, but it lacks the required OAuth scopes (e.g., trying to read orders with only read_products scope).
  • Webhook Timeouts: Shopify expects a 200 OK response within 3 seconds of sending a webhook. If your app attempts to process the payload synchronously (e.g., writing to a database, calling a third-party API) and takes >3 seconds, Shopify considers it a failure. After repeated failures, Shopify drops the webhook entirely.

Step 1: Diagnose the Root Cause

Before writing code, analyze your traffic patterns. Are you hitting limits during inventory syncs? Check the response headers. If you receive a 429, look for the Retry-After header, which tells you exactly how many seconds to wait before attempting the request again.

For 5xx errors (500, 502, 503, 504), these are server-side timeouts from Shopify. They often happen during major flash sales or platform degradation. You must treat these similarly to a 429: wait and retry.

Step 2: Implement Exponential Backoff and Queues

To fix rate limits and 5xx errors, implement an HTTP interceptor with exponential backoff and jitter. If you receive a 429, parse the Retry-After header. If no header is present (common with 5xx errors), wait 1 second, then 2, then 4, up to a maximum threshold.

To fix webhook timeouts, offload processing. Your webhook endpoint should immediately accept the payload, push it to an asynchronous queue (like Redis/BullMQ, AWS SQS, or RabbitMQ), and return 200 OK. Worker processes can then handle the data at their own pace without failing Shopify's 3-second timeout.

Frequently Asked Questions

javascript
import axios from 'axios';

// Create a dedicated Axios instance for Shopify
const shopifyClient = axios.create({
  baseURL: 'https://{shop}.myshopify.com/admin/api/2024-01',
  headers: { 'X-Shopify-Access-Token': process.env.SHOPIFY_TOKEN }
});

// Implement response interceptor for 429 Rate Limits and 5xx errors
shopifyClient.interceptors.response.use(
  (response) => response,
  async (error) => {
    const config = error.config;
    
    // Prevent infinite loops
    if (!config || !config.retryCount) config.retryCount = 0;
    if (config.retryCount >= 5) return Promise.reject(error);

    const status = error.response ? error.response.status : null;

    // Handle 429 Too Many Requests or 5xx Server Errors
    if (status === 429 || (status >= 500 && status < 600)) {
      config.retryCount += 1;
      
      let waitTime = 2000; // Default 2 seconds
      
      // Respect Shopify's Retry-After header if present
      if (status === 429 && error.response.headers['retry-after']) {
        waitTime = parseInt(error.response.headers['retry-after'], 10) * 1000;
      } else if (status >= 500) {
        // Exponential backoff with jitter for 5xx errors
        waitTime = Math.pow(2, config.retryCount) * 1000 + Math.random() * 1000;
      }

      console.warn(`[Shopify API] HTTP ${status}. Retrying attempt ${config.retryCount} after ${waitTime}ms...`);
      
      await new Promise(resolve => setTimeout(resolve, waitTime));
      return shopifyClient.request(config);
    }

    return Promise.reject(error);
  }
);
E

Error Medic Editorial

Specialized in API integrations, scalable architectures, and resolving complex e-commerce platform bottlenecks for enterprise merchants.

Sources

Related Guides