Tools: Update: Stop Letting SSD Performance Rot: Practical `fstrim.timer` on Linux

Tools: Update: Stop Letting SSD Performance Rot: Practical `fstrim.timer` on Linux

Stop Letting SSD Performance Rot: Practical fstrim.timer on Linux

What TRIM actually does

Why fstrim.timer is usually better than discard

Step 1: Check whether your storage advertises discard support

Step 2: Check whether the timer already exists and is active

Step 3: Enable and start the timer

Step 4: Run a one-time TRIM manually

Step 5: Verify the last run and logs

When you should not expect this to work

1. You are inside a container

2. The filesystem or block layer does not support discard

3. You are using old advice that assumes discard must be mounted live

A safe baseline for most Linux machines

Should you add discard to /etc/fstab anyway?

Final take

References If your Linux system lives on SSDs, virtual disks backed by SSD storage, or thin-provisioned volumes, TRIM is one of those boring maintenance jobs that is easy to forget and annoying to debug later. The good news is that modern Linux already has a sensible answer: fstrim.timer. This post shows how to: I am focusing on the practical path here, not storage folklore. When files are deleted, the filesystem knows those blocks are free, but the SSD may not know that immediately. TRIM, exposed on Linux through fstrim, tells the underlying storage which unused blocks can be discarded. The fstrim(8) manual describes it plainly: fstrim discards unused blocks on a mounted filesystem, and it is useful for SSDs and thin-provisioned storage. A lot of guides jump straight to adding discard to mount options. That is not my default recommendation. The upstream fstrim(8) man page explicitly warns that running TRIM frequently, or using mount -o discard, may negatively affect poor-quality SSDs, and says that for most desktop and server systems, once a week is sufficient. That lines up with what many distributions ship today. On this host, the packaged timer is: That is a very reasonable default: You can also inspect mounted filesystems with: That gives you a quick view of mounted filesystems and discard-related device characteristics. Many systems already ship this enabled. Check before changing anything: If you see a next run scheduled, you may already be done. You can inspect the packaged service and timer definitions too: On this machine, the service executes: That is a nice detail. It trims filesystems listed in fstab or mount info, prints useful byte counts, and suppresses noisy errors for unsupported filesystems. If the timer is installed but inactive, enable it: If your distro uses vendor presets that already enabled it, this command is harmless. Sometimes you do not want to wait for the weekly run, especially after a big cleanup, VM image shrink, or container/image pruning session. Example output usually looks like this: One subtle but important note from fstrim(8): the reported byte count is the amount passed down for potential discard, not a guarantee that the device physically discarded every byte right then. That is normal. After either a manual run or a timer-driven run, check the service logs: This gives you two useful things: A few cases trip people up: On this host, the packaged units contain: So fstrim.timer and fstrim.service are intentionally skipped in containers. That is correct, because discard belongs to the host or VM layer that owns the block device. The fstrim(8) man page notes that unsupported filesystems and read-only cases are ignored when trimming all filesystems. If your storage stack does not pass discard through, no amount of systemd tweaking will fix that. That is not generally true anymore. Weekly batched TRIM is the upstream-recommended default for most systems. If I were setting this up on a normal workstation, home server, or VM backed by SSD storage, my baseline would be: I would only consider continuous discard if you have a specific storage stack that benefits from immediate reclamation and you have tested the performance tradeoff. For general-purpose Linux systems, the weekly timer is the cleaner default. fstrim.timer is one of those rare Linux defaults that is both boring and correct. If your storage supports discard, enable the timer, verify it once, and move on with your life. That is better than cargo-culting discard into every mount option and hoping for the best. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

# /usr/lib/systemd/system/fstrim.timer [Timer] OnCalendar=weekly AccuracySec=1h Persistent=true RandomizedDelaySec=100min # /usr/lib/systemd/system/fstrim.timer [Timer] OnCalendar=weekly AccuracySec=1h Persistent=true RandomizedDelaySec=100min # /usr/lib/systemd/system/fstrim.timer [Timer] OnCalendar=weekly AccuracySec=1h Persistent=true RandomizedDelaySec=100min NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO vda 0 512B 2G 0 ├─vda1 0 512B 2G 0 ├─vda14 0 512B 2G 0 └─vda15 0 512B 2G 0 NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO vda 0 512B 2G 0 ├─vda1 0 512B 2G 0 ├─vda14 0 512B 2G 0 └─vda15 0 512B 2G 0 NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO vda 0 512B 2G 0 ├─vda1 0 512B 2G 0 ├─vda14 0 512B 2G 0 └─vda15 0 512B 2G 0 -weight: 500;">systemctl -weight: 500;">status fstrim.timer -weight: 500;">systemctl list-timers --all fstrim.timer -weight: 500;">systemctl -weight: 500;">status fstrim.timer -weight: 500;">systemctl list-timers --all fstrim.timer -weight: 500;">systemctl -weight: 500;">status fstrim.timer -weight: 500;">systemctl list-timers --all fstrim.timer NEXT LEFT LAST PASSED UNIT ACTIVATES Mon 2026-05-11 00:46:45 UTC 3 days Mon 2026-05-04 01:29:37 UTC 3 days ago fstrim.timer fstrim.-weight: 500;">service NEXT LEFT LAST PASSED UNIT ACTIVATES Mon 2026-05-11 00:46:45 UTC 3 days Mon 2026-05-04 01:29:37 UTC 3 days ago fstrim.timer fstrim.-weight: 500;">service NEXT LEFT LAST PASSED UNIT ACTIVATES Mon 2026-05-11 00:46:45 UTC 3 days Mon 2026-05-04 01:29:37 UTC 3 days ago fstrim.timer fstrim.-weight: 500;">service -weight: 500;">systemctl cat fstrim.timer fstrim.-weight: 500;">service -weight: 500;">systemctl cat fstrim.timer fstrim.-weight: 500;">service -weight: 500;">systemctl cat fstrim.timer fstrim.-weight: 500;">service ExecStart=/sbin/fstrim --listed-in /etc/fstab:/proc/self/mountinfo --verbose --quiet-unsupported ExecStart=/sbin/fstrim --listed-in /etc/fstab:/proc/self/mountinfo --verbose --quiet-unsupported ExecStart=/sbin/fstrim --listed-in /etc/fstab:/proc/self/mountinfo --verbose --quiet-unsupported -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now fstrim.timer -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now fstrim.timer -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now fstrim.timer -weight: 500;">systemctl -weight: 500;">status fstrim.timer -weight: 500;">systemctl list-timers --all fstrim.timer -weight: 500;">systemctl -weight: 500;">status fstrim.timer -weight: 500;">systemctl list-timers --all fstrim.timer -weight: 500;">systemctl -weight: 500;">status fstrim.timer -weight: 500;">systemctl list-timers --all fstrim.timer -weight: 600;">sudo fstrim -av -weight: 600;">sudo fstrim -av -weight: 600;">sudo fstrim -av /: 38.2 GiB (41016926208 bytes) trimmed /boot/efi: 97.5 MiB (102236160 bytes) trimmed /: 38.2 GiB (41016926208 bytes) trimmed /boot/efi: 97.5 MiB (102236160 bytes) trimmed /: 38.2 GiB (41016926208 bytes) trimmed /boot/efi: 97.5 MiB (102236160 bytes) trimmed -weight: 500;">systemctl -weight: 500;">status fstrim.-weight: 500;">service journalctl -u fstrim.-weight: 500;">service --since "7 days ago" -weight: 500;">systemctl -weight: 500;">status fstrim.-weight: 500;">service journalctl -u fstrim.-weight: 500;">service --since "7 days ago" -weight: 500;">systemctl -weight: 500;">status fstrim.-weight: 500;">service journalctl -u fstrim.-weight: 500;">service --since "7 days ago" ConditionVirtualization=!container ConditionVirtualization=!container ConditionVirtualization=!container lsblk -D findmnt -D -weight: 500;">systemctl -weight: 500;">status fstrim.timer || true -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now fstrim.timer -weight: 600;">sudo fstrim -av journalctl -u fstrim.-weight: 500;">service --since today lsblk -D findmnt -D -weight: 500;">systemctl -weight: 500;">status fstrim.timer || true -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now fstrim.timer -weight: 600;">sudo fstrim -av journalctl -u fstrim.-weight: 500;">service --since today lsblk -D findmnt -D -weight: 500;">systemctl -weight: 500;">status fstrim.timer || true -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now fstrim.timer -weight: 600;">sudo fstrim -av journalctl -u fstrim.-weight: 500;">service --since today - verify that discard is actually supported - check whether fstrim.timer is already enabled - -weight: 500;">enable a weekly TRIM schedule safely - run a manual trim when you need one - avoid a common mistake, mounting everything with continuous discard - SSD performance consistency - some thin-provisioned storage backends - reclaiming space more accurately on certain virtualized platforms - weekly keeps the cadence modest - Persistent=true means a missed run is caught up after boot - RandomizedDelaySec= spreads load across machines - DISC-GRAN and DISC-MAX should not both be 0B - non-zero discard values suggest the block device can accept discard/TRIM requests - -a trims all mounted filesystems that support the operation - -v shows how many bytes were passed down for potential discard - whether the -weight: 500;">service actually succeeded - which mountpoints were trimmed and how much was reported - capability check - timer state - scheduled ongoing maintenance - one immediate cleanup run - a verification trail - fstrim(8) man page: https://man7.org/linux/man-pages/man8/fstrim.8.html - systemd fstrim.timer manual: https://www.freedesktop.org/software/systemd/man/latest/fstrim.timer.html - Fedora change note on enabling fstrim.timer: https://fedoraproject.org/wiki/Changes/EnableFSTrimTimer - lsblk(8) man page: https://man7.org/linux/man-pages/man8/lsblk.8.html - findmnt(8) man page: https://man7.org/linux/man-pages/man8/findmnt.8.html