Apache/MySQL Performance Tuning for High-Traffic PHP CMS on 512MB RAM VPS


2 views

When dealing with 50k+ visits on a resource-constrained VPS running Apache/PHP/MySQL stack, the performance degradation typically stems from multiple compounding factors. Here's how to systematically address them:

# In httpd.conf or apache2.conf
StartServers 2
MinSpareServers 2
MaxSpareServers 5
ServerLimit 50
MaxClients 50
MaxRequestsPerChild 1000
KeepAlive Off
Timeout 30

Key rationale: On a 512MB VPS, you need to balance between accepting connections and leaving room for MySQL. Setting MaxClients too high will cause swapping.

; php.ini adjustments
realpath_cache_size = 256k
realpath_cache_ttl = 3600
opcache.enable=1
opcache.memory_consumption=64
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60

For ExpressionEngine specifically, enable template caching and disable tracking if not needed:

# In config.php
$config['enable_sql_caching'] = 'y';
$config['template_debugging'] = 'n';
$config['save_tmpl_files'] = 'y';
# my.cnf for 512MB system
[mysqld]
key_buffer_size = 32M
query_cache_size = 32M
tmp_table_size = 16M
max_heap_table_size = 16M
innodb_buffer_pool_size = 64M
innodb_log_file_size = 16M
table_open_cache = 400
table_definition_cache = 400

Critical indexes for ExpressionEngine tables:

ALTER TABLE exp_channel_titles ADD INDEX (entry_date);
ALTER TABLE exp_comments ADD INDEX (entry_id);
ALTER TABLE exp_category_posts ADD INDEX (entry_id);

When dealing with extreme traffic spikes, consider these additional measures:

# Replace Apache with Nginx + PHP-FPM
server {
    listen 80;
    server_name example.com;
    
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Essential commands for real-time diagnostics:

# Apache status
apachectl status
# MySQL queries
mysqladmin processlist
# Memory usage
free -m
# Disk I/O
iostat -x 1
# CPU usage
mpstat -P ALL 1

Beyond configuration files:

  1. Enable static caching for high-traffic templates
  2. Minimize template conditionals
  3. Use {embed:save} for reusable components
  4. Disable member tracking if not used

Example template caching:

{exp:channel:entries channel="news" limit="10" dynamic="no" cache="yes" refresh="60"}
  <h3>{title}</h3>
{/exp:channel:entries}

When dealing with a 512MB RAM VPS running ExpressionEngine CMS, we need to make surgical optimizations. The key symptoms (30s+ response times under 50k visits) suggest three main bottlenecks:

# Current Apache MPM settings (check with):
apache2ctl -V | grep -i mpm
# Typical output for low-memory VPS:
Server MPM:     prefork

Switch to event MPM if possible (requires PHP-FPM):

# Install required modules
sudo apt install apache2-mpm-event php-fpm

# Sample /etc/apache2/mods-available/mpm_event.conf

    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      150
    MaxConnectionsPerChild   1000

For ExpressionEngine specifically, configure PHP-FPM pool:

# /etc/php/7.4/fpm/pool.d/www.conf (adjust version)
[www]
pm = dynamic
pm.max_children = 15
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 500
php_admin_value[memory_limit] = 64M

Critical for 512MB systems - this my.cnf works for EE:

# /etc/mysql/my.cnf
[mysqld]
skip-name-resolve
key_buffer_size = 32M
query_cache_size = 16M
tmp_table_size = 16M
max_heap_table_size = 16M
innodb_buffer_pool_size = 64M
innodb_log_file_size = 16M
table_open_cache = 400
thread_cache_size = 8
max_connections = 30

Implement these in config.php:

$config['enable_sql_caching'] = 'y';
$config['disable_all_tracking'] = 'y';
$config['template_debugging'] = 'n';
$config['save_tmpl_files'] = 'y'; // Requires ./templates cache dir
$config['save_tmpl_revisions'] = 'n';
$config['enable_emoticons'] = 'n';

Essential sysctl tweaks:

# /etc/sysctl.conf
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.core.somaxconn = 1024
vm.swappiness = 10
vm.vfs_cache_pressure = 50

Create this bash script to identify bottlenecks:

#!/bin/bash
while true; do
    echo -e "\n$(date)"
    echo "Apache Processes: $(ps aux | grep apache2 | wc -l)"
    echo "PHP-FPM Processes: $(ps aux | grep php-fpm | wc -l)"
    echo "MySQL Processes: $(mysqladmin processlist | wc -l)"
    free -m
    sleep 5
done