How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: Fix Nginx ‘recv() failed (104: Connection reset by peer)’ with FastCGI
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Server Management > Fix Nginx ‘recv() failed (104: Connection reset by peer)’ with FastCGI
Server Management

Fix Nginx ‘recv() failed (104: Connection reset by peer)’ with FastCGI

how7o
By how7o
Last updated: May 22, 2026
9 Min Read
Nginx 502 with recv() failed 104 connection reset — PHP-FPM timeout and memory tuning
SHARE

The Nginx error recv() failed (104: Connection reset by peer) means PHP-FPM (your FastCGI upstream) hung up on Nginx mid-response. The visitor sees a 502 Bad Gateway. This isn’t really an Nginx problem — Nginx is just reporting that the upstream went away — so the fix lives on the PHP-FPM side: memory, timeouts, worker recycling, and (occasionally) buffer sizes. This guide walks through the seven settings that fix this 95% of the time, in the order I’d touch them.

Contents
  • TL;DR
  • Why this error happens
  • 1. Restart PHP-FPM first
  • 2. Raise PHP memory_limit
  • 3. Raise max_execution_time
  • 4. Raise Nginx FastCGI timeouts
  • 5. Align keepalive_requests with pm.max_requests
  • 6. Raise the socket timeout (for downloads/uploads)
  • 7. Increase output buffering (rarely needed)
  • When none of those work
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-05-17 on Nginx 1.24+ and PHP 8.2/8.3 FPM. Originally published 2023-02-13, rewritten and updated 2026-05-17.

TL;DR

Restart PHP-FPM, raise its memory limit and execution time, raise Nginx’s FastCGI timeouts to match, and align keepalive_requests with PHP-FPM’s pm.max_requests. Sample values:

# /etc/php/8.3/fpm/php.ini
memory_limit = 512M
max_execution_time = 300
default_socket_timeout = 300
output_buffering = 65535

# /etc/php/8.3/fpm/pool.d/www.conf
pm.max_requests = 600

# /etc/nginx/conf.d/your-site.conf  (inside the location ~ \.php$ block)
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
fastcgi_connect_timeout 300;
keepalive_requests 600;

Why this error happens

The OS-level error 104 is ECONNRESET — “Connection reset by peer.” Nginx opened a FastCGI connection to PHP-FPM, sent the request, started reading the response, and the socket closed before the response was complete. Five things commonly cause that:

  1. PHP-FPM hit its memory limit and the worker was terminated mid-request.
  2. PHP-FPM hit max_execution_time and killed the running request.
  3. Nginx’s FastCGI timeout expired before PHP-FPM finished — Nginx closed the connection from its side.
  4. PHP-FPM worker recycled mid-request because it hit pm.max_requests.
  5. The upstream crashed — a segfault in a PHP extension or the OOM killer reaping the process.

For all five, the resolution path is similar: identify which limit you’re hitting (via PHP-FPM’s slow log and error log), raise it to a realistic value, restart both services.

Nginx recv() failed 104 connection reset by peer — fix flow through PHP-FPM memory, timeouts, worker recycling

1. Restart PHP-FPM first

A simple restart clears stuck workers and any one-off bad state. If the error stops appearing after a restart and doesn’t come back, the root cause was transient (a single crashed worker, a brief upstream hiccup). If it returns within minutes, work through the rest of this list.

sudo systemctl restart php8.3-fpm
# or, on RHEL family:
sudo systemctl restart php-fpm

2. Raise PHP memory_limit

If a request needs more memory than memory_limit allows, PHP terminates the request — which closes the socket and triggers a 104 on Nginx. Default memory_limit is often 128M; for any application doing image processing, exporting CSVs, or anything Eloquent-heavy, 512M is a sane starting point:

# in php.ini (apply server-wide)
memory_limit = 512M

# or per-request, inside the PHP script
ini_set('memory_limit', '512M');

3. Raise max_execution_time

If a single request legitimately needs minutes (think bulk imports, report generation), the default 30-second max_execution_time will kill it mid-flight:

# in php.ini
max_execution_time = 300

# or per-script
ini_set('max_execution_time', '300');

For routes that don’t need long execution, leave the default. Long-running routes should be moved to a queue worker, not handled in-request — but raising the limit buys time while you migrate them.

4. Raise Nginx FastCGI timeouts

If PHP-FPM is configured to allow 300 seconds but Nginx still gives up at 60, Nginx closes the connection and you’ll see 104. Match the two sides:

# in your server block, inside the FastCGI location:
location ~ \.php$ {
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout    300;
    fastcgi_read_timeout    300;
    # ... existing fastcgi_pass + fastcgi_param directives
}

Reload Nginx after editing: sudo nginx -t && sudo systemctl reload nginx.

5. Align keepalive_requests with pm.max_requests

PHP-FPM recycles each worker after pm.max_requests; Nginx reuses each upstream connection for keepalive_requests. If these differ, a worker can recycle during an in-flight request and trigger 104. Match them:

# PHP-FPM pool (e.g. /etc/php/8.3/fpm/pool.d/www.conf)
pm.max_requests = 600

# Nginx server block
keepalive_requests 600;

6. Raise the socket timeout (for downloads/uploads)

For PHP code that opens external sockets (fsockopen, file_get_contents against a URL), the default_socket_timeout default of 60 seconds can cause cascading 104s when the external host is slow:

# php.ini
default_socket_timeout = 300

7. Increase output buffering (rarely needed)

If PHP-FPM streams a large response back through Nginx, small buffers can cause flush-related stalls. The default is usually fine, but if other settings haven’t fixed it, try bumping output_buffering:

# php.ini
output_buffering = 65535

When none of those work

If you’ve raised every limit and the error is still firing, the culprit is almost always an application-level problem — an infinite loop, an N+1 query against a large table, or a PHP extension segfaulting. Two diagnostics:

  • PHP-FPM slow log — enable slowlog = /var/log/php-fpm/www-slow.log and request_slowlog_timeout = 5s in your pool config. Anything that fires the slow log is a candidate.
  • System logs — dmesg | tail shows OOM kills (Out of memory: Killed process … (php-fpm7.4)). If you see those, the box is undersized; either add RAM or trim worker count (pm.max_children).

Frequently asked questions

What does recv() failed (104: Connection reset by peer) mean in Nginx?

Linux error 104 is ECONNRESET — the peer (in this case PHP-FPM, the FastCGI upstream) closed the TCP/Unix socket while Nginx was still reading from it. From Nginx’s perspective, it asked PHP-FPM for a response, PHP-FPM hung up mid-conversation, and Nginx had to bail out and serve the visitor a 502 Bad Gateway. The cause is almost always on the PHP-FPM side: it crashed, timed out, hit a memory limit, or was killed by the OOM killer.

How do I find which request killed PHP-FPM?

Check PHP-FPM’s slow log and error log (usually /var/log/php-fpm/www-error.log and the path set by slowlog in your pool config). Look for entries that line up with the Nginx 502 timestamps. The slow log captures stack traces of requests over request_slowlog_timeout — those are usually the same requests that get killed when the timeout fires.

Will increasing fastcgi_read_timeout mask a real problem?

Yes. Bumping timeouts is a legitimate fix when a single legitimate request honestly needs more than 60 seconds (a heavy import script, a one-off report). It’s a bandage when every page is slow because of an N+1 query or a missing index — those need fixing in the application, not in the proxy. Use the slow log to tell which case you’re in before raising the limits.

Why does pm.max_requests matter?

Each PHP-FPM worker handles pm.max_requests requests, then exits and a fresh worker spawns. That bounds long-lived memory leaks but creates a small window where the worker is restarting and not accepting new connections — which can manifest as a connection reset. Matching keepalive_requests on Nginx to pm.max_requests on PHP-FPM keeps the two sides aligned and reduces resets during recycling.

Could it be a network problem, not PHP-FPM?

Possible, but rare in the typical ‘Nginx and PHP-FPM on the same box’ setup — the socket is local. If Nginx and PHP-FPM are on different hosts (over TCP), check dmesg for NIC errors, run ss -s to look at socket counts, and monitor packet loss between the two. For same-host setups, network is essentially never the cause; look at PHP-FPM.

Related guides

  • How to Install Discourse on AlmaLinux with Docker
  • How to Install Docker on AlmaLinux
  • How to Check if the GD Library Is Installed in PHP

References

Nginx fastcgi directives reference: nginx.org/en/docs/http/ngx_http_fastcgi_module.html. PHP-FPM configuration reference: php.net/manual/en/install.fpm.configuration.php.

TAGGED:configurationNginxperformancephptroubleshooting

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article JavaScript format number with decimals — toFixed, Math.floor, and Intl.NumberFormat How to Format a Number with Decimals in JavaScript
Next Article List network devices on Linux — ip a and nmcli output side by side How to List Network Devices on Linux
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Run Laravel queue workers with Supervisor
How to Run Laravel Queue Workers in Production with Supervisor
May 23, 2026
Nginx as a reverse proxy for a Node.js app on Ubuntu
How to Set Up Nginx as a Reverse Proxy for Node.js on Ubuntu
May 23, 2026
Install and configure Redis on Ubuntu for Laravel and WordPress
How to Install and Configure Redis on Ubuntu (for Laravel & WordPress)
May 23, 2026
Harden a fresh Ubuntu VPS with UFW, Fail2Ban, and SSH key auth
How to Harden a Fresh Ubuntu VPS: UFW + Fail2Ban + SSH Key Auth
May 23, 2026
Set up Let's Encrypt SSL with Certbot on Ubuntu
How to Set Up Let’s Encrypt SSL with Certbot on Ubuntu (Apache & Nginx)
May 23, 2026

You Might Also Like

WordPress wpdb get_results returns multiple rows
Web Development

How to Get Multiple Rows with $wpdb in WordPress

5 Min Read
CyberPanel too many redirects Laravel error fixed by restarting LiteSpeed
Server Management

Fix CyberPanel Too Many Redirects (ERR_TOO_MANY_REDIRECTS) for Laravel Subdomain

7 Min Read
WordPress login user programmatically — wp_set_current_user plus wp_set_auth_cookie
Web Development

How to Login a User Programmatically in WordPress

8 Min Read
WordPress get current category ID — three methods by page context
Web Development

How to Get the Current Category ID in WordPress

7 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?