How I Rescued Ubuntu on a USB Pendrive: Fixing High I/O Wait, Stuttering, and Flash Drive Wear
Linux07 Oct 2026
As an engineer working with an older laptop where the internal storage was constrained and couldn't easily be extended or upgraded with a dedicated SSD, I opted for a creative, portable alternative: installing and running a full Ubuntu desktop directly off an external USB 3.0 flash drive (SanDisk 128 GB).
Initially, the experience was great. But over time, the system began to feel sluggish. Windows would hesitate when opening, switching apps felt stuttery, and terminal commands that wrote to disk would stall. Memory and network were completely fine, but the system felt like it was constantly dragging its feet.
Was the pendrive dying? Or was something deeper happening under the hood? Here is how I diagnosed the root causes, the surprising discoveries in kernel logs, and how simple tweaks reduced system load from 7.01 down to 0.49.
1. Diagnosing the Bottleneck: The High I/O Wait Trap
When Linux feels laggy despite low CPU utilization, the first suspect is always I/O Wait (wa). I checked the live system statistics using vmstat:
$ uptime
02:57:25 up 5 min, load average: 7.01, 3.37, 1.38
$ vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
r b swpd free buff cache si so bi bo in cs us sy id wa st gu
0 7 0 8.4G 120M 3.8G 0 0 0 8752 2605 3286 1 1 64 35 0 0
1 5 0 8.3G 120M 3.8G 0 0 0 4712 4810 4731 6 1 62 31 0 0
Notice the numbers:
- Load average was 7.01 just five minutes after boot, despite actual CPU usage being barely 2%!
wa(I/O Wait) was hovering between 31% and 35%. One-third of CPU cycles were spent sitting idle waiting for storage blocks to flush.b(Blocked processes) was 5 to 7. Several key threads were frozen in uninterruptible sleep (Dstate).
Checking the processes trapped in D state revealed the culprit:
$ ps -eo pid,user,stat,comm | grep -E " D"
356 root D usb-storage
987 root D kworker/u57:8+flush-8:0
1115 root D jbd2/sda3-8
The ext4 filesystem journal (jbd2), kernel page flusher, and USB storage driver were all locked up waiting for the flash memory controller to acknowledge writes.
2. The Flash Drive Reality Check
Running a write benchmark with dd and conv=fdatasync showed the harsh reality:
67108864 bytes (64 MiB) copied, 10.79 s, 6.2 MB/s
Sequential write speed was only 6.2 MB/s. For comparison, modern internal SSDs write at 2,000–3,500 MB/s. When an operating system, web browser, and logging daemons write hundreds of small files simultaneously, random 4K write speeds drop below 0.3 MB/s.
Additionally, my /home partition had reached 83% capacity (only 6.3 GB free). Standard USB flash drives use TLC/QLC NAND without TRIM support or DRAM cache. When a thumb drive exceeds 75–80% capacity, the controller runs out of pre-erased blocks. Every single write becomes an agonizing read-erase-write cycle (write amplification).
3. Discovery: The Hidden 10-Second Crash Loop
While checking the systemd journal, I discovered a background service failing repeatedly:
systemd[1]: broadcast-system.service: Failed with result ''exit-code''.
(node)[5798]: broadcast-system.service: Failed at step USER spawning /usr/bin/node: No such process
Due to a small username typo in the service unit file, the service was failing and restarting every 10 seconds indefinitely. Every restart forced systemd to spawn processes and write logs, which constantly triggered ext4 journal syncs on the slow USB drive.
4. The Optimizations That Fixed Everything
A. Leverage Unused RAM with tmpfs
The laptop has 14 GB of RAM, but only ~3.5 GB is actively used. Why commit temporary files, browser caches, and logs to a slow USB flash drive when 10 GB of high-speed RAM is sitting idle?
I added the following entries to /etc/fstab:
tmpfs /tmp tmpfs defaults,noatime,mode=1777,size=1G 0 0
tmpfs /var/tmp tmpfs defaults,noatime,size=512M 0 0
tmpfs /var/log tmpfs defaults,noatime,size=100M,mode=755 0 0
tmpfs /home/santhoshreddym/.cache tmpfs defaults,noatime,uid=1000,gid=1000,size=2G 0 0
And ensured systemd journal logs stay in memory in /etc/systemd/journald.conf:
[Journal]
Storage=volatile
RuntimeMaxUse=100M
Now, browser caches, thumbnails, and temporary files write to RAM at gigabytes per second, bypassing the USB drive completely.
B. Disabling the Looping Service
sudo systemctl stop broadcast-system.service
sudo systemctl disable broadcast-system.service
C. Reclaiming 9.5 GB by Sweeping Inactive node_modules
Scanning my ~/Documents/Git directory revealed that abandoned node_modules across various projects were consuming nearly 10 GB of space. I removed them all with a single prune command:
find ~/Documents/Git -name "node_modules" -type d -prune -exec rm -rf {} +
This instantly dropped /home usage from 28 GB down to 19 GB.
D. Moving Google Chrome Profile to the Root Partition
Google Chrome profiles take around 3.8 GB across multiple user profiles and service worker storage. Since the root partition (/) had 29 GB of free space while /home was tight, I moved the Chrome directory to /opt and linked it back:
sudo mkdir -p /opt/google-chrome
sudo chown -R $USER: /opt/google-chrome
cp -a ~/.config/google-chrome/. /opt/google-chrome/
rm -rf ~/.config/google-chrome
ln -s /opt/google-chrome ~/.config/google-chrome
This brought /home usage down to 41% (with 22 GB free space)!
5. The Results: Before vs. After
| Metric | Before Optimization | After Optimization | Impact |
|---|---|---|---|
| System Load Average | 7.01 | 0.49 | 14x Reduction |
| CPU I/O Wait (wa) | 16% – 35% | 0% | Completely Eliminated |
| Blocked Processes (D state) | 5 to 7 | 0 | Zero Stuttering |
| Write Throughput | 6.2 MB/s | 9.6 MB/s | 55% Faster |
| /home Space Used | 83% (6.3 GB free) | 41% (22.0 GB free) | +15.7 GB Free Space |
Key Takeaways
- Flash drives need free headroom: Never let a USB drive without TRIM exceed 75% capacity.
- Put high-churn caches in RAM: Mounting
~/.cacheand/tmpintmpfssaves your flash drive from wear and makes desktop apps fly. - Watch out for crash loops: A background service looping every few seconds can quietly bring a slow storage bus to its knees.