Nginx 502 Bad Gateway on WooCommerce — When Response Headers Outgrow the Buffer

· 8 min read

The Checkout That Only Broke for Logged-In Customers

A client running a busy WooCommerce store — multiple payment gateways, several hundred products, a decent volume of daily orders — reported that their checkout page was throwing 502 Bad Gateway errors. But only sometimes. And only for some customers.

Guest checkout worked fine. Product pages loaded fine. The homepage was fast. But logged-in customers hitting /checkout/ or /my-account/ would get a blank 502 roughly one in four page loads. The kind of intermittent failure that makes you question everything.

I SSH'd in and checked the nginx error log first:

grep "502" /var/log/nginx/error.log | tail -20

Every 502 had the same companion message:

upstream sent too big header while reading response header from upstream

That single line told me exactly what was happening. The PHP response headers — specifically the Set-Cookie headers — were exceeding nginx's buffer size for reading upstream responses. Nginx couldn't fit them into memory, so it gave up and returned a 502.

Why WooCommerce Sites Hit This More Than Anything Else

The default fastcgi_buffer_size in nginx is 4K on most Linux distributions (8K on some). That's the buffer nginx allocates for reading the first part of the response from PHP-FPM — which is entirely HTTP headers before the body starts.

For a simple WordPress blog, response headers might total 800 bytes. For a WooCommerce store with multiple payment gateways, analytics, and GDPR consent, they can easily hit 12KB or more.

I measured the actual header size on this store by exporting a logged-in session cookie from the browser (DevTools > Application > Cookies, then pass it via -b):

curl -sI -b "cookie_jar_exported_from_browser.txt" https://example.com/checkout/ 2>&1 | wc -c

The response headers totalled 14,238 bytes. Nearly 3.5 times the 4K buffer.

I counted the Set-Cookie headers to understand what was contributing:

curl -v https://example.com/checkout/ 2>&1 | grep -ic 'set-cookie'

Eighteen. Eighteen separate Set-Cookie headers on a single response. Here's what was generating them:

  • WordPress authentication — 4 cookies (wordpress_logged_in_*, wordpress_sec_*, and two auth cookies)
  • WooCommerce session — 2 cookies (wp_woocommerce_session_*, woocommerce_cart_hash)
  • Stripe payment gateway — 2 cookies for fraud detection
  • PayPal PPCP — 1 cookie for session state
  • Klarna — 2 cookies for the checkout widget
  • CookieYes GDPR plugin — 3 cookies storing granular consent preferences
  • Google Tag Manager server-side — 2 cookies
  • Query Monitor (active because the client was a logged-in admin) — 2 cookies

Each individual cookie is small. But multiply eighteen cookies by their name, value, path, domain, expiry, SameSite attribute, and Secure flag, and you're well past 4K. Logged-in administrators with Query Monitor active were the worst hit because they had the most cookies. Guest users with fewer cookies stayed under the buffer most of the time — explaining the intermittent pattern.

The Immediate Fix — Increase FastCGI Buffers

The fastest way to stop the 502s is to give nginx more room. I added these directives to the site's nginx server block:

fastcgi_buffer_size 64k;
fastcgi_buffers 16 32k;
fastcgi_busy_buffers_size 64k;

What each one does:

  • fastcgi_buffer_size — the buffer for reading the first part of the response (headers). This is the one causing the 502.
  • fastcgi_buffers — the number and size of buffers for reading the response body. Not directly related to the 502, but undersized body buffers cause nginx to spool to disk, which hurts performance.
  • fastcgi_busy_buffers_size — how much of the buffer can be busy sending to the client while still receiving from upstream.

Before applying, I tested the configuration:

nginx -t && nginx -s reload

On this server (HestiaCP-managed), the config needed to go in the right place to survive panel rebuilds. HestiaCP regenerates nginx configs from templates, so editing /etc/nginx/conf.d/domains/example.com.conf directly gets overwritten on the next panel operation. Instead, the directives need to go in the custom nginx template:

/usr/local/hestia/data/templates/web/nginx/

For CloudPanel, the equivalent is the custom vhost configuration under Sites > Vhost. For standalone nginx without a panel, /etc/nginx/conf.d/ or within the server block in /etc/nginx/sites-available/ works.

After reload, I verified:

curl -sI https://example.com/checkout/ | head -1
HTTP/1.1 200 OK

The 502s stopped immediately.

The Proper Fix — Reduce the Cookie Surface

Increasing buffer sizes is a sticking plaster. The real problem is that 14KB of headers on every response is wasteful. Every one of those cookies gets sent back by the browser on every subsequent request too, adding latency — especially on mobile connections where upload bandwidth is limited.

I audited which plugins were setting cookies:

grep -rn "setcookie\|set_cookie\|Set-Cookie" wp-content/plugins/ --include="*.php" | \
  grep -v "vendor/" | cut -d: -f1 | sort -u

This revealed that three of the eighteen cookies came from payment gateways the client had installed but never activated. Klarna had been trialled months earlier and deactivated but not removed. Its plugin still registered cookie hooks on every page load. I removed the unused gateway plugins entirely — not just deactivated, but deleted.

Next, I checked the GDPR consent plugin. CookieYes was storing individual consent categories in separate cookies rather than a single consolidated cookie. Switching from "per-category cookies" to "single consent cookie" mode in the plugin settings dropped three cookies down to one.

The WooCommerce session cookie was another target. WooCommerce's default WC_Session_Handler stores session data in the wp_woocommerce_sessions database table, and the browser cookie (wp_woocommerce_session_*) is normally just a small customer ID, expiry, and hash — well under 200 bytes. But this store had a third-party "session manager" plugin overriding the default handler and stuffing serialised cart data into the cookie itself, bloating it to over 2KB. Removing that plugin and letting WooCommerce use its default database-backed session handler brought the session cookie back to its expected small size.

After these changes, the response header size dropped from 14,238 bytes to 4,820 bytes — well within even the default 8K buffer on most distributions. But I kept the increased buffer configuration in place as a safety margin.

The Request-Side Mirror — 400 Bad Request

There's a related failure that hits from the other direction. If cookies accumulate over time — old sessions that never expired, plugins that set cookies but never clean them up — the browser sends increasingly large request headers. When the request headers exceed nginx's large_client_header_buffers limit, you get a different error entirely:

400 Bad Request — Request Header Or Cookie Too Large

I've seen this on stores where customers bookmark the checkout and return weeks later with stale WooCommerce session cookies still attached. The fix is the same principle — audit and reduce cookies — but you also need to ensure large_client_header_buffers is sized appropriately:

large_client_header_buffers 4 32k;

The two errors — 502 from oversized response headers and 400 from oversized request headers — are the same underlying problem viewed from opposite ends. Fix the cookie bloat and both go away.

Prevention

On every nginx + WooCommerce server I set up now, I include the FastCGI buffer directives from the start. The 4K default was never designed for applications that set a dozen cookies per response.

I also add a header size check to my monitoring. In Uptime Kuma, a keyword monitor that hits the checkout page with an authenticated session cookie and alerts on anything other than a 200 catches this before customers do. Catching a 502 at 3 AM is better than discovering it from a complaint at 10 AM.

If your WooCommerce store is throwing intermittent 502s that only affect certain users, check the nginx error log for upstream sent too big header. The fix takes five minutes — but understanding why it happened prevents the next round of cookie bloat from bringing it back.


I deal with nginx and WooCommerce issues like this across the 70+ sites I manage. If you'd rather not debug 502s at midnight, take a look at my maintenance plans — or read more about how I handle WooCommerce maintenance and server management.

Stop Firefighting. Start Maintaining.

I manage 70+ WordPress sites for agencies and businesses. Whether you need ongoing maintenance, emergency support, or a one-off performance fix — I can help.

View Maintenance Plans Get in Touch

Get in Touch to Discuss Your Needs