We kept seeing client sites slow to a crawl because someone uploaded a six-megabyte photo straight from a digital camera into a blog post, then WordPress dutifully served it at full resolution, letterboxed down by nothing more than an img tag's width and height attributes doing the visual resizing while the browser still downloaded every pixel underneath.
Our fix isn't clever, it's process. We now run every image through Photoshop's Save for Web dialog before it goes anywhere near a site, targeting a sensible max width and a quality setting around 60-70 for JPEGs, which is usually indistinguishable on screen from full quality but a fraction of the file size.
Where the six-megabyte photos come from
Most of our clients aren't thinking about file size at all when they add a new photo, they're thinking about the photo looking good, which is exactly the right thing for them to be thinking about. The camera in a decent point-and-shoot or an early smartphone at this point produces images sized for print, not for a blog post that displays at 600 pixels wide, and WordPress's media uploader doesn't do anything by default to correct for that mismatch beyond generating a few standard thumbnail sizes for use in templates, the full original still sits there and gets served wherever a template calls for the full size.
What Save for Web actually buys us
The Save for Web dialog gives a live preview of file size against visible quality loss as you drag the quality slider, which makes it much easier to find the actual point of diminishing returns for a specific image than guessing a quality percentage blind. For most photography, especially anything web-sized rather than being viewed at full resolution, 60-70 quality on a properly resized JPEG is genuinely hard to tell apart from the source file on a normal monitor, while cutting file size dramatically, often to a tenth or less of the original.
We're also stripping metadata in that same pass, camera model, GPS coordinates if the photo has any, which serves no purpose on a public-facing site and adds unnecessary bytes to every image.
Documentation for clients
We're also starting to write this into client documentation, since we can't optimize every future upload for them, and most clients will keep adding their own content long after a project officially wraps. A short PDF with screenshots of the Save for Web panel has already cut down on complaints about slow-loading galleries, even though it relies on the client actually reading and following it rather than just uploading straight from their camera roll out of habit.
What we're still working out
Getting every client to actually adopt this workflow consistently is the real remaining challenge, not the technical fix itself. A few clients have taken to it readily, others still upload full-resolution photos regardless of documentation, and for those accounts we're considering whether a plugin that automatically resizes and compresses on upload is worth the added dependency, weighed against the maintenance of one more piece of software on every site we manage.
For now, the process fix is doing most of the work, and it's a good reminder that not every performance problem needs a clever technical solution, sometimes the fix really is just remembering to do the boring step every single time rather than skipping it under deadline pressure.