Serving one giant original image everywhere it's displayed — a small avatar, a card thumbnail, a full detail view — wastes bandwidth and slows page loads. Generating a few fixed sizes at upload time, once, is more efficient than resizing on every request.
Generating multiple sizes at upload
use Intervention\Image\Laravel\Facades\Image;
public function store(Request $request)
{
$request->validate(['photo' => ['required', 'image', 'max:10240']]);
$file = $request->file('photo');
$filename = uniqid().'.jpg';
$sizes = [
'thumb' => 150,
'medium' => 600,
'large' => 1200,
];
foreach ($sizes as $label => $width) {
$image = Image::read($file)->scaleDown(width: $width);
Storage::disk('public')->put("images/{$label}/{$filename}", (string) $image->toJpeg(82));
}
// optionally also store the original
Storage::disk('public')->putFileAs('images/original', $file, $filename);
}
scaleDown() resizes proportionally without ever upscaling past the original — if the source image is smaller than the requested width, it's left as-is rather than stretched and degraded.
Why generate at upload time, not on every request
Resizing on every request (a common shortcut with an image-manipulation URL parameter) means paying the CPU cost of resizing repeatedly for the same image, for every visitor. Generating the fixed set of sizes once at upload and storing them means every later request just serves a pre-made file — dramatically cheaper at any real traffic volume.
An alternative for high-traffic sites: on-demand with caching
For applications where the exact sizes needed aren't known in advance (responsive images at many breakpoints), an on-demand image resizing service (Glide, or a CDN-level image transformation service) that caches its output after the first request is often a better fit than pre-generating every possible size manually.
Storing the paths
Store the generated filename (or a base identifier) on the model rather than full paths — construct the actual URL for each size at display time using Storage::url(), so a later change to the storage disk or naming scheme doesn't require a data migration.