Как организовать хранение фотографий для сайта?
Загружайте файлы не в папку, а в s3-совместимое хранилище (чтобы при желании можно было без страданий и изменений в коде перейти на Amazon или в Linode какой-нибудь) - MinIO. Т.е. генерируете некий id, превращаете его в хеш, формируете ключ и по нему льёте в MinIO. Причём храните только оригиналы.

Что касается миниатюр, то их нарезать и хранить не нужно. Представьте, если размеры в дизайне поменялись - что тогда? А если для каждой миниатюры webp-версия потребовалась - все картинки опять обрабатывать? Есть решение - imgproxy. Это специальный прокси-сервис (можно на свой сервер поставить, как и MinIO), который нарезает картинки "на лету" в момент обращения (по параметрам в url). Кроме нарезки, есть ещё куча разных возможностей. Кеша внутреннего нет, т.е. перед imgproxy есть смысл поставить Nginx для кеширования миниатюр (чтобы при каждом обращении не нарезало).
Тоже считаю второй способ самым оптимальным. Когда-то смотрел разные варианты и остановился на этом. Генерируется уникальный ID, создаются директории для равномерного распределения согласно второму способу из stackoverflow... а дальше можно посмотреть по ссылкам (w - width, высота зависит от пропорций изображения):
// ID: 3d02573d-4d28-7144-9f6e-f7372a084069
// Путь: [uploads]/[первые два символа ID]/[след. два символа ID]/[ID]/[что угодно][разделитель][разрешение][расширение]
{
	...
	photos: [{
		original: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_4032x3024.jpg',
		w1024: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_1024x768.jpg',
		w600: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_600x450.jpg',
		w256: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_256x192.jpg',
		w56: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_56x42.jpg'
	}]
	...
}
Можно удалить фотографию вместе с тумбами за раз удалив папку 3d02573d-4d28-7144-9f6e-f7372a084069.