VPS Tutorials
What to Do When VPS Disk I/O Is Very High (2026): iowait, iostat, iotop, Database and Log Troubleshooting
VPS CPU looks low, but SSH lags, the website is slow, database queries are slow, and %wa/iowait is high in top. Common causes include log explosions, random database reads and writes, Docker container logs, swap thrashing, backup compression, overly long disk queues, or host storage contention. This article locates the problem layer by layer using top, vmstat, iostat -x, iotop, pidstat, du, and journalctl.

When a VPS slows down, CPU is not necessarily the main cause.
Sometimes you open top and find that CPU usage is not high, but %wa is very high; SSH has a delay when typing commands, website APIs are slow, database queries drag, and unzipping and writing logs also stall. This situation is very likely caused by disk I/O being stuck.
Disk I/O problems are the easiest to misjudge: some people think it is poor application performance, some think it is slow network, and some just reboot. The correct approach is to first confirm whether it is iowait, then find which process is reading and writing, and finally determine whether it is logs, the database, Docker, swap, backup tasks, or the provider's underlying storage contention.
The first step is to look at top:
top
In the CPU line, look at %wa. If %wa stays high for a long time, it means the CPU is spending a lot of time waiting for disk I/O to complete.
You can also use:
vmstat 1
Focus on:
wa: the proportion of CPU waiting for I/O;bi/bo: block device reads and writes;r: processes waiting for CPU;b: uninterruptible sleep, commonly seen when waiting for I/O.
If wa is very high, b is also not low, and the machine feels laggy, do not just stare at application logs.
Install the tool:
sudo apt install sysstat -y
Or on RHEL-based systems:
sudo dnf install sysstat -y
View extended disk metrics:
iostat -x 1
Focus on these columns:
%util: how busy the device is;await: average wait time for I/O requests;r/s,w/s: read/write requests per second;rkB/s,wkB/s: read/write throughput per second;aqu-sz: average queue length.
Simple judgment:
- If
%utilstays close to 100% for a long time, the disk is very busy; - If
awaitrises significantly, I/O wait has become longer; - If
aqu-szstays high for a long time, requests are queuing; - If throughput is not high but await is very high, it may be random I/O, an IOPS limit, or underlying storage latency.
Do not look at only one value. A high iowait only means the CPU is waiting for I/O; it does not directly prove that "the disk is broken." Combine it with iostat and process-level reads and writes.
Install:
sudo apt install iotop -y
Run:
sudo iotop -oPa
Parameter meanings:
-o: only show processes currently generating I/O;-P: aggregate by process instead of thread;-a: show cumulative read and write volume.
Processes commonly seen at the top:
mysqld/mariadbd/postgres: database reads and writes;dockerd/containerd: container logs or image layers;journal/rsyslogd: system log writes;backup/tar/gzip/rsync: backup compression and sync;updatedb/apt/dpkg: indexing or installation tasks;- Application processes: writing logs or temporary files like crazy.
If a process in iotop keeps writing a large amount, do not rush to kill the process; first confirm what it is writing.
iotop is great for looking at the current situation, while pidstat is better for looking at trends over a period of time.
pidstat -d 1
Look at a specific process:
pidstat -d -p PID 1
Focus on:
kB_rd/s: reads per second;kB_wr/s: writes per second;kB_ccwr/s: canceled writes.
If an application's writes remain high, then check its log directory, upload directory, and cache directory.
First look at large directories:
sudo du -xh /var/log --max-depth=1 | sort -h
Look at logs that have changed quickly recently:
sudo find /var/log -type f -printf '%s %p\n' | sort -n | tail -n 20
Watch in real time whether a log is growing like crazy:
sudo tail -f /var/log/nginx/error.log
Common scenarios:
- Nginx repeatedly records upstream errors;
- Application exception stacks flood the screen;
- Docker containers write stdout/stderr logs without limits;
- fail2ban, authentication failures, or crawler access cause log explosions;
- Debug logging was left on.
If it is Docker logs, see: What to Do When VPS Docker Fills the Disk. That article covers disk usage, while this one focuses on I/O stalls; the two problems often appear together.
If iotop shows MySQL, MariaDB, or PostgreSQL, it does not mean the database "has a problem." It may be that the business is genuinely reading and writing, or it may be slow queries, missing indexes, temporary tables, checkpoints, vacuum, or backups.
First look at the system level:
sudo iotop -oPa
pidstat -d -p $(pidof mysqld) 1
pidstat -d -p $(pidof postgres) 1
Then look at database logs:
sudo journalctl -u mysql -n 100 --no-pager
sudo journalctl -u mariadb -n 100 --no-pager
sudo journalctl -u postgresql -n 100 --no-pager
Common causes:
- Missing indexes cause a large number of random reads;
- Queries generate large temporary tables;
- Backup tasks collide with business peak hours;
- High binlog / WAL write pressure;
- Database writes slow down after the disk is nearly full;
- Insufficient memory leads to a low cache hit rate.
If the database cannot be connected to or the service fails to start, you can read the dedicated articles on MySQL, PostgreSQL, and Redis respectively; here we first determine whether the I/O is caused by the database.
Small-memory VPS instances easily encounter swap thrashing. On the surface it is high disk I/O, but the root cause is insufficient memory, and the system frequently swaps memory pages in and out.
Check:
free -h
swapon --show
vmstat 1
In vmstat, look at:
si: swap in;so: swap out.
If si/so is continuously non-zero and %wa is high at the same time, swap is involved in the lag.
As a temporary mitigation, you can stop unnecessary services, reduce concurrency, and stagger tasks. In the long run, you still need to optimize memory, add caching, upgrade the plan, or separate the database and application.
Many I/O peaks are self-created.
For example:
tar -czf backup.tar.gz /var/www /var/lib/mysql
rsync -av /data remote:/backup
mysqldump app > app.sql
docker save image > image.tar
If these tasks happen at the same time as business peak hours, database writes, and log rotation, the VPS can easily lag.
Troubleshoot scheduled tasks:
crontab -l
sudo crontab -l
systemctl list-timers --all
Look at recent logs:
journalctl --since "2 hours ago" --no-pager
If it is triggered by scheduled tasks, see: What to Do When VPS Scheduled Tasks Do Not Run; the troubleshooting methods there are also suitable for finding "who is periodically creating I/O."
In Docker scenarios, high I/O often comes from two places:
- Container logs writing like crazy;
- The overlay2 layer frequently writing temporary files.
First look at container status:
docker ps --size
Check log size:
sudo du -xh /var/lib/docker/containers --max-depth=2 | sort -h | tail -n 20
Check whether a container's logs are flooding:
docker logs 容器名 --tail 100
If the business allows, configure log rotation for Docker, for example max-size and max-file in json-file. Do not let one abnormal container drag down the host disk and I/O.
If you have already confirmed:
- There is no obvious large-write process;
- Database and log pressure is not high;
- Swap is not obviously thrashing;
- Backup tasks are not running;
- But
awaitis high for a long time,%utilis high, and SSH and all applications lag together; - It is more obvious during evening peak hours, or users on the same node also report slowness;
Then it may be host storage contention, IOPS limits, or neighbor impact.
At this point, do not just send "the disk is slow." Attach evidence to the provider ticket:
date
uptime
vmstat 1 10
iostat -x 1 10
sudo iotop -oPa -b -n 5
free -h
df -h
If you run fio tests, be careful not to stress-test the production disk randomly during business peak hours. On a small VPS, fio can easily slow down the business further.
When you encounter high VPS disk I/O or high iowait, check in this order:
- Use
topto see whether%wastays high. - Use
vmstat 1to seewa,b,bi/bo, andsi/so. - Use
iostat -x 1to see%util,await, andaqu-sz. - Use
iotop -oPato find the processes currently reading and writing. - Use
pidstat -d 1to see process read/write trends. - Use
du -xh /var/logto check whether logs are exploding. - Check the database, Docker, backups, compression, and sync tasks.
- Use
free -h,swapon --show, andvmstatto judge swap thrashing. - Stagger heavy tasks, limit logs, and optimize database queries and caching.
- When there is no local cause, take
iostat/vmstat/iotopevidence to the provider.
When VPS disk I/O is high, do not just look at CPU, and do not reboot directly. First use top and vmstat to confirm whether it is iowait, then use iostat -x to judge disk latency and queues, and finally use iotop and pidstat to find the specific process.
Most problems ultimately come down to log explosions, random database reads and writes, Docker logs, swap thrashing, backup task collisions, or host storage contention. If you can locate the process, fix the local machine first; if you cannot locate a local cause, then take complete metrics to the provider, so the ticket is convincing.