Why Go Headless
Traditional Magento 2 architecture couples the frontend theme layer directly to the backend PHP application. Every page request passes through the Magento rendering pipeline — layout XML, blocks, templates, and KnockoutJS components. This architecture served well for years, but modern commerce demands faster storefronts, omnichannel experiences, and independent frontend deployment cycles.
Headless commerce separates the presentation layer from the commerce engine. The Magento 2 backend becomes a pure API server handling catalog, cart, checkout, and order management, while a dedicated frontend framework delivers the customer experience.
Architecture Overview
A production headless Magento 2 setup consists of several layers:
Frontend Layer: A Next.js or React application deployed on edge infrastructure (Vercel, CloudFront, or a Kubernetes cluster). This handles all rendering — either server-side (SSR) or static (SSG) — and communicates with the backend exclusively through APIs.
API Gateway: An NGINX or AWS API Gateway layer that routes requests, handles rate limiting, and manages authentication tokens. This sits between the frontend and the Magento backend.
Commerce Engine: Magento 2 running in API-only mode with the storefront theme disabled. GraphQL and REST endpoints serve product data, cart operations, and checkout flows.
Services Layer: Microservices for search (Elasticsearch/OpenSearch), payments (Stripe/Adyen), and content (headless CMS like Contentful or Strapi).
Setting Up the GraphQL API
Magento 2 ships with a comprehensive GraphQL API. Enable it and configure the schema for headless use:
// app/etc/env.php
'system' => [
'default' => [
'web' => [
'graphql' => [
'cors_allowed_origins' => 'https://store.example.com',
'cors_allowed_methods' => 'GET,POST,OPTIONS',
'cors_max_age' => 86400,
],
],
],
],
Product Query Example
query GetProductPage($urlKey: String!) {
products(filter: { url_key: { eq: $urlKey } }) {
items {
sku
name
price_range {
minimum_price {
final_price { value currency }
discount { percent_off }
}
}
media_gallery {
url
label
}
description { html }
related_products {
sku
name
thumbnail { url }
}
}
}
}
Frontend Architecture with Next.js
Build the storefront with Next.js for optimal performance through server-side rendering and static generation:
// lib/magento-client.ts
const MAGENTO_GRAPHQL_URL = process.env.MAGENTO_GRAPHQL_URL!;
export async function magentoFetch<T>(
query: string,
variables?: Record<string, unknown>
): Promise<T> {
const response = await fetch(MAGENTO_GRAPHQL_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
Store: "default",
},
body: JSON.stringify({ query, variables }),
next: { revalidate: 60 },
});
const json = await response.json();
if (json.errors) throw new Error(json.errors[0].message);
return json.data;
}
Static Generation for Category Pages
export async function generateStaticParams() {
const data = await magentoFetch<CategoryData>(
`{ categories(filters: {}) { items { url_path children { url_path } } } }`
);
return data.categories.items.flatMap((cat) =>
[cat, ...cat.children].map((c) => ({ slug: c.url_path.split("/") }))
);
}
Caching Strategy
Implement multi-layer caching for performance:
CDN Layer: Cache product listing pages and category pages at the CDN edge with 60-second TTL. Use stale-while-revalidate headers to serve cached content while fetching fresh data.
Application Layer: Use Next.js ISR (Incremental Static Regeneration) with on-demand revalidation triggered by Magento webhooks when products or prices change.
API Layer: Deploy Varnish or Redis in front of the Magento GraphQL endpoint. Cache GET-equivalent POST requests using query hashing.
Handling Cart and Checkout
Cart operations are stateful and require careful session management in a headless context:
// Create guest cart
const { createEmptyCart } = await magentoFetch<{ createEmptyCart: string }>(
`mutation { createEmptyCart }`
);
// Store cart ID in HTTP-only cookie
cookies().set("cart_id", createEmptyCart, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 60 * 60 * 24 * 30,
});
Performance Benchmarks
A well-implemented headless Magento 2 storefront typically achieves:
- Time to First Byte: under 200ms (vs. 800-1200ms traditional)
- Largest Contentful Paint: under 1.5s (vs. 3-5s traditional)
- Core Web Vitals: all green across mobile and desktop
- API response times: under 100ms for cached queries
Deployment Architecture
Deploy the frontend independently from Magento using separate CI/CD pipelines. The frontend deploys in seconds via edge platforms, while Magento backend deployments follow the standard zero-downtime process with maintenance mode and cache warming.
For Magento 2 performance optimization and headless architecture consulting, our team brings deep experience across dozens of headless implementations for B2B and B2C merchants.
Need help with this?
Our team handles this kind of work daily. Let us take care of your infrastructure.
Related Articles
How to Boost Magento 2 Performance in a Few Easy Steps
Magento 2 delivers incredible flexibility for eCommerce, but without proper optimization it can become sluggish. This guide walks through ten proven DevOps strategies to dramatically speed up your store, from PHP upgrades and full-page caching to Varnish, Redis, CDN configuration, and ongoing code audits.
MagentoHow to Upgrade Magento 2 from 2.4.7 to 2.4.8
Keeping Magento current is critical for security, performance, and compatibility. This step-by-step guide walks developers through upgrading from Magento 2.4.7 to 2.4.8, covering system requirements, pre-upgrade checks, Git workflow, Composer commands, and post-upgrade validation.
MagentoHow to Completely Disable "Compare Products" in Magento 2
Magento's built-in Compare Products feature can add unnecessary clutter and slow down page loads. This guide shows you how to fully remove it using layout XML overrides, CSS rules, and a quick CLI deploy -- keeping your storefront clean and fast.