How a Magento reindex can run without slowing down the web server
A reindex, a backup, or a large cron job competes directly with PHP-FPM workers for the same CPU time and the same disk access without deliberate priorities. nice and ionice allow deliberately deprioritizing background jobs, so they only get resources when the web server does not currently need them.
Table of Contents
- 1. Why background jobs can slow down web requests
- 2. How nice values influence the CFS scheduler
- 3. Applying nice and renice in practice
- 4. ionice classes: realtime, best-effort, and idle
- 5. Using ionice for backups and reindexing
- 6. Combining nice and ionice for Magento cron
- 7. Setting priorities permanently via systemd units
- 8. Recognizing the limits of nice and ionice
- 9. nice and ionice values compared
- 10. Summary
- 11. FAQ
1. Why background jobs can slow down web requests
On a typical Magento server, PHP-FPM workers, MySQL, Redis, and regular cron jobs such as reindexing, price rules, or cache warming all run side by side on the same hardware. Without deliberate priority control, the Linux kernel treats all these processes as equal by default and splits CPU time and disk access according to a fair but not context-aware principle. A compute-intensive reindex job can therefore claim just as much CPU time as a PHP-FPM worker currently answering a customer request.
The result: during a running cron job, the shop's response times rise noticeably, even though the server's overall CPU utilization might still have capacity. This is exactly where nice and ionice come in. nice controls a process's CPU priority relative to the scheduler, ionice analogously controls priority when accessing block devices. Together they allow deliberately deprioritizing background jobs without blocking them entirely.
This article shows how nice values influence the scheduler, which ionice classes are available, and how both mechanisms are combined for Magento cron jobs, reindexing, and backups so that production web requests are always treated with priority.
2. How nice values influence the CFS scheduler
The Linux kernel's Completely Fair Scheduler (CFS) distributes CPU time by default according to a fairness principle, but additionally weights each process by its nice value. The range goes from minus 20, the highest priority, to plus 19, the lowest priority, with 0 as the default. A higher nice value paradoxically means lower priority, a process is figuratively "nicer" to other processes and yields CPU to them.
This weighting is relative, not absolute: a process with a nice value of 19 is not completely starved, but still receives CPU time as soon as no higher-priority processes have anything to do. For a Magento cron job, a high nice value therefore means it keeps running to completion, but is automatically deferred whenever PHP-FPM workers simultaneously need CPU time.
3. Applying nice and renice in practice
A new process can be started directly with the nice command and the desired priority value. For already-running processes, renice changes the nice value retroactively without needing to restart the process, which is particularly practical for long-running reindex jobs already in the middle of execution when a performance issue is noticed.
It is important to know that a normal, unprivileged user may only increase their own nice value, i.e. lower the priority of their process, but not raise it. Root or a user with the corresponding capability, however, can assign negative nice values as well, to deliberately favor a process, for example the main MySQL process over less critical maintenance scripts.
# Start a new process with a lower CPU priority (higher nice value)
nice -n 15 php bin/magento indexer:reindex
# Lower the priority of an already-running process by PID
renice -n 19 -p 24817
# Verify current nice value of running processes
ps -eo pid,ni,cmd --sort=-ni | head -10
4. ionice classes: realtime, best-effort, and idle
While nice controls CPU priority, ionice governs priority when accessing block devices, i.e. hard disks and SSDs. The kernel distinguishes three I/O scheduling classes: realtime for the highest priority, practically never suitable for background jobs, best-effort as the default for most processes with additionally gradable priority levels from 0 to 7, and idle, which only gets I/O time when no other process currently wants to access the block device.
For background jobs such as backups or large file exports, the idle class is the natural choice, because it guarantees that a process never displaces active database or application I/O, and instead only uses the gaps that occur anyway. The exact effect, however, depends on the I/O scheduler in use: on systems with the BFQ scheduler, ionice works significantly more precisely than under the simpler mq-deadline scheduler, which partly ignores ionice priorities.
# Check the currently active I/O scheduler for a disk
cat /sys/block/sda/queue/scheduler
# [bfq] mq-deadline none
# Start a backup with idle I/O priority (never competes with active I/O)
ionice -c 3 tar -czf /backup/daily.tar.gz /var/www/html
# Query the ionice class of a running process
ionice -p 24817
5. Using ionice for backups and reindexing
A daily database dump or file backup typically reads large amounts of data sequentially, which can noticeably reduce I/O throughput for concurrently running, latency-sensitive database queries of the Magento shop. With ionice -c 3, exactly this backup process can be classified so it automatically pauses as soon as MySQL or the web server actively wants to access the same disk, and only resumes afterward.
For Magento reindexing, the situation is somewhat more complex, because reindex jobs can be both CPU-intensive and I/O-intensive, depending on the affected indexer. A combination of a moderate nice value and a best-effort ionice class with reduced priority level is usually more sensible here than the strict idle class, because a reindex still needs to finish within a reasonable time, just not at the expense of the customer experience.
6. Combining nice and ionice for Magento cron
For a production Magento cron job, nice and ionice can be combined in a single invocation, so both CPU priority and I/O priority are lowered at the same time. This combination is particularly relevant for resource-intensive Magento commands like indexer:reindex, cache:flush with a large cache backend, or export jobs, which regularly need to run outside main business hours, but sometimes have to run during active user load anyway.
A common pattern is a wrapper script that automatically starts all Magento cron invocations with reduced priority, instead of manually adjusting every single cron entry. This centralizes the priority logic in one place and prevents a newly added cron job from accidentally running without a priority adjustment.
#!/usr/bin/env bash
# magento-cron-wrapper.sh — run Magento cron with reduced CPU and I/O priority
set -euo pipefail
cd /var/www/html
exec nice -n 10 ionice -c 2 -n 6 php bin/magento cron:run
7. Setting priorities permanently via systemd units
For services that run permanently rather than being started once via cron, nice and ionice equivalent settings can be set directly in the systemd unit file, via the Nice= and IOSchedulingClass= directives combined with IOSchedulingPriority=. This has the advantage that the priority automatically takes effect on every start of the service, without needing to maintain a wrapper script.
For a dedicated batch processing service that regularly processes large amounts of data for a Magento shop, for example a product data import from an ERP system, this systemd-native configuration is the more robust and lower-maintenance alternative compared to manually maintained wrapper scripts.
# /etc/systemd/system/magento-import.service
[Unit]
Description=Magento ERP data import batch job
After=mysql.service
[Service]
Type=oneshot
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=6
ExecStart=/usr/bin/php /var/www/html/bin/magento erp:import
User=www-data
[Install]
WantedBy=multi-user.target
8. Recognizing the limits of nice and ionice
Both nice and ionice only influence relative prioritization between processes, they guarantee no absolute upper bound on resource consumption. A low-priority process can still briefly use 100 percent of a free CPU core if no other process currently has anything to do. For hard resource limits, for example a fixed upper bound on CPU time or memory, cgroups with CPUQuota= or MemoryMax= are the more appropriate tool instead.
Another important point: ionice only works reliably with I/O schedulers that actually take priorities into account, such as bfq. On NVMe SSDs with the none scheduler, often chosen for performance reasons on very fast storage, ionice has practically no effect anymore, because no software queue with prioritization exists at all. On such systems, control has to happen via cgroups I/O weights, not via ionice.
9. nice and ionice values compared
The following table shows typical settings for different background job types on a Magento server.
| Job type | nice value | ionice class |
|---|---|---|
| PHP-FPM worker (web server) | 0 (default) | best-effort, priority 4 (default) |
| Magento reindexing | 10 | best-effort, priority 6 |
| Database backup | 15 to 19 | idle |
| MySQL main process | -5 to -10 | best-effort, priority 2 |
These values are starting points, not fixed rules. The actually appropriate nice and ionice settings should be verified based on concrete response time measurements during running background jobs and fine-tuned as needed.
Mironsoft
Cron and batch job prioritization for Magento servers
Is your reindex slowing down the shop during active user load?
We analyze your cron jobs, configure nice and ionice values to match your I/O scheduler, and set up systemd units that permanently deprioritize background jobs.
Job analysis
Identify response time dips during cron jobs
Priority setup
Configure nice and ionice for reindex, backup, and export appropriately
systemd integration
Permanent, low-maintenance priority control via unit files
10. Summary
nice and ionice solve a very concrete operational problem: background jobs like reindexing, backups, and data imports compete directly with production PHP-FPM requests for the same CPU time and the same disk access without priority control. With nice values between 10 and 19, the CPU priority of background jobs can be deliberately lowered, with the idle or reduced best-effort ionice class the I/O priority accordingly.
For permanently running services, systemd directives like Nice= and IOSchedulingClass= are the more robust alternative to manually maintained wrapper scripts. It remains important that both mechanisms only set relative priorities, not hard upper bounds, and that ionice only works reliably with a suitable I/O scheduler like bfq.
nice and ionice for Background Jobs — Key Takeaways
CPU priority
nice -n 10 to 19 for cron jobs, renice for running processes.
I/O priority
ionice -c 3 (idle) for backups, -c 2 -n 6 for reindexing.
Use systemd
Nice= and IOSchedulingClass= for permanent services.
Know the limits
Only relative priority, hard limits via cgroups CPUQuota/MemoryMax.