Back to blog
August 31, 2026Sergei Solod9 min read

My FDCServers VPS Worked Fine for More Than 3 TB of Traffic. Then Disk Reads Started Taking 18 Seconds

My FDCServers VPS initially handled real traffic normally and transferred more than 3 TB of data. Then ordinary workload began triggering severe virtual-disk stalls: CPU I/O wait reached 100%, Linux I/O pressure approached 100%, read latency reached 18.7 seconds, and flush latency exceeded 53 seconds.

FDCServersVPSLinuxDisk I/ODevOps

I am not writing this as a negative review of FDCServers. I am not trying to tell people whether they should or should not buy a VPS from them. I had one server, one workload, and one sequence of problems. That is not enough to judge an entire hosting company.

This is simply one of my days as a developer. The VPS had been working normally for some time and had already transferred more than 3 TB of traffic. Then ordinary workload started producing severe delays. Pages could take a very long time to respond or time out completely. At first the usual suspects were the application, Nginx, memory, networking, connection limits, or too much load. The Linux metrics pointed somewhere else.

The VPS did not start out slow

Between incidents the machine could look completely healthy. During one clean period I saw no processes in D-state, CPU iowait was around 0%, disk latency was roughly 2–4 ms, and I/O PSI was almost zero:

D-state processes: 0
CPU iowait:        ~0%
disk latency:      ~2–4 ms
I/O PSI some:      0.04
I/O PSI full:      0.04

If I had connected only at that moment and checked top, free -h, df -h, and systemctl status nginx, I probably would have concluded that the VPS was fine. Then the normal workload returned and the state of the machine changed dramatically.

18.7-second reads changed the investigation

One of the strongest iostat samples looked like this:

r_await = 18744 ms
f_await = 53561 ms
aqu-sz  = 128.54
util    = 100.10%
read    = 88 KB/s

The numbers matter together. Completed reads were averaging about 18.7 seconds. Flush latency was about 53.6 seconds. The average I/O queue was above 128, while useful read throughput was only 88 KB/s. This was not simply a busy disk moving lots of data. It was a storage path spending enormous amounts of time waiting for operations to complete.

iowait and PSI showed system-wide I/O pressure

During the worst periods, vmstat showed 4–9 blocked processes, CPU iowait around 97–100%, and 0% CPU idle. iowait does not mean the application is consuming all CPU time. It means useful work is waiting for outstanding I/O.

Linux Pressure Stall Information made the picture even clearer. One severe sample showed:

I/O PSI some avg10 = 99.14
I/O PSI full avg10 = 95.55

In later reproductions, full approached 98%. Disk utilization tells me that a device is busy; PSI tells me how badly the workload is being stalled by the resource. Sustained I/O pressure around 95–98% is not a small performance regression.

D-state and kernel stacks pointed below the application

I then inspected which processes were blocked. At the same time I could see jbd2, systemd-journald, Nginx workers, Nginx cache processes, and other filesystem activity in D-state. If only my application were stuck, I would investigate the application. If Nginx, the system journal, and the EXT4 journal are blocked together, storage becomes the obvious shared dependency.

The EXT4 journaling paths included:

wait_on_buffer
jbd2_log_wait_commit
jbd2_journal_commit_transaction

Nginx workers were waiting in ordinary file reads:

folio_wait_bit_common
filemap_read
generic_file_read_iter
ext4_file_read_iter
vfs_read
pread64

At one point the kernel reported that an Nginx task had been blocked for more than 122 seconds. Nginx could still be reported as active, but that did not mean its workers could complete useful work. Running and healthy are different states.

A 3 ms backend response separated the application from the filesystem path

The cleanest comparison was between Nginx and the local application backend. Requests through Nginx were returning HTTP=000 with connection or TLS timeouts. A direct request to the backend completed in about 3 ms:

connect = 0.000423 s
TTFB    = 0.003063 s
total   = 0.003139 s

The exact HTTP status was not important for this test. The backend accepted the connection, processed the request, and produced a response almost immediately. At the same time, Nginx workers were visible waiting on EXT4 reads. That separated normal application execution from the filesystem-backed path in front of it.

The failure was reproducible — and could disappear again

Before one reproduction, the machine looked normal:

HTTP:          200
D-state:       0
CPU iowait:    3%
r_await:       ~1.18 ms
I/O PSI full:  ~2.95%

Roughly half a minute later:

D-state:       4
CPU iowait:    91%
CPU idle:      0%
I/O PSI some:  86.11%
I/O PSI full:  78.02%
r_await:       236.50 ms
HTTP:          000

Later, CPU iowait reached 96–100%, I/O PSI full approached 98%, the HTTPS queue reached 512, and HTTP checks still failed. This was much more useful evidence than saying the VPS felt slow.

When I removed the workload, the opposite transition could happen quickly:

D-state:      0
CPU iowait:   6%
r_await:      ~0.98 ms
queue depth:  ~0.07
HTTP:         200

That is why intermittent storage problems are hard to inspect after the fact. A provider can look at the server after recovery and truthfully see normal latency. That does not explain what happened ten minutes earlier. Exact UTC timestamps became essential.

Two metrics that can mislead: await=0 and free disk space

During some bad intervals I could see r_await = 0 while iowait was high, processes were in D-state, requests remained in flight, and almost no reads completed. Latency statistics are based on completed I/O. If an operation remains stuck and does not complete during the sampling interval, it cannot contribute a completed latency measurement. A zero therefore does not always mean an instant disk.

I also considered disk fullness. Later the filesystem became fuller than I would normally allow, but the same class of failure had already appeared when the root filesystem was only about 24% used. At that point there was roughly 1.2 GiB of available RAM, inode usage was about 5%, and the network interface showed no errors or dropped packets. Disk fullness could not explain the entire incident.

What I could prove, and what I could not

From inside the VPS I could observe the application, Linux VFS, EXT4, and the virtual block device. After that comes the provider's infrastructure: virtualization, distributed storage, storage networking, physical devices, scheduling, and other layers I cannot inspect from the guest.

So I cannot honestly claim that a particular physical SSD was broken, or identify a specific storage node, network path, or virtualization component as the root cause.

What I can say is narrower and well supported: the virtual storage path presented to my Linux guest repeatedly entered states where ordinary filesystem I/O took seconds or failed to complete in a reasonable amount of time. The evidence came from iostat, PSI, D-state, kernel wait stacks, EXT4/jbd2 waits, Nginx filesystem waits, queue depth, and request timings. That was enough for the engineering diagnosis I needed, but not enough for a physical root cause.

Why more than 3 TB of previous traffic did not contradict the later stalls

This initially confused me. If storage was having trouble, why had the VPS already transferred several terabytes successfully?

Because network traffic is not the same thing as physical disk I/O. A file can be read from backing storage once, remain in Linux page cache, and then be served many more times from memory. Three terabytes transferred over the network therefore does not mean three terabytes of unique physical disk reads.

Infrastructure conditions can also change over time: cache state, storage load, queueing, host placement, and other workloads may all change. A VPS working normally yesterday does not guarantee identical storage behavior today.

I eventually stopped waiting for a deeper root cause

I collected exact timestamps, vmstat, iostat, PSI, blocked-process snapshots, kernel stacks, filesystem waits, queue depths, and HTTP timings. I sent the diagnostics to FDCServers and waited for a deeper infrastructure-level explanation.

I waited for a long time. Eventually I stopped waiting. From my side, I already knew enough to make an operational decision: the problem was reproducible, severe, visible below the application layer, and the physical cause was outside the visibility of my VPS.

I asked for a refund, and FDCServers returned the money

I sent FDCServers a summary of the problems and the diagnostics I had collected, asked to cancel the service, and requested a refund. They refunded me.

So this story does not end with a long fight over money. I waited for a definitive technical explanation, decided I was done waiting, sent the evidence I had, and asked for my money back. FDCServers returned it.

What I changed afterward

The useful result was not deciding whether one hosting company is good or bad. It was changing how I debug slow Linux servers.

I still use basic commands such as top, free -h, and df -h, but I now reach for these much earlier:

date -u
uptime
cat /proc/pressure/io
cat /proc/pressure/memory
cat /proc/pressure/cpu
vmstat 1 10
iostat -x 1 10
ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'
ss -lntp
journalctl -k --since '30 min ago' --no-pager

I also test separate request paths whenever possible: public request, local Nginx, direct backend, filesystem, and block-device metrics. The question is no longer simply why the server is slow. It is: At which layer does useful work stop completing?

When possible, I capture the evidence before rebooting. A reboot may restore service, but it can also erase the exact D-state, PSI, queues, and latency that make an intermittent incident diagnosable.

Final thought

I did not buy an FDCServers VPS because I wanted material for a hosting article. I wanted a server with a lot of bandwidth. For a while, that is exactly what I got. It handled real workload and transferred more than three terabytes.

Then normal workload began reproducibly producing iowait up to 100%, I/O PSI near 100%, reads up to 18.7 seconds, flush latency above 53 seconds, large queues, Nginx blocked in filesystem reads, and EXT4/jbd2 waiting for I/O.

I never learned which physical or host-side component caused it, and I do not need to pretend that I did. I identified the layer where the failure manifested, collected enough evidence to distinguish it from an application problem, stopped waiting for a deeper root-cause explanation, and asked for my money back. FDCServers refunded me.

This is not a verdict on every FDCServers VPS. It is one well-documented reminder that a service can look active, a process can look running, and the machine can still be spending almost all of its useful time waiting for storage.