Multi-store support
Evolve supports multiple stores, locales, and currencies from a single backend deployment. Every request carries a StoreContext that tells each service which store, language, and currency to use. This enables scenarios like running separate country stores, localized storefronts, or B2B stores with different assortments from the same infrastructure.
StoreContext
Section titled “StoreContext”The StoreContext has three properties:
storeKey: identifies the storelocale: the language for the request (e.g.nl-NL,en-GB)currency: the currency for prices and carts (e.g.EUR,GBP)
These three values flow through the entire request lifecycle, from the frontend through the gateway to every domain service. All services receive the same StoreContext, regardless of which SAAS backend they integrate with.
How it flows
Section titled “How it flows”sequenceDiagram
participant Frontend
participant Gateway as GraphQL Gateway
participant Commerce as Commerce Service
participant CMS as CMS Service
Frontend->>Gateway: GraphQL request + headers<br/>X-StoreContext-StoreKey<br/>X-StoreContext-Locale<br/>X-StoreContext-Currency
Gateway->>Gateway: Read headers into StoreContext
Gateway->>Commerce: Federated subquery (headers forwarded)
Gateway->>CMS: Federated subquery (headers forwarded)
Commerce->>Commerce: readStoreContextFromRequest()
CMS->>CMS: readStoreContextFromRequest()
Commerce-->>Gateway: Store-scoped, localized data
CMS-->>Gateway: Localized content
Gateway-->>Frontend: Merged response
Frontend
Section titled “Frontend”The frontend sets the three X-StoreContext-* headers on every GraphQL
request, both server-side and client-side:
const fetcher = initClientFetcher("/graphql", { defaultHeaders: { "X-StoreContext-StoreKey": storeConfig.storeKey, "X-StoreContext-Locale": locale, "X-StoreContext-Currency": storeConfig.currency, },});The store key and currency come from the store configuration
(selected per deployment via the STORE_KEY environment variable). The
locale comes from the URL path via next-intl routing (e.g.
/nl-NL/products/...).
Gateway
Section titled “Gateway”The GraphQL gateway (Hive Router) forwards the headers from the
incoming request to every subgraph service. This is configured
declaratively in router.config.yaml:
headers: all: request: - propagate: named: - X-StoreContext-StoreKey - X-StoreContext-Locale - X-StoreContext-CurrencyDomain services
Section titled “Domain services”Each service reads the headers from the incoming request and constructs a
StoreContext object that resolvers can access via context.storeContext:
import { readStoreContextFromRequest } from "@evolve-framework/core/service/graphql";
const storeContext = readStoreContextFromRequest(request);All three headers are required. If any is missing, the request fails with a GraphQL error.
How services use StoreContext
Section titled “How services use StoreContext”Every service uses StoreContext, but what each property means depends on the integration.
Commerce services
Section titled “Commerce services”Commerce services use all three properties to scope operations to the correct store:
storeKey: scopes API calls to a specific store. Carts, orders, customers, and shopping lists are all queried within the store context.locale: determines which translations are returned for product names, descriptions, and category names.currency: selects the correct prices. Together with the country (derived from the locale), it drives price selection, tax calculation, and cart operations.- Product projections: the store context provides parameters for product queries that filter results by store assortment, locale, and pricing.
CMS services
Section titled “CMS services”CMS services (Contentful, Storyblok) use StoreContext primarily for content localization:
locale: determines which language version of content to fetch from the CMS. Contentful uses it to filter entries by locale, Storyblok extracts the language code for its API.storeKey: used in cache keys to keep content separated per store when different stores serve different content.currency: included in cache keys to ensure different currency contexts don’t share cached data.
Cache scoping
Section titled “Cache scoping”All services use StoreContext to generate cache key prefixes. This ensures that cached data from one store, locale, or currency does not leak into another:
public get cacheKeyPrefix(): string { return `${this.storeKey}-${this.locale}-${this.currency}`;}Store configuration
Section titled “Store configuration”Each frontend deployment is configured for a specific store through the
STORE_KEY environment variable. This selects a store configuration that
defines:
- Store key: identifies the store across all backend services
- Default locale and available locales: which languages the store supports
- Currency: the store’s currency
- Country: used for tax and shipping calculations
- Available payment methods: which payment providers are enabled
- Checkout configuration: checkout-specific settings
- Distribution channel: for store-specific product assortment and pricing
To run multiple stores, deploy multiple frontend instances with different
STORE_KEY values. They all share the same backend.
B2B store override
Section titled “B2B store override”In B2B scenarios, a customer may belong to a business unit that is assigned
to a specific store. When this is the case, the ClientContext overrides
the store key from the request with the business unit’s store key:
get storeKey(): string { if (!this.isAuthenticated()) { return this.storeContext.storeKey; } return this._info?.businessContext?.storeKey ?? this.storeContext.storeKey;}This allows B2B customers to see store-specific assortments and pricing based on their business unit, even when accessing the platform through a shared storefront. See B2B & B2C architecture for more details on business units and the BusinessContext.

