Nginx returns ‘This site can’t be reached’ error when processing large datasets

I am managing a PHP 8.2 and Symfony 7-based school management platform hosted on a VPS with 8GB RAM from Hostinger, running Ubuntu and Nginx.

The Issue:
The problem arises when I attempt to generate report cards in bulk or compile global statistics for an entire class.

Specifically:

When generating report cards for a full class of 60 students, the page displays a “This site can’t be reached
enter image description here error after approximately 30 seconds.
This issue also occurs when sending mass notifications to over 1000 parents (e.g., during news announcements). Also, when register mass data in the database (1000+ notifications whend sending news), the same errors occur but in my database, all the data are saved but the “site unavailable” appear.

Observations:

  • When mass notifications are handled in the background using Symfony Messenger, the process works flawlessly, even for 1000+ notifications.
  • If I segment the report card generation (e.g., 10 students at a time), the process completes quickly without errors.
  • On my local development environment (Windows 10 with Apache, 8GB RAM), the same tasks complete successfully, regardless of the data size. Even if the process takes 1 to 10 minutes or more, it ultimately generates the expected results.

Actions Taken So Far:
I have explored potential solutions, including suggestions from ChatGPT, and implemented the following configurations:

  1. Upgrade php limit on php.ini from /etc/php/8.2/fpm/php.ini
  • -memory_limit=-1
  • maximum_time_execution = 3600
  • post_max_size = 100M
  • upload_max_filesize = 100M
  1. Upgrade nginx configuration on /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 1024;
        # multi_accept on;
}

http {
        # Configurations de timeout globales
        proxy_read_timeout 300s;  # Temps d'attente pour les proxys
        fastcgi_read_timeout 300s; # Temps d'attente pour FastCGI
        client_max_body_size 100M;
        client_body_timeout 300s;
        client_header_timeout 300s;
        keepalive_timeout 300s;
        send_timeout 300s;
        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

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

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}


#mail {
#       # See sample authentication script at:
#       # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
#
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}

  1. here is my mysql configuration
#
# The MySQL database server configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# Here is entries for some specific programs
# The following values assume you have at least 32M RAM

[mysqld]
#
# * Basic Settings
#
user            = mysql
# pid-file      = /var/run/mysqld/mysqld.pid
# socket        = /var/run/mysqld/mysqld.sock
# port          = 3306
# datadir       = /var/lib/mysql

# If MySQL is running as a replication slave, this should be
# changed. Ref https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_tmpdir
# tmpdir                = /tmp
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address            = 127.0.0.1
mysqlx-bind-address     = 127.0.0.1

#
# * Fine Tuning
#
#
innodb_buffer_pool_size = 6G
#innodb_log_file_size = 512M
innodb_redo_log_capacity = 1G
innodb_flush_log_at_trx_commit = 2
innodb_io_capacity = 1000

# Memory and performance tuning
key_buffer_size         = 64M
max_allowed_packet      = 128M
thread_stack            = 256K
thread_cache_size       = 8

# Table cache
table_open_cache        = 2000

# Connections
max_connections         = 500
#wait_timeout = 3600
#innodb_lock_wait_timeout = 3600

# Temp tables
tmp_table_size          = 64M
max_heap_table_size     = 64M
# Temp tables
tmp_table_size          = 64M
max_heap_table_size     = 64M

# MyISAM recover options
myisam-recover-options  = BACKUP

#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
#
# Log all queries
# Be aware that this log type is a performance killer.
# general_log_file        = /var/log/mysql/query.log
# general_log             = 1

# Error log - should be very few entries.
log_error = /var/log/mysql/error.log

# Here you can see queries with especially long duration
# slow_query_log          = 1
# slow_query_log_file     = /var/log/mysql/mysql-slow.log
# long_query_time         = 2
# log-queries-not-using-indexes

# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change.
# server-id               = 1
# binlog_expire_logs_seconds = 2592000
max_binlog_size          = 100M
# binlog_do_db            = include_database_name
# binlog_ignore_db        = include_database_name
  1. I have also try this to my PHP-FPM Wokers on /etc/php/8.2/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10

Thank for any help