A high Time to First Byte (TTFB) is one of the most common performance complaints on DirectAdmin servers — and one of the most misdiagnosed. Sysadmins often start by upgrading hardware when the real fixes are configuration changes that cost nothing. This guide covers every major cause of high TTFB on DirectAdmin, with specific configuration changes for PHP-FPM, OPcache, MySQL, and Redis that routinely cut TTFB from 1–3 seconds down to under 200ms.
What Is TTFB and What Causes It to Be High?
TTFB measures the time from when a browser sends a request to when it receives the first byte of the response. For cached pages, a healthy target is under 200ms. For dynamic pages (WordPress, PHP apps), under 500ms is acceptable; above 1 second means something is wrong at the server level.
The most common causes on DirectAdmin servers:
- PHP-FPM pool misconfiguration — too few workers, wrong process manager settings
- OPcache disabled or under-allocated — PHP recompiles every file on every request
- No object caching (Redis) — WordPress or other CMS making hundreds of database queries per page load
- MySQL/MariaDB not tuned — slow queries, missing indexes, insufficient buffer pool
- Apache with mpm_prefork — each request forks a new process, exhausting memory
- DNS resolution delays —
skip-name-resolvenot set in MySQL
💡 None of these worked? Skip the guesswork.
Get Expert Help →Step 1: Diagnose the Bottleneck Before Optimizing
Don't guess — measure. Start with a baseline TTFB reading and identify where the time is being spent.
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s
Total: %{time_total}s
" https://yourdomain.com
3. Check server load:
top -bn1 | head -5
vmstat 1 5
High CPU (>80%) or high iowait suggests a different problem (MySQL, disk I/O) than high TTFB with low CPU (which points to PHP or caching issues).
tail -50 /var/log/mysql/mysql-slow.log
If the slow query log is full of queries taking 1+ seconds, database optimization is your priority.
Step 2: Switch to PHP-FPM and Tune the Pool
If you're still running PHP as CGI or suPHP, switching to PHP-FPM alone will often halve your TTFB. PHP-FPM keeps PHP processes running between requests instead of spawning a new process each time.
Enable PHP-FPM via CustomBuild:
cd /usr/local/directadmin/custombuild
./build set php1_release 8.2
./build set php1_mode php-fpm
./build php
./build rewrite_confs
Tune the PHP-FPM pool — edit /etc/php/8.2/fpm/pool.d/www.conf (or the per-domain pool file):
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
The right values for pm.max_children depend on your RAM. A rough formula: available RAM / average PHP process size. Check average PHP-FPM process size with:
ps aux | grep php-fpm | awk '{print $6}' | sort -n | tail -5
Values are in KB. Divide available RAM (in KB) by the average process size to get a safe max_children. Restart PHP-FPM after changes: systemctl restart php8.2-fpm
Step 3: Configure PHP OPcache Correctly
OPcache stores compiled PHP bytecode in memory, eliminating the need to parse and compile PHP files on every request. It's included in PHP 5.5+ but its default settings are too conservative for production workloads — especially WordPress sites.
Edit /etc/php/8.2/fpm/conf.d/10-opcache.ini (path varies by PHP version and OS):
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.save_comments=1
opcache.fast_shutdown=1
Key settings explained:
- memory_consumption=256 — The default 128MB is too low for WordPress sites. Raise to 256–512MB depending on your server's available RAM. If OPcache fills up and resets, you'll see TTFB spikes.
- max_accelerated_files=10000 — Set this higher than the number of PHP files across all your sites. Too low and files won't be cached.
- revalidate_freq=60 — How often (in seconds) OPcache checks if files changed. Set to 0 in production for maximum speed; set to 60 if you deploy code changes frequently.
Verify OPcache is active: php -r "print_r(opcache_get_status());" | head -20
Step 4: Add Redis for Object Caching
For WordPress and other database-driven CMS platforms, OPcache handles PHP compilation but not database query results. Redis object caching stores the results of expensive database queries in memory so they don't hit MySQL on every page load.
Install Redis on the server:
apt install redis-server # Debian/Ubuntu
yum install redis # CentOS/AlmaLinux
systemctl enable --now redis
Install the PHP Redis extension:
apt install php8.2-redis
systemctl restart php8.2-fpm
In DirectAdmin, go to User Level → Advanced Features → Redis to configure Redis connections per domain.
For WordPress, install the Redis Object Cache plugin, add to wp-config.php:
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_CACHE', true);
Then activate the plugin from the WordPress dashboard. With Redis active, repeat pages typically load with TTFB under 100ms.
Step 5: Tune MySQL/MariaDB
Database queries are the second biggest cause of TTFB after PHP compilation. Edit /etc/my.cnf or /etc/mysql/my.cnf:
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_type = 0
skip-name-resolve = 1
max_connections = 150
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
Key settings:
- innodb_buffer_pool_size — Set to 60–70% of available RAM if MySQL is the primary service. This is the single most impactful MySQL setting.
- skip-name-resolve — Stops MySQL from doing reverse DNS lookups on every connection. Eliminates significant latency on busy servers.
- query_cache_type=0 — The MySQL query cache causes contention on busy servers and is deprecated in MySQL 8. Disable it.
Restart MySQL: systemctl restart mariadb
Run MySQLTuner for automated recommendations:
wget http://mysqltuner.pl -O mysqltuner.pl
perl mysqltuner.pl
Step 6: Switch from Apache mpm_prefork to mpm_event (If Using Apache)
If you're using Apache as your web server, mpm_prefork (the default on many installations) creates a new process for every request. On busy servers, this exhausts memory and creates queuing delays. Switch to mpm_event, which uses threads:
a2dismod mpm_prefork
a2enmod mpm_event
a2enmod proxy_fcgi setenvif
systemctl restart apache2
Then enable PHP-FPM integration as the PHP handler via CustomBuild as described in Step 2. The combination of Apache mpm_event + PHP-FPM is significantly faster than mpm_prefork + mod_php for multi-tenant hosting.
Step 7: Verify the Improvement
After making the changes above, restart all services and re-measure:
systemctl restart php8.2-fpm mariadb apache2 redis
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s
" https://yourdomain.com
For a second opinion, use Google PageSpeed Insights (which reports TTFB as "Server Response Time") or WebPageTest's waterfall view. A well-configured DirectAdmin server should show:
- Cached pages: TTFB under 150ms
- Uncached WordPress pages: TTFB under 500ms
- Full page load: under 2 seconds on a 5Mbps connection
If TTFB is still high after these changes, the bottleneck is likely disk I/O (check with iostat -x 1 5) or network latency — at which point switching to NVMe storage or moving to a data center closer to your users is the path forward.
For hosting companies managing performance across dozens of DirectAdmin servers, CloudHouse's managed server support handles full performance tuning — PHP-FPM, OPcache, MySQL, Redis, and web server optimization — across your entire fleet.
