Load test Shopify app integrations while respecting API rate limits. Plan capacity for high-traffic events like Black Friday / Cyber Monday (BFCM).
brew install k6)Your app's throughput is bounded by Shopify's rate limits, not your infrastructure:
| Plan | GraphQL Points | Restore Rate | Max Sustained QPS | Burst Capacity |
|---|---|---|---|---|
| Standard | 1,000 | 50/sec | ~10 queries/sec | 1,000 points burst |
| Shopify Plus | 2,000 | 100/sec | ~20 queries/sec | 2,000 points burst |
A typical product query costs 10-50 points. At 50 points/query, Standard supports ~1 query/second sustained.
k6 script with Shopify-specific custom metrics (throttle tracking, query cost trends, error rates) and automatic request pacing.
See k6 Load Test Script for the complete test script.
# Against a test store — NEVER production
k6 run \
--env SHOPIFY_STORE=dev-store.myshopify.com \
--env SHOPIFY_ACCESS_TOKEN=shpat_test_token \
shopify-load-test.js
# Output results to InfluxDB for Grafana dashboards
k6 run --out influxdb=http://localhost:8086/k6 shopify-load-test.js
Pre-BFCM preparation including cache pre-warming, Storefront API offloading, bulk inventory sync, and Kubernetes HPA configuration for webhook processing.
See BFCM Preparation for application-level and infrastructure scaling patterns.
| Issue | Cause | Solution |
|---|---|---|
| k6 shows high error rate | Hitting rate limits | Reduce VUs, increase sleep between requests |
| All requests THROTTLED | Exceeding 50 points/sec | Space queries further apart |
| Webhooks backing up | Slow processing | Respond 200 immediately, queue processing |
| Cache stampede on sale start | All caches expire at once | Stagger cache TTLs, pre-warm |
# How many queries can you sustain?
# Standard plan: 50 points/sec restore
# Your query costs: check with debug header
curl -sf "https://$STORE/admin/api/${SHOPIFY_API_VERSION:-2025-04}/graphql.json" \
-H "X-Shopify-Access-Token: $TOKEN" \
-H "Content-Type: application/json" \
-H "Shopify-GraphQL-Cost-Debug: 1" \
-d '{"query": "{ products(first: 10) { edges { node { id title } } } }"}' \
| jq '"Query cost: \(.extensions.cost.actualQueryCost) points. Max sustained: \(50 / .extensions.cost.actualQueryCost) queries/sec"'