A media library grows faster than the images put into it, and the reason matters: WordPress stores several versions of every upload.
One upload, many files
WordPress generates thumbnail, medium and large versions of every image. Themes register their own sizes. Plugins register more.
A single upload commonly becomes five to ten files. Ten thousand images can be sixty thousand files.
That is a different problem from disk space, because a hosting account has a limit on the number of files as well as on bytes, and on an image-heavy site the file count is usually reached first, producing failures that mention disk while the space looks fine. Understanding inodes walks through that failure.
Measure both
du -sh ~/public_html/wp-content/uploads find ~/public_html/wp-content/uploads -type f | wc -l df -i
The middle figure is the one people have never looked at, and it is frequently the surprising one.
Reduce how many sizes are generated
Most themes register sizes that nothing ever displays: left over from a demo layout, or from a slider that was removed.
Every one of those is an extra file for every image uploaded from now on. Removing the ones you do not use is the single change with the most effect, and it costs nothing.
Existing files are unaffected; this only changes what happens next. Regenerating thumbnails afterwards is what removes the old ones, and on a large library that is a long job best run over SSH rather than through the browser. See using WP-CLI.
Resize before uploading
An image straight from a camera is several thousand pixels wide and a few megabytes. Displayed at 800 pixels, none of that is used, and the full-size original is stored permanently regardless.
Resizing to the largest size the site actually displays, before upload, reduces both the original and every generated version. It is the habit that prevents the problem rather than managing it. Optimising images and the media library sets out the formats and the compression.
Sizes from departed themes are never cleaned
When a theme or plugin is removed, the image sizes it generated remain in the uploads directory indefinitely, referenced by nothing.
On a site that has changed themes twice, this can be most of the file count. Nothing cleans it automatically, because WordPress no longer knows those sizes existed.
Tools exist to find and remove unregistered sizes. Take a backup first. The operation deletes files based on what is currently registered, and a size that is still referenced somewhere unusual will disappear.
Deleting attachments, and the ones that are not tracked
Deleting an image from the media library removes its generated versions too. That works.
What is not tracked is an image referenced only inside page content, pasted in, or uploaded by a page builder that manages its own files. Those are not attachments, so nothing associates them with a post, and nothing will ever remove them.
This is why "unused media" tools are unreliable on builder-heavy sites: an image the tool thinks is unused may be displayed on the homepage. Verify before deleting in bulk.
Offloading to storage elsewhere
For genuinely large libraries, moving the files to object storage and serving them from there removes both the space and the file-count problem from the hosting account.
The trade is a dependency: the site now needs that service to display images, and migrating away later means moving them back. Worth it above a certain size and unnecessary below it.
A content delivery network is a different thing and solves a different problem. It caches copies for speed while the files still live on your account. Choosing and setting up a CDN goes into that distinction.
Backups get harder
A large uploads directory is what makes a backup slow, and it is also the part that cannot be regenerated: core and plugins can be downloaded again.
Backing up uploads on a different, less frequent schedule than the database is a reasonable arrangement, since images change rarely and content changes constantly. Managing WordPress backups goes into what each part needs.
Find out what is actually taking the space
Before changing any setting, establish which part of the library is the problem, since the answers differ completely.
du -sh wp-content/uploads du -sh wp-content/uploads/* 2>/dev/null | sort -h | tail -8 find wp-content/uploads -type f | wc -l find wp-content/uploads -type f -size +2M | wc -l
A small number of very large files is one problem, fixed by resizing the originals. A very large number of small files is a different one, fixed by generating fewer sizes.
The file count matters independently of the size, because the file allowance is a separate limit and a media library is the usual reason an account reaches it. Understanding inodes covers that ceiling.
Find the files nothing references
Uploads outlive the content that used them, and nothing removes them.
wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_type='attachment';" find wp-content/uploads -type f -name '*.jpg' | wc -l wp db query "SELECT COUNT(*) FROM wp_posts p WHERE p.post_type='attachment' AND p.post_parent = 0;"
A file count far above the attachment count means files exist on disk that the site does not know about, usually left by a plugin or an interrupted import.
Attachments with no parent are frequently still in use, since anything inserted into a page rather than attached to it appears this way. That is why bulk removal based on this figure alone deletes images that are on live pages.
Check the library before a migration, not after
The media directory is the slowest part of any move, and it is the part that fails quietly.
du -sh wp-content/uploads; find wp-content/uploads -type f | wc -l
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/wp-content/uploads/2026/01/example.jpg
Reduce it before copying rather than moving years of unused files to a new server and paying for the transfer time twice.
After the move, request a handful of images directly rather than trusting a page to look correct. A page can render acceptably while a proportion of its images are missing, and the missing ones are usually the older content nobody checks.