Skip to content

Multi-PHP & WooCommerce Cache

Two related scenarios that come up together often enough to cover in one place: running several PHP versions side-by-side on one box, and getting FastCGI Cache right on a WooCommerce store (where getting it wrong shows up as "customers seeing each other's carts," which is exactly as bad as it sounds — though see below for why AidiPanel's default rules already prevent this).

Running multiple PHP versions on one server

A common real scenario: you host a legacy client site that's stuck on PHP 7.4-era code next to a fresh WordPress build you want on 8.4. AidiPanel handles this natively, since every site already gets its own PHP-FPM pool — there's no shared-pool mode to work around.

bash
# See what's installed vs. just available
aidipanel php:list

# Install the version the legacy site needs
aidipanel php:install --version 8.2

# Point each site at its own version independently
aidipanel php:version --domain legacy-client.com --set 8.2
aidipanel php:version --domain new-build.com --set 8.4

That's genuinely the whole procedure — there's no extra step to "isolate" them from each other since the isolation already exists by default. Each site's Nginx vhost points fastcgi_pass at that site's own versioned socket (php8.2-fpm-legacyclient.sock vs. php8.4-fpm-newbuild.sock), so restarting one version's FPM service, or that specific site's pool, never touches the other.

Testing a PHP upgrade safely

Before switching a live site's PHP version, install the target version and test with a temporary subdomain or staging copy first if the codebase is old or uses third-party plugins — see PHP Management for the switch command, and check storage/logs or the site's error log immediately after switching either way.

FastCGI Cache on WooCommerce

WooCommerce is more cache-sensitive than a plain WordPress blog because it mixes genuinely static content (product pages, category listings) with per-visitor dynamic content (cart contents, "you're logged in," personalized pricing) on the same URLs. Caching the wrong response to the wrong visitor is the classic WooCommerce caching failure mode — but it's worth understanding exactly how AidiPanel avoids it before you flip the switch.

Why this is safe by default

AidiPanel's cache exclusion rules (FastCGI Cache → What never gets cached) already bypass caching for:

  • any request carrying a woocommerce_items_in_cart cookie
  • any request carrying a wordpress_logged_in_* cookie (i.e., any logged-in visitor, including logged-in customers)
  • the cart, checkout, and my-account URLs specifically
  • any request with a query string, and all POST requests

In practice this means: a page only gets cached and served from cache to fully anonymous, cart-empty visitors. The moment someone adds something to their cart, WooCommerce sets that cookie, and every subsequent request from them bypasses cache automatically — they always see their own live cart, never a cached snapshot of someone else's.

Turning it on

bash
aidipanel cache:enable --domain shop.example.com --install-nginx-helper --install-redis-plugin

Both helper flags matter more here than on a plain blog:

  • --install-nginx-helper — purges cache automatically when product content changes (price edits, stock updates, new posts)
  • --install-redis-plugin — WooCommerce runs many more database queries per pageview than plain WordPress (cart totals, stock checks, related products); Redis object caching speeds up exactly the requests that FastCGI Cache can't help with, since logged-in/cart-bearing traffic always bypasses the page cache

What to verify after enabling

Don't just trust the config — check it, especially the first time:

bash
# 1. Anonymous visit to a product page — should be cacheable
curl -I https://shop.example.com/product/example-product/
# X-FastCGI-Cache: MISS (first time), then HIT on a second request

# 2. Simulate a logged-in visitor — should ALWAYS bypass
curl -sI -b "wordpress_logged_in_test=1" https://shop.example.com/ | grep X-FastCGI-Cache
# X-FastCGI-Cache: BYPASS

# 3. Cart and checkout should always bypass regardless of cookies
curl -I https://shop.example.com/cart/
curl -I https://shop.example.com/checkout/
# Both: X-FastCGI-Cache: BYPASS

If step 2 or 3 ever shows HIT instead of BYPASS, stop and don't leave cache enabled — that would mean a logged-in or cart-bearing response could theoretically be served to someone else. This shouldn't happen with AidiPanel's default rules, but it's exactly the kind of thing worth confirming yourself rather than assuming, since it's the one WooCommerce-caching mistake serious enough to matter. If you ever see this, disable cache immediately (aidipanel cache:disable --domain shop.example.com) and treat it as a bug to report.

Excluding additional dynamic pages

If you use plugins that add their own dynamic, per-user pages outside the standard cart/checkout/account paths (a wishlist plugin, a custom "my orders" page, a membership portal), those need their own bypass rule — they won't be caught by the default WooCommerce cookie patterns unless they also set one of the cookies above.

Add a rule to the site's Nginx config (via the panel's editor, which validates and rolls back automatically — see Site Management → Editing Nginx config):

nginx
if ($request_uri ~* "(/wishlist|/my-orders|/member-portal)") {
    set $skip_cache 1;
}

Cache duration for a store

Product pages change less often than you'd think (mostly stock/price), while the homepage or category listings might be closer to real-time if you run flash sales. Consider a shorter TTL than the WordPress default of 1 hour if pricing changes frequently:

nginx
# Example: 15 minutes instead of the default 1 hour
fastcgi_cache_valid 200 301 302 15m;

See FastCGI Cache → Adjusting cache duration for where this line lives and how to reload after editing.

Putting it together

A realistic setup for a store running alongside an older site:

bash
# Legacy site stays on its known-good PHP version
aidipanel php:version --domain legacy-client.com --set 8.2

# Store gets a modern PHP version plus full caching stack
aidipanel php:version --domain shop.example.com --set 8.4
aidipanel cache:enable --domain shop.example.com --install-nginx-helper --install-redis-plugin

# If the store gets busy enough that its cache is evicting fast, give it headroom
aidipanel cache:zone --action enable --domain shop.example.com --keys 64m --max-size 5g

Each of these is independent per site — none of it requires touching or restarting anything on the neighboring site.