Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kayintveen's avatar

Local nginx setup initial load super slow

Hi All,

I've been struggling with my local setup for a while now. And finally took the time to investigate deeper but was not able to find out whats wrong.

I have a local nginx setup build with homebrew with PHP running also on homebrew not on a socket but on a port with php-fpm (currently only running [email protected])

Some how the initial load on my local test domains take somewhere between 5 and 10 seconds in the stall/blocked (blocked for firefox and stalled in chrome) state. The second / third page I visit the only thing that could be slow is the waiting state (for like 3 sec for a uncached page) which makes sens on heavy pages.

Install machine Macbook pro M1 Max with Sonoma OS. nginx version: nginx/1.25.3 PHP 8.1.27 (xdebug off, opcache on with timestamp validation for local development)

This issue is on both Laravel, magento2, wordpress and drupal projects.

example of a basic project

server {
  listen			80;
  server_name		projectname.test;

  add_header X-Frame-Options "SAMEORIGIN";
  add_header X-XSS-Protection "1; mode=block";
  add_header X-Content-Type-Options "nosniff";

  root /Users/username/sites/projectname;
  index index.php

  gzip on;
  gzip_vary on;
  gzip_disable "msie6";
  gzip_comp_level 6;
  gzip_min_length 1100;
  gzip_buffers 16 8k;
  gzip_proxied any;
  gzip_types
  text/plain
  text/css
  text/js
  text/xml
  text/javascript
  application/javascript
  application/x-javascript
  application/json
  application/xml
  application/xml+rss;


  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

  error_page 404 /index.php;

  location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9081;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    include fastcgi_params;
  }

  location ~ /\.(?!well-known).* {
  deny all;
  }

}

and the basic nginx.conf looks like this

worker_processes  auto;

error_log /Users/kayintveen/Logs/nginx_error.log info;

events {
    worker_connections  1024;
}

http {
    server_names_hash_bucket_size 512;

    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    types_hash_max_size 2048;
    client_max_body_size 512M;

    gzip  on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_vary on;
    gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/rss+xml
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/svg+xml
    image/x-icon
    text/css
    text/plain
    text/x-component;

   include servers/*;
}

and this is my php.ini (xdebug is most of the time turned off by commenting it out)

[xdebug]
zend_extension="xdebug.so"
xdebug.mode=debug
xdebug.client_port=9003
xdebug.idekey=PHPSTORM
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = Off
zend.exception_string_param_max_len = 15
expose_php = On
max_execution_time = 300
max_input_time = 60
memory_limit = 10G
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
realpath_cache_size = 4096k
realpath_cache_ttl = 600
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = Off
post_max_size = 50M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
extension_dir = "/opt/homebrew/lib/php/pecl/20210902"
enable_dl = Off
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
[filter]
[iconv]
[imap]
[intl]
[sqlite3]
[Pcre]
[Pdo]
[Pdo_mysql]
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = On
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = 1
[COM]
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[dba]
[opcache]
opcache.enable=1
opcache.enable_cli=1
#opcache.jit_buffer_size=500000000
#opcache.jit=1235
opcache.revalidate_freq=0
opcache.validate_timestamps=1
opcache.max_accelerated_files=10000
opcache.memory_consumption=192
opcache.max_wasted_percentage=10
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1
[curl]
[openssl]
openssl.cafile = "/opt/homebrew/etc/openssl@3/cert.pem"
openssl.capath = "/opt/homebrew/etc/openssl@3/certs"
[ffi]

PHP fpm www.conf

[www]
user = username
group = staff
listen = 127.0.0.1:9081

pm = dynamic
pm.max_children = 100
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 1s
pm.max_requests = 500

so in basis everything runs fine. but I noticed Laravel herd ran so much quicker. felt so much better but I had a lot of issues as Herd runs PHP from the application support directory. This gave issues with for example magerun helper tools and it just was too much magic I would like more control.

anyone a idea how to improve I checked all configurations of herd as reference.

1 like
3 replies
LaryAI's avatar
Level 58

It seems like you've done a thorough job of setting up your local environment and have considered many of the common performance bottlenecks. However, since you're experiencing slow initial load times across multiple applications (Laravel, Magento, WordPress, Drupal), it suggests that the issue might be related to the common elements in your stack, such as Nginx or PHP-FPM.

Here are a few suggestions that might help you improve the initial load time:

  1. DNS Resolution: Ensure that the domain names you are using (like projectname.test) are resolved quickly. Since these are local, you might want to map them directly in your /etc/hosts file to 127.0.0.1 to avoid any potential DNS resolution delays.

  2. Nginx Configuration: Review your Nginx configuration for any potential misconfigurations that could cause delays. For example, ensure that the server_name directive matches your test domain exactly, and there are no conflicts.

  3. PHP-FPM Configuration: The slow initial response might be due to PHP-FPM's process management. Since you're using a dynamic process manager, it's possible that on the first request, PHP-FPM has to spin up a new process to handle it. You can try changing the pm setting to static and setting a lower pm.max_children to see if that helps with the initial load time.

  4. Opcache: You have opcache.validate_timestamps=1, which means that on each request, PHP will check for updated scripts. This can slow down performance, especially on the first load. For local development, you might want to set opcache.validate_timestamps=0 and manually reset the cache when you update your PHP files.

  5. Xdebug: Even though you mentioned that Xdebug is turned off most of the time, ensure that it is indeed not running as it can significantly slow down requests.

  6. Filesystem Performance: Since you're on a Mac with an M1 chip, there might be filesystem performance issues, especially if you're using Docker or any form of virtualization. Ensure that your projects are located on a native filesystem and not within a virtualized environment.

  7. Network Configuration: If PHP-FPM is listening on a network port, there might be some network latency, even if it's just 127.0.0.1. You can try switching to Unix sockets for communication between Nginx and PHP-FPM to see if that reduces the initial load time.

  8. Error Logs: Check both Nginx and PHP-FPM error logs for any warnings or errors that might indicate what's causing the delay.

  9. Tracing the Request: Use tools like curl with the -v option to trace the request and response headers and see where the delay might be occurring.

  10. Profiler: Use a profiling tool to get more insight into what's happening during the request lifecycle. Tools like Tideways, Blackfire, or even the built-in PHP profiler can help you pinpoint where the slowdown is occurring.

Here's an example of how you might adjust your PHP-FPM pool configuration to use a static number of child processes:

[www]
user = username
group = staff
listen = /var/run/php-fpm.sock

listen.owner = username
listen.group = staff
listen.mode = 0660

pm = static
pm.max_children = 5

And the corresponding Nginx configuration to use the Unix socket:

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    include fastcgi_params;
}

Remember to restart both Nginx and PHP-FPM after making changes to their configurations. If none of these suggestions resolve the issue, you may need to perform more in-depth profiling to understand where the bottleneck is occurring.

kayintveen's avatar

Some extra info. First request

Salled: 7.20s DNS lookup: 42us Initial connection: 17.15ms SSL: 16ms request sent: 0.56ms waiting for server response: 331ms (simple HTML response not big tasks) content download 1.02ms

Second request to a second uncached page Salled: 0.86ms DNS lookup: (not in timing) Initial connection: (not in timing) SSL: (not in timing) request sent: 0.31ms waiting for server response: 1.7s (this is to be expected its a heavier page) content download 0.53

kayintveen's avatar

I increased the keepalive a bit and that did help but waiting 5min I have the same issue. so seems to be the setup of the connection that is the cause.

Please or to participate in this conversation.