{"id":4971,"date":"2026-02-11T15:54:01","date_gmt":"2026-02-11T12:54:01","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/cdn-and-cache-key-architecture-for-multilingual-multi-currency-woocommerce\/"},"modified":"2026-02-11T15:54:01","modified_gmt":"2026-02-11T12:54:01","slug":"cdn-and-cache-key-architecture-for-multilingual-multi-currency-woocommerce","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/cdn-and-cache-key-architecture-for-multilingual-multi-currency-woocommerce\/","title":{"rendered":"CDN and Cache\u2011Key Architecture for Multilingual &amp; Multi\u2011Currency WooCommerce"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>For a simple single-language WooCommerce store, basic CDN caching rules are often enough. As soon as you add multiple languages, multiple currencies, and regional pricing, the picture changes completely. Product pages start showing the wrong prices, visitors see the wrong language, and your cache hit ratio falls off a cliff. All of this usually comes down to one architectural topic that is easy to overlook: <strong>how you design your CDN cache key<\/strong> for a multilingual and multi\u2011currency WooCommerce setup.<\/p>\n<p>In this article, we will walk through the practical side of building a CDN and cache\u2011key strategy that respects language, currency, and customer state without breaking carts, checkouts, or SEO. We will focus on URL structure, cookies, headers, and GeoIP signals, and we will keep the examples close to real WooCommerce setups running on our hosting stack at dchost.com. If you already know you want a CDN but are unsure how to keep variants under control, this is exactly the level of detail you need.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Why_CDN_CacheKey_Design_Matters_So_Much_for_Multilingual_Stores\"><span class=\"toc_number toc_depth_1\">1<\/span> Why CDN &amp; Cache\u2011Key Design Matters So Much for Multilingual Stores<\/a><\/li><li><a href=\"#Cache_Keys_101_What_the_CDN_Actually_Uses_to_Find_Your_Page\"><span class=\"toc_number toc_depth_1\">2<\/span> Cache Keys 101: What the CDN Actually Uses to Find Your Page<\/a><ul><li><a href=\"#What_Is_a_Cache_Key\"><span class=\"toc_number toc_depth_2\">2.1<\/span> What Is a Cache Key?<\/a><\/li><li><a href=\"#Safe_vs_Unsafe_Pages_for_HTML_Caching_in_WooCommerce\"><span class=\"toc_number toc_depth_2\">2.2<\/span> Safe vs Unsafe Pages for HTML Caching in WooCommerce<\/a><\/li><li><a href=\"#The_Enemy_Cache_Fragmentation\"><span class=\"toc_number toc_depth_2\">2.3<\/span> The Enemy: Cache Fragmentation<\/a><\/li><\/ul><\/li><li><a href=\"#Multilingual_Architecture_How_Domain_URL_Choices_Shape_Your_Cache_Key\"><span class=\"toc_number toc_depth_1\">3<\/span> Multilingual Architecture: How Domain &amp; URL Choices Shape Your Cache Key<\/a><ul><li><a href=\"#Option_1_Separate_CountryLanguage_Domains\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Option 1: Separate Country\/Language Domains<\/a><\/li><li><a href=\"#Option_2_Language_in_Subdirectory_en_de\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Option 2: Language in Subdirectory (\/en\/, \/de\/)<\/a><\/li><li><a href=\"#Option_3_Language_in_Subdomain_enexamplecom_deexamplecom\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Option 3: Language in Subdomain (en.example.com, de.example.com)<\/a><\/li><li><a href=\"#Option_4_Language_Determined_Only_by_Cookie_or_Accept-Language\"><span class=\"toc_number toc_depth_2\">3.4<\/span> Option 4: Language Determined Only by Cookie or Accept-Language<\/a><\/li><\/ul><\/li><li><a href=\"#MultiCurrency_Where_the_Real_CacheKey_Challenges_Start\"><span class=\"toc_number toc_depth_1\">4<\/span> Multi\u2011Currency: Where the Real Cache\u2011Key Challenges Start<\/a><ul><li><a href=\"#Currency_in_Query_String_currencyEUR\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Currency in Query String (?currency=EUR)<\/a><\/li><li><a href=\"#Currency_in_Path_or_Combined_Locale_eg_en-eur\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Currency in Path or Combined Locale (e.g. \/en-eur\/)<\/a><\/li><li><a href=\"#Currency_in_Cookie\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Currency in Cookie<\/a><\/li><li><a href=\"#Handling_GeoIP-Based_Currency\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Handling GeoIP-Based Currency<\/a><\/li><\/ul><\/li><li><a href=\"#Designing_a_Practical_CDN_CacheKey_Strategy_for_WooCommerce\"><span class=\"toc_number toc_depth_1\">5<\/span> Designing a Practical CDN Cache\u2011Key Strategy for WooCommerce<\/a><ul><li><a href=\"#Step_1_Stabilize_Your_URL_Strategy\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Step 1: Stabilize Your URL Strategy<\/a><\/li><li><a href=\"#Step_2_Define_Your_Base_Cache_Key\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Step 2: Define Your Base Cache Key<\/a><\/li><li><a href=\"#Step_3_Add_Selected_Query_Parameters_Currency_Pagination_Filters\"><span class=\"toc_number toc_depth_2\">5.3<\/span> Step 3: Add Selected Query Parameters (Currency, Pagination, Filters)<\/a><\/li><li><a href=\"#Step_4_Add_a_Limited_Cookie_Dimension_Only_When_Necessary\"><span class=\"toc_number toc_depth_2\">5.4<\/span> Step 4: Add a Limited Cookie Dimension Only When Necessary<\/a><\/li><li><a href=\"#Step_5_Segment_LoggedIn_vs_Guest_Traffic\"><span class=\"toc_number toc_depth_2\">5.5<\/span> Step 5: Segment Logged\u2011In vs Guest Traffic<\/a><\/li><li><a href=\"#Step_6_Avoid_Device-Based_Cache_Explosion\"><span class=\"toc_number toc_depth_2\">5.6<\/span> Step 6: Avoid Device-Based Cache Explosion<\/a><\/li><\/ul><\/li><li><a href=\"#Edge_Logic_Vary_Headers_Geo_Redirects_SEOSafe_Behavior\"><span class=\"toc_number toc_depth_1\">6<\/span> Edge Logic: Vary Headers, Geo Redirects &amp; SEO\u2011Safe Behavior<\/a><ul><li><a href=\"#Accept-Language_vs_Explicit_Language_URLs\"><span class=\"toc_number toc_depth_2\">6.1<\/span> Accept-Language vs Explicit Language URLs<\/a><\/li><li><a href=\"#GeoIP_Redirects_and_Cache_Keys\"><span class=\"toc_number toc_depth_2\">6.2<\/span> GeoIP Redirects and Cache Keys<\/a><\/li><li><a href=\"#Dont_Break_SEO_Canonical_Hreflang_and_Caching\"><span class=\"toc_number toc_depth_2\">6.3<\/span> Don\u2019t Break SEO: Canonical, Hreflang and Caching<\/a><\/li><\/ul><\/li><li><a href=\"#Measuring_Tuning_and_Scaling_Your_Origin_with_a_CDN_in_Front\"><span class=\"toc_number toc_depth_1\">7<\/span> Measuring, Tuning and Scaling Your Origin with a CDN in Front<\/a><ul><li><a href=\"#Monitor_Cache_Hit_Ratio_and_TTFB\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Monitor Cache Hit Ratio and TTFB<\/a><\/li><li><a href=\"#Handling_Promotions_and_Purge_Events\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Handling Promotions and Purge Events<\/a><\/li><li><a href=\"#RightSizing_Your_Origin_VPS_Dedicated_or_Cluster\"><span class=\"toc_number toc_depth_2\">7.3<\/span> Right\u2011Sizing Your Origin: VPS, Dedicated or Cluster<\/a><\/li><\/ul><\/li><li><a href=\"#Putting_It_All_Together\"><span class=\"toc_number toc_depth_1\">8<\/span> Putting It All Together<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Why_CDN_CacheKey_Design_Matters_So_Much_for_Multilingual_Stores\">Why CDN &amp; Cache\u2011Key Design Matters So Much for Multilingual Stores<\/span><\/h2>\n<p>A CDN (Content Delivery Network) moves your static and semi\u2011dynamic content closer to visitors globally, lowering latency and improving Core Web Vitals. If you want a refresher on CDN fundamentals, our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/cdn-nedir-ne-zaman-gerekir-trafik-ve-lokasyona-gore-karar-rehberi\/\">what a CDN is and when you really need one<\/a> is a good starting point.<\/p>\n<p>However, on a multilingual and multi\u2011currency WooCommerce store, the CDN cannot just cache one generic copy of each page. At a minimum, you have different variants by:<\/p>\n<ul>\n<li><strong>Language<\/strong> \u2013 \/en\/, \/de\/, \/fr\/, or separate domains<\/li>\n<li><strong>Currency<\/strong> \u2013 EUR, USD, GBP, etc.<\/li>\n<li><strong>Customer state<\/strong> \u2013 logged\u2011in vs guest, items in cart, user roles<\/li>\n<li><strong>Device<\/strong> \u2013 sometimes desktop vs mobile HTML<\/li>\n<li><strong>Geo<\/strong> \u2013 content or pricing rules based on visitor country<\/li>\n<\/ul>\n<p>All these dimensions affect which version of a page is correct for a given visitor. The CDN\u2019s <strong>cache key<\/strong> is the formula that decides which of these dimensions are considered when looking up an object in cache. If the key is too simple, users see wrong language or prices. If the key is too complex, you end up with millions of variants that never hit cache and overload your origin.<\/p>\n<p>Getting this balance right is the art of CDN and cache\u2011key architecture for WooCommerce. Let\u2019s unpack the concepts and then design a realistic strategy step by step.<\/p>\n<h2><span id=\"Cache_Keys_101_What_the_CDN_Actually_Uses_to_Find_Your_Page\">Cache Keys 101: What the CDN Actually Uses to Find Your Page<\/span><\/h2>\n<h3><span id=\"What_Is_a_Cache_Key\">What Is a Cache Key?<\/span><\/h3>\n<p>A <strong>cache key<\/strong> is the set of attributes a CDN or reverse proxy uses to decide whether a request is a cache hit or miss. At its simplest, it looks like:<\/p>\n<ul>\n<li>Scheme (http\/https)<\/li>\n<li>Host (example.com)<\/li>\n<li>Path (\/en\/product\/red-shoes\/)<\/li>\n<li>Selected query parameters (e.g. ?page=2)<\/li>\n<\/ul>\n<p>For multilingual and multi\u2011currency, we usually extend this with additional dimensions, such as:<\/p>\n<ul>\n<li>Language (from URL, subdomain, or header)<\/li>\n<li>Currency (from URL, query string, cookie, or header)<\/li>\n<li>Sometimes: important cookies that change the page output<\/li>\n<\/ul>\n<p>Each distinct combination of these values becomes a separate cache entry. That\u2019s why choosing what goes into the key is a primary performance and correctness decision.<\/p>\n<h3><span id=\"Safe_vs_Unsafe_Pages_for_HTML_Caching_in_WooCommerce\">Safe vs Unsafe Pages for HTML Caching in WooCommerce<\/span><\/h3>\n<p>Before we add languages and currencies into the mix, we have to respect WooCommerce\u2019s own boundaries. Some pages should <strong>never<\/strong> be cached at the HTML level:<\/p>\n<ul>\n<li>Cart (\/cart\/)<\/li>\n<li>Checkout (\/checkout\/)<\/li>\n<li>My Account (\/my-account\/)<\/li>\n<li>Login\/registration pages<\/li>\n<\/ul>\n<p>Others are <strong>usually safe<\/strong>, with some caveats:<\/p>\n<ul>\n<li>Home page and landing pages<\/li>\n<li>Category and archive pages<\/li>\n<li>Product detail pages<\/li>\n<li>Blog content and informational pages<\/li>\n<\/ul>\n<p>We covered generic WooCommerce caching rules (which paths to bypass, which cookies to ignore, etc.) in detail in our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/woocommerce-icin-cdn-ve-onbellek-ayarlari-sepet-ve-odeme-sayfalarini-bozmadan-hizlanmak\/\">CDN and caching settings for WooCommerce without breaking cart and checkout<\/a>. In this article, we will assume you already follow those safe\/unsafe rules and focus on the extra complexity of multiple languages and currencies.<\/p>\n<h3><span id=\"The_Enemy_Cache_Fragmentation\">The Enemy: Cache Fragmentation<\/span><\/h3>\n<p>Every extra thing you add to the cache key multiplies your variants. For example, suppose you have:<\/p>\n<ul>\n<li>4 languages<\/li>\n<li>5 currencies<\/li>\n<li>2 device layouts (desktop, mobile)<\/li>\n<\/ul>\n<p>If you blindly include all three dimensions in the cache key for every page, one URL could explode into <strong>4 \u00d7 5 \u00d7 2 = 40<\/strong> variants. Multiply that by thousands of products and your cache starts to look like a random sample of unique pages instead of a high\u2011hit\u2011ratio performance layer.<\/p>\n<p>The key design question becomes: <strong>Which dimensions really need their own cached HTML, and which can be handled by JavaScript or price APIs on top of a shared HTML shell?<\/strong><\/p>\n<h2><span id=\"Multilingual_Architecture_How_Domain_URL_Choices_Shape_Your_Cache_Key\">Multilingual Architecture: How Domain &amp; URL Choices Shape Your Cache Key<\/span><\/h2>\n<p>Multilingual architecture heavily influences your CDN strategy. We have a separate in\u2011depth article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/cok-dilli-web-siteleri-icin-hosting-ve-seo-mimarisi\/\">multilingual website hosting and SEO architecture (WPML vs Multisite vs separate domains)<\/a>. Here we will focus on what each option means for your cache key.<\/p>\n<h3><span id=\"Option_1_Separate_CountryLanguage_Domains\">Option 1: Separate Country\/Language Domains<\/span><\/h3>\n<p>Example:<\/p>\n<ul>\n<li>example.com \u2013 English, global<\/li>\n<li>example.de \u2013 German, Germany<\/li>\n<li>example.fr \u2013 French, France<\/li>\n<\/ul>\n<p>In this setup, <strong>the host header itself is the language signal<\/strong>. That means your cache key can often remain:<\/p>\n<ul>\n<li>scheme + host + path + selected query string<\/li>\n<\/ul>\n<p>You do <em>not<\/em> need to explicitly add language to the cache key, because the host already makes each language unique. This is the simplest option in terms of CDN architecture and usually plays well with SEO and hreflang.<\/p>\n<h3><span id=\"Option_2_Language_in_Subdirectory_en_de\">Option 2: Language in Subdirectory (\/en\/, \/de\/)<\/span><\/h3>\n<p>Example:<\/p>\n<ul>\n<li>example.com\/en\/<\/li>\n<li>example.com\/de\/<\/li>\n<\/ul>\n<p>Here the language is encoded into the path. If you keep the default cache key of scheme + host + path, you automatically get separate entries per language because <code>\/en\/product\/red-shoes\/<\/code> and <code>\/de\/product\/red-shoes\/<\/code> are different URLs.<\/p>\n<p>In other words, <strong>you still don\u2019t need a separate language field in the key<\/strong>, as long as your language selection is fully represented in the URL (and not in a cookie).<\/p>\n<h3><span id=\"Option_3_Language_in_Subdomain_enexamplecom_deexamplecom\">Option 3: Language in Subdomain (en.example.com, de.example.com)<\/span><\/h3>\n<p>This behaves similarly to Option 1 (separate domains), because the <strong>subdomain is part of the host<\/strong>. Again, the standard cache key already keeps languages separate.<\/p>\n<h3><span id=\"Option_4_Language_Determined_Only_by_Cookie_or_Accept-Language\">Option 4: Language Determined Only by Cookie or Accept-Language<\/span><\/h3>\n<p>This is where things get risky. If your URLs are the same for all languages (e.g. <code>example.com\/product\/red-shoes\/<\/code>), but you change the language:<\/p>\n<ul>\n<li>Based on a cookie (e.g. <code>wp-wpml_current_language<\/code>)<\/li>\n<li>Or based on the browser\u2019s <code>Accept-Language<\/code> header<\/li>\n<\/ul>\n<p>then different visitors may expect <strong>different HTML for the same URL<\/strong>. You have two choices:<\/p>\n<ol>\n<li>Don\u2019t cache HTML for these URLs at all (performance loss).<\/li>\n<li>Add the language signal (cookie or header) to the cache key.<\/li>\n<\/ol>\n<p>In practice, we strongly prefer <strong>having language in the URL or host<\/strong>. It is more cache\u2011friendly and SEO\u2011friendly, and makes hreflang implementation far simpler. Our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/hreflangi-dogru-kurmanin-sirlari-cctld-alt-dizin-alt-alan-ve-x-default-ile-uluslararasi-seoyu-rayina-oturt\/\">setting up hreflang correctly with ccTLDs, subdirectories and subdomains<\/a> goes deeper into why this matters.<\/p>\n<h2><span id=\"MultiCurrency_Where_the_Real_CacheKey_Challenges_Start\">Multi\u2011Currency: Where the Real Cache\u2011Key Challenges Start<\/span><\/h2>\n<p>Language is often cleanly represented in the URL. Currency is not always that lucky. Most WooCommerce multi\u2011currency plugins support several ways of picking a currency:<\/p>\n<ul>\n<li>User selection in a currency switcher<\/li>\n<li>GeoIP\u2011based automatic currency<\/li>\n<li>Payment\u2011method\u2011specific currency rules<\/li>\n<\/ul>\n<p>And they store the result in different places:<\/p>\n<ul>\n<li>URL parameter (e.g. <code>?currency=EUR<\/code>)<\/li>\n<li>Language + currency in path (e.g. <code>\/en-eur\/<\/code>)<\/li>\n<li>Cookie (e.g. <code>woocommerce_multicurrency<\/code>)<\/li>\n<li>Custom header (rare, usually only with custom integrations)<\/li>\n<\/ul>\n<p>Let\u2019s look at what those choices mean for your CDN cache key.<\/p>\n<h3><span id=\"Currency_in_Query_String_currencyEUR\">Currency in Query String (?currency=EUR)<\/span><\/h3>\n<p>This is relatively CDN\u2011friendly as long as your CDN supports <strong>whitelisting query parameters into the cache key<\/strong>. The idea is:<\/p>\n<ul>\n<li>Base key: scheme + host + path<\/li>\n<li>Add: <code>?currency=<\/code> as an allowed parameter<\/li>\n<\/ul>\n<p>So <code>\/en\/product\/red-shoes\/?currency=EUR<\/code> and <code>\/en\/product\/red-shoes\/?currency=USD<\/code> become separate cache entries.<\/p>\n<p>Key considerations:<\/p>\n<ul>\n<li>Strip all other meaningless query params (<code>utm_*<\/code>, tracking IDs, etc.) from the key.<\/li>\n<li>Be consistent: don\u2019t sometimes include currency, sometimes not.<\/li>\n<li>Make sure your plugin always appends the currency param once it is known, so the URL is stable.<\/li>\n<\/ul>\n<h3><span id=\"Currency_in_Path_or_Combined_Locale_eg_en-eur\">Currency in Path or Combined Locale (e.g. \/en-eur\/)<\/span><\/h3>\n<p>If your multilingual\/multi\u2011currency setup encodes both in the path (e.g. <code>\/en-eur\/product\/<\/code>, <code>\/de-eur\/product\/<\/code>, <code>\/de-chf\/product\/<\/code>), then you again get the benefit of having it all inside the <strong>URL itself<\/strong>. The default cache key of host + path works fine and creates a separate entry for each combination.<\/p>\n<p>The downside is potential <strong>URL proliferation<\/strong>. If you have 5 currencies and 6 languages, you have up to 30 locale prefixes. From an SEO perspective you should be careful which ones you expose to search engines and where hreflang should point.<\/p>\n<h3><span id=\"Currency_in_Cookie\">Currency in Cookie<\/span><\/h3>\n<p>This is common with multi\u2011currency plugins that want \u201cpretty\u201d URLs without extra parameters. The problem is the same as with language in cookies: <strong>the same URL can render different HTML<\/strong> depending on the cookie value.<\/p>\n<p>If you include the currency cookie in your cache key, your variants multiply fast. For example, assuming 5 currencies:<\/p>\n<ul>\n<li>Each product page now has 5 possible HTML variants in cache.<\/li>\n<\/ul>\n<p>This is acceptable <strong>if<\/strong>:<\/p>\n<ul>\n<li>You only include a single, well\u2011defined cookie in the cache key (not all cookies).<\/li>\n<li>You keep TTLs reasonable so that variants that are rarely requested drop out.<\/li>\n<li>You avoid per\u2011user or per\u2011session cookies in the key.<\/li>\n<\/ul>\n<p>If your plugin sets multiple currency\u2011related cookies (e.g. one for currency, one for region, one for tax configuration), try to configure it (or customize it) so that <strong>only a single normalized cookie<\/strong> controls the final price behavior. Then add only that normalized cookie to your CDN cache key.<\/p>\n<h3><span id=\"Handling_GeoIP-Based_Currency\">Handling GeoIP-Based Currency<\/span><\/h3>\n<p>Some stores automatically pick a currency based on the visitor\u2019s country (via GeoIP). If the currency is then reflected in URL or cookie, the above rules apply.<\/p>\n<p>If not, and you purely rely on the <strong>GeoIP header<\/strong> from the CDN (e.g. <code>CF-IPCountry<\/code> or similar), you must decide whether to:<\/p>\n<ul>\n<li>Add country to the cache key (which may explode the number of variants), or<\/li>\n<li>Use GeoIP just to <em>redirect<\/em> first\u2011time visitors to a language\/currency URL, after which the URL itself holds the variant.<\/li>\n<\/ul>\n<p>We strongly prefer the redirect approach: detect the country, then send the user to <code>example.de<\/code> or <code>example.com\/de\/<\/code> with an explicit currency. Your cache key then stays simple and predictable.<\/p>\n<h2><span id=\"Designing_a_Practical_CDN_CacheKey_Strategy_for_WooCommerce\">Designing a Practical CDN Cache\u2011Key Strategy for WooCommerce<\/span><\/h2>\n<p>With the theory out of the way, let\u2019s build a practical cache\u2011key strategy that works for most multilingual and multi\u2011currency WooCommerce stores.<\/p>\n<h3><span id=\"Step_1_Stabilize_Your_URL_Strategy\">Step 1: Stabilize Your URL Strategy<\/span><\/h3>\n<p>Decide where language and currency live:<\/p>\n<ol>\n<li><strong>Language<\/strong> \u2013 domain, subdomain, or subdirectory (recommended: one of these, not cookies).<\/li>\n<li><strong>Currency<\/strong> \u2013 URL parameter or combined locale in path (recommended) or, if unavoidable, single normalized cookie.<\/li>\n<\/ol>\n<p>From an SEO and internationalization perspective, mapping your language structure to a clear domain or directory scheme is critical. If you are still deciding, our articles on <a href=\"https:\/\/www.dchost.com\/blog\/en\/com-mu-cctld-mi-uluslararasi-seo-icin-dogru-domain-mimarisi\/\">international SEO domain architecture (ccTLD vs subfolder vs subdomain)<\/a> and the already\u2011mentioned hreflang guide provide concrete decision frameworks.<\/p>\n<h3><span id=\"Step_2_Define_Your_Base_Cache_Key\">Step 2: Define Your Base Cache Key<\/span><\/h3>\n<p>For HTML pages we usually start with:<\/p>\n<ul>\n<li><strong>Scheme<\/strong> (https only; HTTP should redirect)<\/li>\n<li><strong>Host<\/strong> (including subdomain)<\/li>\n<li><strong>Path<\/strong> (full request path)<\/li>\n<\/ul>\n<p>This already handles: different languages per domain, per subdomain, or per directory. No extra language dimension is required, because it\u2019s baked into host\/path.<\/p>\n<h3><span id=\"Step_3_Add_Selected_Query_Parameters_Currency_Pagination_Filters\">Step 3: Add Selected Query Parameters (Currency, Pagination, Filters)<\/span><\/h3>\n<p>Next we explicitly whitelist only the query parameters that genuinely change content:<\/p>\n<ul>\n<li><code>currency<\/code> \u2013 when using currency in query string<\/li>\n<li><code>paged<\/code> or <code>page<\/code> \u2013 for archives pagination<\/li>\n<li>Specific filter parameters (e.g. <code>min_price<\/code>, <code>max_price<\/code>, <code>filter_color<\/code>) if you want cached variants for them<\/li>\n<\/ul>\n<p>Everything else\u2014<code>utm_source<\/code>, <code>fbclid<\/code>, tracking IDs\u2014should be <strong>stripped from the key<\/strong>. Many CDNs support \u201cignore all query params except X, Y, Z\u201d. Use that aggressively.<\/p>\n<p>This is also where edge rules and <code>Cache-Control<\/code> behavior come into play. We covered the general patterns for WordPress and WooCommerce in our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/cdn-onbellekleme-cache-control-ve-edge-kurallari-wordpress-ve-woocommercede-tam-isabet-ayarlar\/\">the CDN caching playbook for WordPress and WooCommerce<\/a>. For multilingual\/multi\u2011currency stores, you\u2019ll extend those rules with query\u2011parameter handling as described above.<\/p>\n<h3><span id=\"Step_4_Add_a_Limited_Cookie_Dimension_Only_When_Necessary\">Step 4: Add a Limited Cookie Dimension Only When Necessary<\/span><\/h3>\n<p>In many setups you can avoid cookies in the cache key entirely for HTML pages. But for some multi\u2011currency plugins or personalization rules, you may have to vary on a cookie.<\/p>\n<p>Best practices:<\/p>\n<ul>\n<li><strong>Whitelist<\/strong> exactly which cookies may influence cache (e.g. <code>currency<\/code>).<\/li>\n<li><strong>Ignore<\/strong> all others in the cache key (session IDs, analytics, CSRF tokens, AB test IDs, etc.).<\/li>\n<li>Never vary HTML cache by <em>user\u2011specific<\/em> cookies such as login sessions. Logged\u2011in users should be bypassed.<\/li>\n<\/ul>\n<p>For WooCommerce specifically, ensure that cookies like <code>woocommerce_cart_hash<\/code>, <code>woocommerce_items_in_cart<\/code>, <code>woocommerce_recently_viewed<\/code> do <strong>not<\/strong> enter your cache key for public pages. Instead, use them only in <em>bypass<\/em> rules for cart\/checkout or via AJAX fragments.<\/p>\n<h3><span id=\"Step_5_Segment_LoggedIn_vs_Guest_Traffic\">Step 5: Segment Logged\u2011In vs Guest Traffic<\/span><\/h3>\n<p>By default, we recommend:<\/p>\n<ul>\n<li><strong>Guests<\/strong> \u2013 fully eligible for CDN HTML caching on safe pages, controlled by the cache key we designed.<\/li>\n<li><strong>Logged\u2011in users<\/strong> \u2013 either bypass HTML caching or have a very short TTL at the CDN, depending on your personalization needs and backend capacity.<\/li>\n<\/ul>\n<p>The split is typically done via a rule such as \u201cif <code>wordpress_logged_in_*<\/code> cookie exists, do not cache HTML\u201d. This keeps the cache surface simple and avoids tricky bugs where one customer sees another customer\u2019s account data.<\/p>\n<h3><span id=\"Step_6_Avoid_Device-Based_Cache_Explosion\">Step 6: Avoid Device-Based Cache Explosion<\/span><\/h3>\n<p>It\u2019s tempting to create separate HTML caches for mobile and desktop. But that doubles your variants. Instead, consider:<\/p>\n<ul>\n<li>Using responsive design so the same HTML works for both.<\/li>\n<li>If absolutely needed, vary by a stable header (like <code>User-Agent<\/code> class) instead of many individual values.<\/li>\n<\/ul>\n<p>Most modern WooCommerce themes and builders are responsive enough that you don\u2019t need separate HTML per device. Save that complexity for truly critical use cases.<\/p>\n<h2><span id=\"Edge_Logic_Vary_Headers_Geo_Redirects_SEOSafe_Behavior\">Edge Logic: Vary Headers, Geo Redirects &amp; SEO\u2011Safe Behavior<\/span><\/h2>\n<h3><span id=\"Accept-Language_vs_Explicit_Language_URLs\">Accept-Language vs Explicit Language URLs<\/span><\/h3>\n<p>For performance and SEO, we recommend using <strong>explicit language URLs<\/strong> (domains, subdomains, or directories) and treating <code>Accept-Language<\/code> as a <em>hint<\/em> for first\u2011time redirection rather than as a permanent content switch.<\/p>\n<p>A common pattern:<\/p>\n<ol>\n<li>Visitor comes to <code>example.com<\/code> with <code>Accept-Language: de-DE<\/code>.<\/li>\n<li>Edge logic redirects them once to <code>example.com\/de\/<\/code>.<\/li>\n<li>All further navigation stays in the \/de\/ URL space; the CDN cache key is just host + path.<\/li>\n<\/ol>\n<p>In this setup you do <strong>not<\/strong> need to add <code>Accept-Language<\/code> to the cache key, avoiding fragmentation.<\/p>\n<h3><span id=\"GeoIP_Redirects_and_Cache_Keys\">GeoIP Redirects and Cache Keys<\/span><\/h3>\n<p>Similarly, for country\u2011based redirects, use the country code only in routing logic, then land the user on a concrete language\/currency URL. Do not use country directly in the HTML cache key unless you intentionally want per\u2011country HTML variants.<\/p>\n<p>For example:<\/p>\n<ul>\n<li>CF-IPCountry=DE \u2192 redirect first visit to <code>example.de<\/code> or <code>example.com\/de\/<\/code>.<\/li>\n<li>Once on <code>example.de<\/code>, <strong>host<\/strong> already encodes country\/language.<\/li>\n<\/ul>\n<h3><span id=\"Dont_Break_SEO_Canonical_Hreflang_and_Caching\">Don\u2019t Break SEO: Canonical, Hreflang and Caching<\/span><\/h3>\n<p>Multilingual and multi\u2011currency setups are particularly sensitive to SEO mistakes. While your CDN won\u2019t directly manage <code>rel=\"alternate\" hreflang=\"\u2026\"<\/code> tags, your architecture decisions affect how easy it is to implement them.<\/p>\n<p>Key points:<\/p>\n<ul>\n<li>Each language\/currency combination that you want Google to index should have a stable, unique URL.<\/li>\n<li>Your cache key should mirror that uniqueness: one URL \u2192 one cached variant.<\/li>\n<li>Redirects based on headers (Accept-Language, GeoIP) should settle on such URLs and not keep users bouncing.<\/li>\n<\/ul>\n<p>We already linked to our dedicated hreflang and international SEO guides earlier; they are worth reviewing as you design your cache key so that caching, UX and SEO all point in the same direction.<\/p>\n<h2><span id=\"Measuring_Tuning_and_Scaling_Your_Origin_with_a_CDN_in_Front\">Measuring, Tuning and Scaling Your Origin with a CDN in Front<\/span><\/h2>\n<h3><span id=\"Monitor_Cache_Hit_Ratio_and_TTFB\">Monitor Cache Hit Ratio and TTFB<\/span><\/h3>\n<p>Once your cache\u2011key and edge rules are deployed, watch two numbers closely:<\/p>\n<ul>\n<li><strong>Cache hit ratio<\/strong> \u2013 how many requests are served from CDN vs forwarded to origin.<\/li>\n<li><strong>TTFB (Time To First Byte)<\/strong> \u2013 especially for misses, which still hit your origin server.<\/li>\n<\/ul>\n<p>A well\u2011designed multilingual\/multi\u2011currency cache key should still give you a solid hit ratio on product listings, product detail pages, and content pages. If your hit ratio is unexpectedly low, common causes include:<\/p>\n<ul>\n<li>Too many query parameters in the cache key.<\/li>\n<li>Per\u2011user or per\u2011session cookies accidentally included.<\/li>\n<li>Misconfigured rules that bypass caching due to a cookie that almost everyone has.<\/li>\n<\/ul>\n<p>We often pair CDN analytics with origin logs to diagnose these patterns. If you want to go deeper on interpreting hosting\u2011side metrics, our articles on <a href=\"https:\/\/www.dchost.com\/blog\/en\/yuksek-ttfb-sorununu-cozmek-wordpress-ve-php-sitelerde-sunucu-tarafli-nedenler-ve-cozumler\/\">fixing high TTFB<\/a> and capacity planning for WooCommerce (linked below) are a useful complement.<\/p>\n<h3><span id=\"Handling_Promotions_and_Purge_Events\">Handling Promotions and Purge Events<\/span><\/h3>\n<p>In a multi\u2011currency environment, cache purges have to be smart. When a product\u2019s price changes, you may need to invalidate:<\/p>\n<ul>\n<li>The product page in all languages.<\/li>\n<li>The product page in all currencies.<\/li>\n<li>Listing pages where the product appears.<\/li>\n<\/ul>\n<p>This is easier when your variant dimensions are predictable (host\/path\/selected params) and not hidden in opaque cookies. Many CDNs support tag\u2011based or surrogate\u2011key purges: you tag responses with product IDs or categories and then purge by tag. If your CDN does not support that, at least design URLs so that you can confidently purge by path prefix per language (e.g. <code>\/de\/product\/red-shoes\/<\/code>, <code>\/en\/product\/red-shoes\/<\/code>).<\/p>\n<h3><span id=\"RightSizing_Your_Origin_VPS_Dedicated_or_Cluster\">Right\u2011Sizing Your Origin: <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a>, Dedicated or Cluster<\/span><\/h3>\n<p>A good CDN and cache\u2011key strategy reduces load on your origin, but it does not eliminate the need for a solid server stack. Complex multi\u2011currency calculations, tax rules, and logged\u2011in users still hit PHP and MySQL. If you see CPU or disk IO saturation during peaks, consider:<\/p>\n<ul>\n<li>Moving from shared hosting to an <strong>NVMe VPS<\/strong> where you control PHP\u2011FPM, OPcache and database tuning.<\/li>\n<li>For very busy stores, a <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a> or a small cluster with separate DB and cache servers.<\/li>\n<\/ul>\n<p>We have a dedicated guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/woocommerce-kapasite-planlama-rehberi-vcpu-ram-iops-nasil-hesaplanir\/\">WooCommerce capacity planning for vCPU, RAM and IOPS<\/a> that you can use to estimate what you need before big campaigns. If you outgrow a single server, our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/yuksek-erisilebilir-wordpress-ve-woocommerce-kume-mimarisi\/\">high\u2011availability WordPress and WooCommerce cluster architecture<\/a> shows how to scale further while keeping CDN and cache behavior consistent.<\/p>\n<p>At dchost.com we run WooCommerce stores on optimized VPS, dedicated and colocation setups with tuned Nginx\/Apache, PHP\u2011FPM, Redis and MariaDB\/MySQL. The CDN and cache\u2011key strategy we described here is exactly the layer we put in front of such origins to keep them calm during traffic spikes.<\/p>\n<h2><span id=\"Putting_It_All_Together\">Putting It All Together<\/span><\/h2>\n<p>A multilingual and multi\u2011currency WooCommerce store doesn\u2019t have to mean chaotic caching and slow performance. Most of the hard problems come down to a few structural decisions:<\/p>\n<ul>\n<li>Make language and, ideally, currency visible in URLs or hostnames.<\/li>\n<li>Design a cache key that uses host + path + a small set of meaningful parameters.<\/li>\n<li>Only include a <em>single<\/em>, normalized cookie in the key if you absolutely must vary by cookie.<\/li>\n<li>Segment logged\u2011in users and sensitive paths (cart, checkout, account) out of HTML caching.<\/li>\n<li>Use Accept-Language and GeoIP only to route users once into the right URL space.<\/li>\n<\/ul>\n<p>From there, you can tune edge rules, purge behavior, and origin capacity with much more confidence. If you want to see how general CDN rules translate into WooCommerce specifics, combine this article with our more general guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpress-icin-cdn-onbellek-kurallari-nasil-kurulur-woocommercede-html-cache-bypass-ve-edge-ayarlariyla-uctan-uca-hiz\/\">CDN caching rules for WordPress that won\u2019t break WooCommerce<\/a>.<\/p>\n<p>If you are planning or running a multilingual, multi\u2011currency store and want help aligning domain structure, CDN configuration and hosting resources, our team at dchost.com can review your current setup, propose a cache\u2011key architecture, and host your WooCommerce stack on a right\u2011sized VPS, dedicated server or colocation environment. Reach out with your languages, currencies and typical traffic, and we can turn them into a concrete, testable CDN and hosting design instead of a fragile collection of ad\u2011hoc rules.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>For a simple single-language WooCommerce store, basic CDN caching rules are often enough. As soon as you add multiple languages, multiple currencies, and regional pricing, the picture changes completely. Product pages start showing the wrong prices, visitors see the wrong language, and your cache hit ratio falls off a cliff. All of this usually comes [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4972,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-4971","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/4971","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=4971"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/4971\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/4972"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=4971"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=4971"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=4971"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}