tuned-adm on CentOS Stream 9: Optimize Web Server, Database, and HPC Performance with the Right Profile

CentOS tutorial - IT technology blog
CentOS tutorial - IT technology blog

Why Is Your Server Stable but Still Slow?

I ran into this situation once: a freshly set up CentOS server with plenty of RAM to spare, CPU usage under 30%, yet application response times were still higher than expected. It wasn’t the code. It wasn’t the network. After debugging for a while, I discovered the kernel was running in power-saving mode, the I/O scheduler wasn’t suited to the workload, and dozens of other small parameters the kernel never automatically adjusts based on the type of work running.

That’s when I started looking into tuned-adm — a built-in tool on RHEL/CentOS that automatically tunes the system using “profiles” matched to specific workload types.

Three Ways to Tune Linux Performance — and the Trade-offs of Each

There are three approaches to Linux performance tuning. I’ll walk through all three so you can see why tuned-adm is the most practical choice:

Approach 1: Manual Tuning via sysctl and Kernel Parameters

You manually edit /etc/sysctl.conf, set the CPU governor, tweak the I/O scheduler, and so on. Pros: complete control over every parameter. Cons: requires deep knowledge of kernel internals, takes hours of research, and a single small mistake can destabilize the entire server.

Approach 2: Home-grown Scripts Accumulated Over the Years

Many sysadmins have a collection of “magic” scripts they apply whenever setting up a new server. Sounds good in theory, but in practice: the scripts are rarely well-tested, don’t keep up with new kernel releases, and nobody remembers why a particular line is there. When something breaks, debugging becomes nearly impossible.

Approach 3: Using tuned-adm with Built-in Profiles

Red Hat recommends this approach for production — and for good reason. Profiles are thoroughly tested by Red Hat engineers, well-documented, and updated with each major RHEL/CentOS release. No parameter memorization, no risk of getting it wrong — just pick the right profile for your workload.

If you don’t have time to dive deep into kernel tuning, tuned-adm is the most sensible starting point. Need to fine-tune further? You can absolutely create a custom profile that inherits from a built-in one — I’ll cover that later.

Installing and Checking tuned-adm

On CentOS Stream 9, tuned is usually pre-installed. If not:

sudo dnf install tuned -y
sudo systemctl enable --now tuned

Check the current profile and view the list of available profiles:

# Show the currently active profile
tuned-adm active

# List all available profiles
tuned-adm list

The output is usually balanced or virtual-guest if you’re running inside a VM — neither is optimal for a production server.

Understanding Each Profile and When to Use It

throughput-performance — For Database Servers

Best suited for: MySQL, PostgreSQL, MariaDB, batch processing, data pipelines.

For database servers, this is the first profile to try. It completely disables power saving, sets the CPU governor to performance, and fine-tunes the I/O scheduler. The CPU never throttles down, and disk read/write becomes noticeably more consistent. The only trade-off is higher power consumption — not a concern for physical servers in a datacenter.

sudo tuned-adm profile throughput-performance

# Check if CPU governor has switched to performance
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# Output: performance

# Check I/O scheduler
cat /sys/block/sda/queue/scheduler
# Usually switches to [mq-deadline] or [none] depending on disk type

network-throughput — For Web Servers

Best suited for: Nginx, Apache, CDN nodes, reverse proxies handling many simultaneous connections.

Increases network buffer sizes (receive/send), and tunes the TCP stack to handle more simultaneous connections. This is the profile I apply first on any web server.

sudo tuned-adm profile network-throughput

# Verify that network buffer has increased
sysctl net.core.rmem_max
sysctl net.core.wmem_max
# Value increases from ~212992 to ~134217728 (roughly 600x)

network-latency — For API Servers and Load Balancers

Best suited for: API gateways, load balancers, microservices requiring low per-request response times.

The opposite of network-throughput — this profile shrinks TCP buffers to prioritize latency over throughput. Ideal when you have many small, high-frequency requests rather than fewer large payloads.

sudo tuned-adm profile network-latency

latency-performance — For Real-time Applications

Best suited for: Trading systems, game servers, applications requiring extremely low and consistent response times.

Completely disables CPU C-states (CPU idle states), ensuring the CPU never “sleeps” even when there are no tasks. The result: extremely stable response times with no latency spikes caused by the CPU waking from a sleep state. The main downside: the CPU always runs at full power consumption even when idle.

sudo tuned-adm profile latency-performance

hpc-compute — For HPC and Machine Learning

Best suited for: Machine learning training, video encoding, simulations, scientific computing.

The most aggressive profile — CPU is locked in performance mode, NUMA topology is optimized, and swap is minimized to prevent memory thrashing. If you’re running compute-heavy workloads, this is the first profile to try.

sudo tuned-adm profile hpc-compute

# Verify swap has been reduced (vm.swappiness)
sysctl vm.swappiness
# Output: 10 (instead of the default 60)

Choosing the Right Profile for Your Use Case

Quick reference table:

  • Nginx/Apache web servernetwork-throughput
  • MySQL/PostgreSQL databasethroughput-performance
  • API gateway/load balancernetwork-latency
  • Real-time / low-latency applatency-performance
  • ML training / HPChpc-compute
  • Cloud VMvirtual-guest (use as base, then override)

Creating a Custom Profile When Built-ins Aren’t Enough

I once had a case where a server ran both a database and a web server simultaneously (a small startup’s monolithic setup). No single profile fit perfectly. The solution: create a custom profile that inherits from throughput-performance and overrides a few network parameters on top.

# Create directory for the new profile
sudo mkdir /etc/tuned/my-webdb

# Create the config file
sudo nano /etc/tuned/my-webdb/tuned.conf

Contents of tuned.conf:

[main]
summary=Custom profile for web+database combo server
include=throughput-performance

[sysctl]
# Override: increase network buffers like network-throughput
net.core.rmem_max=134217728
net.core.wmem_max=134217728
net.ipv4.tcp_rmem=4096 87380 134217728
net.ipv4.tcp_wmem=4096 65536 134217728
# Lower swappiness for database workloads
vm.swappiness=10
# Apply the custom profile
sudo tuned-adm profile my-webdb

# Confirm
tuned-adm active

Benchmarking to See the Difference

Once you’ve switched profiles, benchmark before and after to get concrete numbers:

# Web server: use wrk (install if not already)
sudo dnf install wrk -y
wrk -t4 -c100 -d30s http://localhost/

# Disk I/O: use fio
sudo dnf install fio -y
fio --name=randread --ioengine=libaio --iodepth=16 \
    --rw=randread --bs=4k --size=1G --numjobs=4 \
    --runtime=30 --group_reporting

Based on my own measurements: database servers typically see a 15–25% reduction in query time after switching to throughput-performance, most noticeably with random I/O workloads. Web servers tested with wrk under network-throughput generally see around 20% throughput improvement.

Key Things to Remember in Production

My team has migrated several servers from CentOS 7 to AlmaLinux. Every single time, setting the tuned profile is one of the first things done on day one — not deferred. If you’re building out a new server from scratch, it fits naturally into the essential post-installation steps for CentOS Stream 9. Saying “I’ll do it when I have time” means it never gets done.

  • Profiles persist across reboots only when the tuned service is enabled. Always run: systemctl enable tuned
  • Switching profiles does not require a reboot — tuned applies changes immediately
  • The default profile after installation is balanced — not optimal for production
  • On cloud VMs (AWS, GCP, Azure), the base profile should be virtual-guest before adding any overrides
# Quick check if tuned is running
systemctl status tuned

# View logs if there's an issue
journalctl -u tuned -n 50

# View details of what a profile changes
tuned-adm profile-info throughput-performance

tuned-adm isn’t the answer to every performance problem, but it is the first step you should take with any production server. It takes just 5 minutes to set up and benchmark — in return, your system runs tuned to its actual workload, not the generic defaults designed for an office laptop.

Share: