
Introduction
Shopify load testing is essential for any brand preparing for product launches, flash sales, holiday traffic, or major marketing campaigns. While Shopify handles much of the platform infrastructure for you, your storefront theme, third-party apps, custom scripts, Storefront API usage, and checkout flow can still introduce performance bottlenecks that hurt conversion rates.
A slow collection page, delayed cart updates, or sluggish checkout redirect can quickly turn high-intent shoppers into abandoned sessions. That’s why load testing, performance testing, and stress testing your Shopify store matters. By simulating realistic user behavior under load, you can identify whether your storefront can handle peak traffic before real customers arrive.
In this guide, you’ll learn how to load test a Shopify store with LoadForge using Locust-based Python scripts. We’ll cover storefront browsing, cart interactions, Storefront API requests, authenticated customer flows, and more advanced scenarios that reflect how real shoppers use Shopify. Along the way, we’ll also show how LoadForge’s distributed testing, real-time reporting, cloud-based infrastructure, and global test locations make it easier to validate Shopify performance at scale.
Prerequisites
Before you begin load testing Shopify, make sure you have the following:
- A Shopify store or development store
- Permission to test the storefront and any APIs you plan to use
- A list of important URLs and user journeys, such as:
- Homepage
- Collection pages
- Product detail pages
- Cart endpoints
- Search pages
- Customer login pages
- Storefront API endpoints
- Test products with valid variants in stock
- Optional customer test accounts for authenticated flows
- Optional Storefront API access token if testing GraphQL Storefront API
- LoadForge account for running distributed load tests in the cloud
You should also gather a few Shopify-specific details in advance:
- Your store domain, such as
https://your-store.myshopify.comor your custom domain - Product handles, collection handles, and variant IDs
- Whether you use Shopify’s Online Store pages, Storefront API, or a headless frontend
- Whether your theme or apps add extra requests to product pages, cart, or search
If you’re testing checkout behavior, be aware that Shopify checkout is hosted and partially controlled by Shopify, especially on non-Plus plans. In most cases, you should focus on testing the pre-checkout user journey and the transition into checkout rather than attempting to fully automate payment submission.
Understanding Shopify Under Load
Shopify is a managed e-commerce platform, but that doesn’t mean every storefront performs equally well under traffic spikes. The base platform is highly scalable, yet several layers can affect performance under concurrent load.
Common Shopify bottlenecks
When load testing Shopify, these are the most common areas to watch:
Theme rendering and frontend assets
A storefront may load slowly because of:
- Heavy JavaScript bundles
- Large images
- Third-party tracking scripts
- App-injected widgets
- Excessive client-side rendering
Under load, the HTML response may still be fast, but the real customer experience can degrade because of frontend complexity.
Product and collection pages
Collection pages often become hotspots during peak shopping events because many users browse them at once. Performance issues can come from:
- Too many products loaded per page
- Complex filtering or faceting logic
- App-generated badges or pricing rules
- Slow recommendations and personalization widgets
Cart operations
Cart actions are critical. Shopify cart endpoints like /cart/add.js, /cart.js, and /cart/change.js are heavily used during shopping sessions. Problems here can directly impact conversion.
Search and predictive search
Search traffic often spikes during promotions or when users are hunting for featured products. Search endpoints and predictive search can become bottlenecks if themes or third-party integrations perform extra processing.
Storefront API usage
Headless Shopify implementations often rely on the GraphQL Storefront API. In these cases, your performance testing should include:
- Product queries
- Collection queries
- Cart creation or updates
- Customer authentication flows
- Search queries
GraphQL performance can vary significantly depending on query complexity and response size.
Third-party apps and integrations
Apps for reviews, upsells, subscriptions, personalization, analytics, and chat can add latency. Even if Shopify itself is stable, app-related requests may fail or slow down the page under load.
This is why realistic Shopify load testing should include both page requests and AJAX/API calls that reflect actual shopper behavior.
Writing Your First Load Test
Let’s start with a basic Shopify storefront load test. This script simulates anonymous shoppers who browse the homepage, visit a collection, open a product page, and fetch the cart.
This is a good first performance testing scenario because it represents the top of the funnel and helps you understand how your store handles general browsing traffic.
from locust import HttpUser, task, between
import random
class ShopifyBrowserUser(HttpUser):
wait_time = between(2, 5)
product_handles = [
"classic-logo-tee",
"premium-hoodie",
"summer-cap"
]
collection_handles = [
"new-arrivals",
"best-sellers",
"sale"
]
@task(3)
def homepage(self):
self.client.get("/", name="Homepage")
@task(2)
def collection_page(self):
collection = random.choice(self.collection_handles)
self.client.get(f"/collections/{collection}", name="Collection Page")
@task(2)
def product_page(self):
product = random.choice(self.product_handles)
self.client.get(f"/products/{product}", name="Product Page")
@task(1)
def cart_view(self):
self.client.get("/cart.js", name="View Cart JSON")What this test does
This script simulates a common Shopify browsing session:
- Loads the homepage
- Visits collection pages
- Opens product detail pages
- Checks the current cart state via
/cart.js
Why this matters
This basic load test helps you answer questions like:
- Does the homepage stay responsive under concurrent users?
- Are collection pages slower than product pages?
- Does cart state retrieval remain fast during traffic spikes?
- Are certain pages generating more errors than expected?
What to customize
For a real Shopify store, replace:
product_handleswith actual product handlescollection_handleswith real collection paths- The base URL in LoadForge with your store domain
In LoadForge, you can run this test from multiple regions to see how global shoppers experience your storefront. This is especially useful for international Shopify brands with customers across North America, Europe, and Asia-Pacific.
Advanced Load Testing Scenarios
Once you’ve validated basic browsing performance, the next step is to model realistic e-commerce behavior. The following scenarios focus on actions that matter most for Shopify conversion rates.
Advanced Scenario 1: Add to Cart and Update Quantity
This test simulates shoppers browsing products, adding variants to cart, viewing the cart, and updating item quantities. These endpoints are central to Shopify storefront performance testing.
from locust import HttpUser, task, between
import random
class ShopifyCartUser(HttpUser):
wait_time = between(1, 4)
variants = [
{
"product_handle": "classic-logo-tee",
"variant_id": 44681234567890,
"quantity": 1
},
{
"product_handle": "premium-hoodie",
"variant_id": 44681234567891,
"quantity": 1
},
{
"product_handle": "summer-cap",
"variant_id": 44681234567892,
"quantity": 1
}
]
def on_start(self):
self.client.get("/", name="Homepage")
@task(3)
def browse_product(self):
item = random.choice(self.variants)
self.client.get(f"/products/{item['product_handle']}", name="Product Page")
@task(2)
def add_to_cart(self):
item = random.choice(self.variants)
payload = {
"items": [
{
"id": item["variant_id"],
"quantity": item["quantity"]
}
]
}
self.client.post(
"/cart/add.js",
json=payload,
headers={"Content-Type": "application/json"},
name="Add to Cart"
)
@task(1)
def update_cart_quantity(self):
cart_response = self.client.get("/cart.js", name="View Cart Before Update")
if cart_response.status_code == 200:
cart_data = cart_response.json()
if cart_data.get("items"):
line_item = cart_data["items"][0]
payload = {
"id": line_item["variant_id"],
"quantity": random.randint(1, 3)
}
self.client.post(
"/cart/change.js",
json=payload,
headers={"Content-Type": "application/json"},
name="Change Cart Quantity"
)
@task(1)
def view_cart(self):
self.client.get("/cart", name="Cart Page")Why this scenario is important
For Shopify stores, cart actions are often more business-critical than simple page views. A store that handles browsing well but slows down during add-to-cart operations will still lose revenue.
This test helps uncover:
- Latency in AJAX cart endpoints
- Session or cookie-related issues
- Errors caused by app-based cart customizations
- Performance degradation when many users modify carts at once
Shopify-specific note
Shopify cart endpoints typically rely on session cookies. Locust’s HttpUser client maintains cookies per simulated user, which makes it a good fit for this kind of realistic cart load testing.
Advanced Scenario 2: Customer Login and Account Activity
Many Shopify stores support returning customer logins for order history, saved addresses, subscriptions, or B2B workflows. This scenario tests login and authenticated account pages.
from locust import HttpUser, task, between
import random
class ShopifyCustomerUser(HttpUser):
wait_time = between(2, 5)
credentials = [
{"email": "testuser1@example.com", "password": "Password123!"},
{"email": "testuser2@example.com", "password": "Password123!"},
{"email": "testuser3@example.com", "password": "Password123!"}
]
def on_start(self):
self.login()
def login(self):
user = random.choice(self.credentials)
# Load login page first to establish session/cookies
self.client.get("/account/login", name="Customer Login Page")
payload = {
"customer[email]": user["email"],
"customer[password]": user["password"],
"form_type": "customer_login",
"utf8": "✓"
}
response = self.client.post(
"/account/login",
data=payload,
headers={"Content-Type": "application/x-www-form-urlencoded"},
allow_redirects=True,
name="Customer Login Submit"
)
if response.status_code not in [200, 302]:
response.failure("Login failed")
@task(3)
def account_overview(self):
self.client.get("/account", name="Customer Account")
@task(2)
def order_history(self):
self.client.get("/account", name="Order History")
@task(1)
def logout_and_relogin(self):
self.client.get("/account/logout", name="Customer Logout")
self.login()What this scenario tests
This script simulates authenticated customer traffic and helps you validate:
- Login form responsiveness
- Session handling under load
- Performance of account pages
- Stability of customer-related theme customizations and apps
Where this is especially useful
This type of Shopify performance testing is valuable for:
- Subscription stores
- Wholesale or B2B storefronts
- Brands with loyalty programs
- Stores with many repeat customers
If your store relies heavily on authenticated experiences, you should include this scenario in every major load testing cycle.
Advanced Scenario 3: Shopify Storefront API GraphQL Testing
Many modern Shopify builds use the Storefront API, especially in headless commerce setups. This scenario tests realistic GraphQL queries for products and collections.
from locust import HttpUser, task, between
import random
class ShopifyStorefrontAPIUser(HttpUser):
wait_time = between(1, 3)
headers = {
"Content-Type": "application/json",
"X-Shopify-Storefront-Access-Token": "your_storefront_access_token"
}
product_handles = [
"classic-logo-tee",
"premium-hoodie",
"summer-cap"
]
@task(2)
def query_product_by_handle(self):
handle = random.choice(self.product_handles)
query = {
"query": """
query ProductByHandle($handle: String!) {
product(handle: $handle) {
id
title
handle
description
availableForSale
variants(first: 5) {
edges {
node {
id
title
availableForSale
quantityAvailable
price {
amount
currencyCode
}
}
}
}
images(first: 3) {
edges {
node {
url
altText
}
}
}
}
}
""",
"variables": {
"handle": handle
}
}
self.client.post(
"/api/2024-01/graphql.json",
json=query,
headers=self.headers,
name="Storefront API - Product Query"
)
@task(2)
def query_collection_products(self):
query = {
"query": """
query CollectionProducts {
collection(handle: "best-sellers") {
id
title
products(first: 12) {
edges {
node {
id
title
handle
availableForSale
priceRange {
minVariantPrice {
amount
currencyCode
}
}
}
}
}
}
}
"""
}
self.client.post(
"/api/2024-01/graphql.json",
json=query,
headers=self.headers,
name="Storefront API - Collection Query"
)
@task(1)
def predictive_search_style_query(self):
query = {
"query": """
query SearchProducts($query: String!) {
products(first: 8, query: $query) {
edges {
node {
id
title
handle
vendor
}
}
}
}
""",
"variables": {
"query": "hoodie"
}
}
self.client.post(
"/api/2024-01/graphql.json",
json=query,
headers=self.headers,
name="Storefront API - Search Query"
)Why this matters for headless Shopify
If your storefront uses Hydrogen, Next.js, Gatsby, Remix, or another headless frontend, the Storefront API is often the real performance bottleneck. This test helps you measure:
- GraphQL response times
- Query complexity impact
- Product and collection retrieval speed
- Search responsiveness under concurrent load
For headless commerce teams, this kind of stress testing is often more important than testing Liquid-rendered storefront pages.
Advanced Scenario 4: Cart Creation via Storefront API
If you use Shopify’s newer cart workflows in a headless implementation, test cart creation and line additions directly through GraphQL.
from locust import HttpUser, task, between
import random
class ShopifyHeadlessCartUser(HttpUser):
wait_time = between(1, 4)
headers = {
"Content-Type": "application/json",
"X-Shopify-Storefront-Access-Token": "your_storefront_access_token"
}
merchandise_ids = [
"gid://shopify/ProductVariant/44681234567890",
"gid://shopify/ProductVariant/44681234567891",
"gid://shopify/ProductVariant/44681234567892"
]
cart_id = None
@task(1)
def create_cart(self):
if self.cart_id:
return
merchandise_id = random.choice(self.merchandise_ids)
mutation = {
"query": """
mutation cartCreate($merchandiseId: ID!) {
cartCreate(
input: {
lines: [
{
quantity: 1,
merchandiseId: $merchandiseId
}
]
}
) {
cart {
id
checkoutUrl
totalQuantity
}
userErrors {
field
message
}
}
}
""",
"variables": {
"merchandiseId": merchandise_id
}
}
response = self.client.post(
"/api/2024-01/graphql.json",
json=mutation,
headers=self.headers,
name="Storefront API - Cart Create"
)
if response.status_code == 200:
data = response.json()
cart = data.get("data", {}).get("cartCreate", {}).get("cart")
if cart:
self.cart_id = cart["id"]
@task(2)
def add_line_to_cart(self):
if not self.cart_id:
self.create_cart()
return
merchandise_id = random.choice(self.merchandise_ids)
mutation = {
"query": """
mutation cartLinesAdd($cartId: ID!, $merchandiseId: ID!) {
cartLinesAdd(
cartId: $cartId,
lines: [
{
quantity: 1,
merchandiseId: $merchandiseId
}
]
) {
cart {
id
totalQuantity
}
userErrors {
field
message
}
}
}
""",
"variables": {
"cartId": self.cart_id,
"merchandiseId": merchandise_id
}
}
self.client.post(
"/api/2024-01/graphql.json",
json=mutation,
headers=self.headers,
name="Storefront API - Cart Lines Add"
)When to use this test
Use this scenario if your Shopify storefront is headless and relies on Storefront API cart operations instead of classic /cart/*.js endpoints.
This is especially useful for:
- Hydrogen storefronts
- Custom React or Next.js frontends
- Mobile apps backed by Shopify Storefront API
- Progressive web apps using Shopify as the commerce backend
Analyzing Your Results
After running your Shopify load test in LoadForge, focus on the metrics that directly impact shopper experience and conversion.
Response time percentiles
Don’t just look at average response time. Pay close attention to:
- P50 for typical user experience
- P95 for slower edge cases
- P99 for worst-case shopper impact
For Shopify performance testing, a product page with a decent average but poor P95 may still feel unreliable during peak traffic.
Error rates
Watch for:
- 4xx errors from invalid requests or authentication issues
- 429 throttling, especially for API-heavy tests
- 5xx errors from app proxies, custom integrations, or middleware
- Redirect loops or failed login flows
Throughput
Review requests per second across:
- Homepage
- Product pages
- Collection pages
- Cart endpoints
- GraphQL API endpoints
A drop in throughput combined with rising latency often indicates the system is reaching capacity.
Endpoint-level bottlenecks
Compare endpoint performance directly. In many Shopify tests, you’ll find:
/cart/add.jsslower than product pages- GraphQL collection queries slower than product queries
- Authenticated account pages slower than anonymous browsing
- Search endpoints degrading faster under concurrency
Geographic performance
With LoadForge’s global test locations, you can measure how your Shopify store performs for users in different regions. This is useful for identifying:
- CDN issues
- Regional latency differences
- Third-party script delays in specific markets
Trends during ramp-up
Run tests with gradual user ramp-up and observe where performance starts to degrade. This helps identify your practical concurrency threshold before real shoppers experience slowdowns.
Performance Optimization Tips
Here are some practical ways to improve Shopify performance after load testing reveals bottlenecks.
Optimize theme assets
- Compress and properly size images
- Remove unused JavaScript and CSS
- Audit third-party app scripts
- Reduce render-blocking resources
Simplify collection and product templates
- Avoid overly complex Liquid logic
- Limit expensive app widgets on high-traffic pages
- Reduce the number of products loaded per collection page
Improve cart performance
- Minimize custom cart logic
- Audit AJAX cart customizations
- Test app interactions that hook into add-to-cart events
Optimize Storefront API queries
- Request only the fields you need
- Reduce nested GraphQL query complexity
- Paginate product and collection data carefully
- Cache where appropriate in headless architectures
Review app impact
Apps can be one of the biggest contributors to Shopify performance issues. Disable or test apps selectively to identify which integrations slow down key journeys.
Prepare for peak traffic
Use LoadForge to run distributed stress testing ahead of major campaigns. Simulate realistic traffic from multiple regions and use real-time reporting to catch regressions before launch day. If you deploy theme updates through CI/CD, add performance testing as a release gate.
Common Pitfalls to Avoid
Shopify load testing is most effective when it reflects actual user behavior. Avoid these common mistakes.
Testing only the homepage
The homepage is rarely the most important performance bottleneck. Product pages, collection pages, cart actions, and search usually matter more for revenue.
Using unrealistic traffic patterns
A test that hammers one endpoint continuously won’t reflect real shopper behavior. Mix browsing, add-to-cart, and account activity in realistic proportions.
Ignoring variant IDs
For Shopify cart testing, you need valid variant IDs, not just product handles. Using incorrect IDs will produce misleading failures.
Overlooking session behavior
Cart and login flows depend on cookies and session continuity. Make sure your Locust users behave like real sessions rather than isolated stateless requests.
Not accounting for third-party scripts and apps
Many Shopify slowdowns come from outside Shopify core. If your load test ignores app-driven endpoints or frontend dependencies, you may miss the real issue.
Trying to fully automate payment submission
In most Shopify setups, full checkout and payment automation is limited or inappropriate for load testing. Focus instead on cart creation, checkout initiation, and pre-purchase flow performance.
Failing to test before major events
Too many teams wait until the week of a launch or sale to run performance tests. Shopify stress testing should happen well before traffic spikes, giving you time to optimize themes, apps, and custom integrations.
Conclusion
Shopify load testing helps you uncover the issues that actually affect shopper experience: slow collection pages, laggy add-to-cart actions, overloaded Storefront API queries, and fragile customer login flows. Even though Shopify provides a powerful managed platform, your theme, apps, and custom storefront architecture still need thorough performance testing.
With LoadForge, you can run realistic Shopify load tests using Locust scripts, simulate traffic from global locations, monitor results in real time, and scale tests with cloud-based infrastructure. Whether you’re validating a traditional Shopify storefront or a headless commerce build, LoadForge makes it easier to find bottlenecks before your customers do.
If you’re preparing for a product drop, holiday sale, or high-traffic marketing campaign, now is the time to test. Try LoadForge and see how your Shopify store performs under real-world load.
LoadForge Team
LoadForge is a load and performance testing platform built on Locust. Our team has been shipping load tests against production systems since 2018, and we write these guides from real customer engagements.
Related guides
Keep going with more guides from the same category.

Contentful Load Testing: How to Load Test Contentful APIs with LoadForge
Learn how to load test Contentful APIs with LoadForge to measure content delivery performance and handle traffic surges.

Ghost Load Testing: Performance Testing Ghost CMS with LoadForge
Learn how to load test Ghost CMS with LoadForge to benchmark publishing performance and keep content delivery fast under load.

Magento Load Testing: Performance Testing Magento Stores with LoadForge
Run Magento load tests with LoadForge to identify slow pages, optimize checkout flows, and validate store performance at scale.