Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungPlanning a DEX Product Without Starting With Smart Contracts(21.09.2026 um 15:26 Uhr)
Malware / Trojaner / VirenInside BambooToken’s Linux implant: shell and file control over MQTT(21.09.2026 um 12:37 Uhr)
Linux Tipps & HardeningVoid Linux (base) as a server distro?(21.09.2026 um 14:13 Uhr)
IT Security VideoBlack Hat Stories | Ryan & Isabella Barnett(21.09.2026 um 15:30 Uhr)
IT Security NachrichtenSuccess of Trump-Xi summit lies in what happens afterwards(21.09.2026 um 14:30 Uhr)
Sichere ProgrammierungPlanning a DEX Product Without Starting With Smart Contracts(21.09.2026 um 15:26 Uhr)
Malware / Trojaner / VirenInside BambooToken’s Linux implant: shell and file control over MQTT(21.09.2026 um 12:37 Uhr)
Linux Tipps & HardeningVoid Linux (base) as a server distro?(21.09.2026 um 14:13 Uhr)
IT Security VideoBlack Hat Stories | Ryan & Isabella Barnett(21.09.2026 um 15:30 Uhr)
IT Security NachrichtenSuccess of Trump-Xi summit lies in what happens afterwards(21.09.2026 um 14:30 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

How I Solved Lazy Image Resizing Without Slowing Down the Page Load

The moment user-uploaded images need to appear in more than one place (a thumbnail grid, a product preview, a hero banner) you need multiple sizes. The standard approach generates all variants at upload time, but this slows uploads, wastes…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

The moment user-uploaded images need to appear in more than one place (a thumbnail grid, a product preview, a hero banner) you need multiple sizes. The standard approach generates all variants at upload time, but this slows uploads, wastes disk space on sizes that are never requested, and forces a full library reprocess whenever your layout changes.




Most image sizes will never actually be requested. Generating them eagerly is wasteful.




The solution I landed on: store only the original, and use the web server's 404 handler to trigger resizing on demand. Once a size is generated, it's saved to disk and served as a static file forever. No application code is involved on repeat visits.









The Problem



The correct image size depends entirely on your UI, and those sizes change whenever your layout changes. The standard solution is responsive <picture> elements with srcset and sizes attributes:




<picture>
<source
srcset="/uploads/photos/480x480/my-image.webp 480w,
/uploads/photos/640x640/my-image.webp 640w,
/uploads/photos/1920x1920/my-image.webp 1920w"

sizes="(max-width: 576px) 480px, (max-width: 992px) 640px, 1920px"
type="image/webp">
<img src="/uploads/photos/640x640/my-image.webp"
width="640" height="640"
loading="lazy">
</picture>






This assumes that all those resized images already exist, which typically means generating them during upload.



But this creates two problems:




  1. Uploads become slower because multiple image sizes must be generated immediately.

  2. Many generated sizes are never actually used.



Pre-generating every possible size for every possible layout just isn't practical.



What I wanted instead was something like this: declare the sizes you need, and let them materialize on demand.



To make this work safely and efficiently, the system had to satisfy a few constraints:




  • Uploads must remain fast

  • Page loads must not block on image resizing

  • Only requested sizes should be generated

  • Arbitrary resize requests must be impossible

  • Generated images must become permanent static files



The architecture that ended up satisfying all of these requirements is what I call lazy-load image resizing.









The Architecture: Lazy-Load Image Resizing



The core idea is simple: generate resized images only when they are first requested.



But instead of creating an explicit resize endpoint, the trigger is a missing file (404).



Here's the full lifecycle:




Browser requests:
/uploads/photos/480x480/my-image.webp?key=a1b2c3

Web server checks: Does this file exist?

├── YES → Serve static file
└── NO → Pass request to application
→ Validate resize pattern + security key
→ Locate original image
→ Generate resized version
→ Save to disk
→ 302 redirect to the now-existing file






The key property is this: after the first request, the application is never involved again. The web server serves the resized file directly like any other static asset.









Step 1: Smart URL Generation with Signed Keys



The first step is a helper that generates the URL where the resized image would exist, even if it hasn't been generated yet.




function img_url(string $path, int $width, int $height): string {

$resizedUrl =
dirname($path)
. "/{$width}x{$height}/"
. pathinfo($path, PATHINFO_FILENAME)
. '.webp';

$key = hash_hmac('sha256', $resizedUrl, $yourSecretKey);

return $resizedUrl . '?key=' . substr($key, 0, 16);
}






Example:




Original:      /uploads/photos/my-image.jpg
Generated URL: /uploads/photos/480x480/my-image.webp?key=a1b2c3






Three important things happen here.






1. Size Encoded in the Path






/uploads/photos/480x480/my-image.webp






The directory contains the dimensions. This makes the filesystem naturally act as a cache.






2. Format Conversion



All resized images are saved as WebP, regardless of the original format. This typically reduces file size by 25–35% compared to JPEG.






3. Signed URLs



The HMAC signature prevents malicious resize requests. Without signing, someone could request:




/uploads/photos/99999x99999/image.webp






...and force your server to process huge images. Signing ensures:




  • Only your application can generate valid resize URLs

  • Width/height tampering invalidates the request









Step 2: The 404 Handler



When the browser requests an image that doesn't exist yet, the web server forwards the request to your application. Your 404 handler detects whether the request is a resize request.




function handle404(Request $request)
{
$path = $request->getPath();
$ext = pathinfo($path, PATHINFO_EXTENSION);

if (!in_array($ext, ['jpg','jpeg','png','webp'])) {
return show404();
}

if (!preg_match('/\/(\d+)x(\d+)\//', dirname($path), $matches)) {
return show404();
}

$expectedKey = hash_hmac('sha256', $path, $yourSecretKey);

if (substr($expectedKey, 0, 16) !== $request->getQuery('key')) {
return show404();
}

$width = (int) $matches[1];
$height = (int) $matches[2];

$originalPath = str_replace("/{$width}x{$height}", '', $path);

foreach (['jpg','jpeg','png','webp'] as $tryExt) {

$candidate = preg_replace('/\.\w+$/', ".{$tryExt}", $originalPath);

if (file_exists($candidate)) {

resize_image($candidate, $path, $width, $height);

return redirect($path);
}
}

return show404();
}






Key details:




  • Invalid signatures return a normal 404

  • Original format is automatically detected

  • After resizing, the server issues a 302 redirect









Step 3: The Resize Function



The actual resizing logic can use any image library. Here's an example using Intervention Image:




function resize_image(
string $source,
string $destination,
int $width,
int $height
): void {

adjust_memory_for_image($source);

$img = ImageManager::read($source);

$img->scaleDown($width, $height);

@mkdir(dirname($destination), recursive: true);

$img
->toWebp(quality: 85)
->save($destination);
}






Key decisions:





  • scaleDown() prevents upscaling

  • Everything is converted to WebP









Step 4: Web Server Caching



Once generated, the resized file should behave like immutable static content.



Apache:




<filesMatch "\.(webp|jpg|jpeg|png|gif)$">
Header set Cache-Control "max-age=84600000, public, immutable"
</filesMatch>

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [L,QSA]






Nginx:




location ~* \.(webp|jpg|jpeg|png|gif)$ {
expires max;
add_header Cache-Control "public, immutable";
try_files $uri /index.php?$query_string;
}






The key directive is immutable. This tells the browser: this file will never change at this URL. So returning visitors often don't even make a network request.









The Complete Flow



First Request:




  1. Template outputs srcset URLs

  2. Browser requests resized image

  3. File doesn't exist → application generates resized image

  4. 302 redirect → browser receives static file



Second Request:




  1. File exists → web server serves it directly

  2. No application code involved



Returning Visitor:




  1. Image already cached → no network request at all









Performance Comparison











































Aspect Traditional Lazy Resize
Upload time Slow Fast
First page load Fast One resize per size
Later page loads Static Static
Disk usage All sizes Only used sizes
Output format Original WebP
Security Often open Signed URLs








Trade-offs



No solution is perfect.



Cache Cleanup: Replacing or deleting an image leaves resized variants on disk. Your upload/delete workflow should remove those directories.



First Request Penalty: The first visitor requesting a size triggers a resize. In practice this is usually sub-second, but it exists.



Disk Growth: Over time the cache directories accumulate generated images. A periodic cleanup job may help.









Key Takeaways



Let the web server do the heavy lifting. Once generated, images are served as static files.



404 handlers can be powerful. Missing files become a trigger for lazy-load generation.



Always sign resize URLs. Otherwise your resize endpoint becomes a DoS vector.



Convert images during resizing. This allows you to deliver modern formats like WebP automatically.



Keep uploads simple. Store the original image and generate everything else lazily.



In practice this pattern gives you the best of both worlds: fast uploads, minimal storage waste, and static-file performance after the first request. And the implementation is surprisingly small.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How I Solved Lazy Image Resizing Without Slowing Down the Page Load

Thematisch verwandte Begriffe: Solved, Lazy, Image, Resizing · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94142 | A security vulnerability has been detected in BioStar Temperature Monito…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick