Full-page caching can significantly speed up WordPress, but WooCommerce requires careful rules. If a server, CDN, or caching plugin delivers a ready-made HTML page to the wrong visitor, that user may see someone else’s cart, personal data, or a checkout form that has already been filled in.
A safe setup is based on separating content: public pages can be cached for everyone, while cart, checkout, account pages, and responses for users with an active session must bypass the page cache or receive a separately isolated response. It is important to check not only WordPress settings but the entire delivery chain: browser, CDN, reverse proxy, web server, caching plugin, and object cache.
Why Caching Is Dangerous for WooCommerce
A standard product page is often identical for all visitors, so it is convenient to store it in the page cache. Cart and checkout pages work differently: their content depends on cookies, the session, authentication status, shipping method, entered data, and the current order state.
The problem occurs when the cache ignores these differences. For example, the first user opens the cart page, the server generates HTML containing that user’s products, and the CDN stores the response. The next guest may receive the same page with someone else’s items. Even if the price or complete order contents are not displayed, this behavior is already a data-isolation failure.
Caching can also break store functionality: the checkout button may not update after the quantity changes, error messages may disappear, an outdated authentication status may be displayed, or dynamic cart fragments may stop working.
- Do not cache personalized HTML as a shared response for all visitors.
- Do not rely only on exclusions in the plugin if a CDN or Nginx cache operates in front of it.
- Treat any response containing session data as potentially personalized.
Which WooCommerce Pages Must Bypass the Page Cache
For most stores, the basic exclusions are the cart, checkout, and customer account pages. In a typical WooCommerce setup, these may use URLs such as /cart/, /checkout/, and /my-account/, but the actual URLs can be changed for a specific store. Rely on the pages assigned to these functions rather than on the slug names alone.
The exclusion must apply at every level where HTML may be stored: the caching plugin, server, reverse proxy, and CDN. If only the WordPress plugin knows that /checkout/ must not be cached while the CDN continues to serve an old object, the problem remains.
Also check URLs used by the theme or store extensions for mini-cart functionality, one-page checkout, product comparisons, or personalized recommendations. They do not always have standard names, so identify them using the extension documentation and the browser’s network requests.
- Exclude cart, checkout, and my-account pages from full-page caching.
- Do not cache login, registration, or other pages containing personal data.
- Do not cache POST requests; for GET requests, check whether they are AJAX operations.
- Update the cache rules after changing WooCommerce slugs or page assignments.
Cookies That Identify a Personalized Request
WooCommerce uses cookies to preserve cart and session state. The presence of these cookies is an important signal for bypassing the shared page cache. The cookies most commonly considered are woocommerce_items_in_cart, woocommerce_cart_hash, and wp_woocommerce_session_.
If at least one of them is present, the safe approach is not to deliver a shared cached HTML response. The server can pass the request to WordPress for dynamic generation or use a separate, properly isolated cache variation. For most stores, bypassing the cache is simpler and more reliable.
Cookie names may be supplemented or changed by the theme, payment modules, membership plugins, and custom integrations. Therefore, the three cookies listed above should not be treated as universal: check the actual Set-Cookie headers and the documentation for the installed extensions.
- woocommerce_items_in_cart — indicates that the cart contains products.
- woocommerce_cart_hash — identifies changes to the cart state.
- wp_woocommerce_session_ — the WooCommerce session cookie.
- For logged-in users, the WordPress login cookie, including wordpress_logged_in_, is an additional signal.
Example of Bypass Logic in Nginx
The following is only an illustrative example. Variable names, directive order, and the way fastcgi_cache is connected depend on the server configuration. Check the syntax before applying it, and do not insert this fragment without adapting it to your environment.
map $http_cookie $skip_woocommerce_cache {
default 0;
~*"woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session_|wordpress_logged_in_" 1;
}
map $request_uri $skip_woocommerce_path {
default 0;
~^/cart/ 1;
~^/checkout/ 1;
~^/my-account/ 1;
}
# У правилах кешу використовуйте обидва прапорці:
# не читати та не зберігати кеш, якщо будь-який із них дорівнює 1.
wc-ajax Requests and Dynamic Fragments
WooCommerce and its extensions can update the cart without fully reloading the page. They use AJAX requests for this, including URLs with the wc-ajax parameter. The response often depends on the current user’s cookies, so it must not be stored as a shared response for everyone.
At the server and CDN levels, create a rule that prevents caching requests containing wc-ajax in the query string. Also check other AJAX endpoints, REST requests, and routes added by installed plugins. Not every dynamic request uses the same name.
Caching JavaScript files is not itself a problem: static scripts can usually be cached for a long time. The danger lies in caching their personalized responses or the HTML that the scripts retrieve from the server.
- Exclude URLs containing wc-ajax from the cache.
- Make sure the CDN does not cache AJAX responses with a 200 status.
- Check requests after adding a product, changing its quantity, removing it, and applying a coupon.
- Do not disable all JavaScript merely because of a caching issue—fix the response-storage rules first.
How to Configure Caching for Logged-In Users
A logged-in user should almost always receive a dynamic response. Their page may contain a name, orders, address, access level, or other data that must not be placed in a shared cache. For this reason, requests with the WordPress authentication cookie are generally excluded from the page cache entirely.
The same applies to roles with extended capabilities, including store managers, partners, members of private clubs, and users with personalized prices. Even if a page looks public on the surface, its response may depend on the account.
An object cache, such as Redis or Memcached, is not a replacement for a page cache and must not mix data from different sessions. WordPress and WooCommerce core generally work with cache keys, but custom-code errors or incorrect configuration can create a shared key for personalized data.
- Exclude logged-in users from full-page caching based on the login cookie.
- Do not cache profile, order, address, or personalized-pricing pages.
- Check custom code and plugins that write data to the object cache.
- Do not flush the entire object cache unnecessarily on a production site: this can temporarily increase the load.
What to Purge After Changing the Rules
Changing the configuration does not automatically remove objects that have already been stored. If /cart/ or /checkout/ was previously cached, users may continue receiving the old response until its lifetime expires.
After updating the rules, clear the page cache on the server or in the plugin, the CDN cache, and related reverse-proxy caches. Clear the object cache only when the changes affect objects or query results stored there. After purging, make sure that new responses are not being stored again with incorrect headers.
Check response headers such as X-Cache, Age, Cache-Control, Vary, and your CDN’s service headers. Their names differ, but they help determine whether the response came from a cache and at which level.
- Clear the plugin or reverse-proxy cache.
- Purge the relevant objects in the CDN.
- Clear the object cache if necessary.
- Verify that personalized responses have the correct Cache-Control settings and are not stored again.
A Practical Cache Security Test
Test the store in a clean guest session and in a separate logged-in session. The easiest approach is to use different browsers or private windows, but make sure that the private window does not contain old cookies.
First, open a product page in the first session, add a product to the cart, and go to /cart/. In the other session, open the same URL. It must not display the first user’s products. Repeat the check for checkout and my-account.
Then test cart changes: add a product, change its quantity, remove it, apply a coupon, and return to checkout. Also test logging in, logging out, and reopening the page after clearing cookies.
The test must be performed through the actual domain and CDN, not only locally on the server. The external layer may be the one returning an outdated response.
- A guest cannot see another guest’s cart.
- A logged-in user does not receive guest HTML.
- Cart changes appear after every operation.
- Checkout does not open with old data from another session.
- The headers show no indication of a shared cache for a personalized response.
- After a purge, the first request does not create an unsafe cached variant.
Frequently asked questions
Can the cart page be cached to speed up WooCommerce?
The cart page is generally not cached as shared HTML. Its content depends on the session and cookies. It is safer to cache public product and category pages and static resources while generating the cart dynamically.
Is excluding /cart/ and /checkout/ in the caching plugin enough?
No, not if Nginx, a reverse proxy, or a CDN operates in front of WordPress. Exclusions must be consistent across all levels; otherwise, an external cache may deliver an old personalized response.
What should I do if the store does not use the standard WooCommerce cookies?
Check the browser cookies and request headers after adding a product. The theme or an extension may use custom cookies or sessions. These must also be included in the bypass rules.
Do I need to disable caching across the entire WooCommerce site?
No. Full-page caching can be used safely for public pages if personalized URLs, cookies, logged-in requests, and AJAX responses are excluded. The key is to separate content types correctly rather than caching everything indiscriminately.
Conclusion
Safe WooCommerce caching is not about giving up performance; it is about properly isolating personalized responses. Cart, checkout, and account pages, wc-ajax requests, responses for logged-in users, and requests containing session cookies must bypass the shared page cache.
After configuring the rules, clear all relevant cache layers and test the store in both guest and logged-in modes. If each session sees only its own data while public pages continue to load quickly from the cache, the configuration follows the correct principle.