Compressing Images Before Storage in Laravel

When users upload images to a web app, raw uploads can easily be several megabytes each. Multiply that by hundreds of uploads and you’ve got a storage and bandwidth problem. Pages load slower, backups get bigger, and hosting costs climb. The straightforward way to fix it is by compressing images before they hit storage, not after.

This post walks through how I added compression to the upload flow for my Laravel Project, why I picked the package I did, and what the actual size difference looked like.

The Problem

Before adding compression, a typical uploaded photo from a phone camera came in at a range of 2-8 MB. Multiplied across a product catalog / gallery / whatever your app stores, that adds up fast to both in disk usage and in how long the image takes to load on the frontend.

Picking a Package: Intervention Image vs Spatie

There are 2 common options in the Laravel ecosystem:

  • Intervention Image: a general-purpose image manipulation library (resize, crop, compress, format conversion). Good when you need more than just compression, e.g. thumbnails, watermarks, format conversion.
  • Spatie’s Image: more opinionated, integrates well if you’re already using Spatie’s media library for file handling, but adds a heavier dependency if you’re not.

In this case, I went with Spatie because i was already using another Spatie package in the project and wanted to stay consistent

How to implement Spatie to your project:

1. Initial Setup

composer require spatie/image
composer require spatie/laravel-image-optimizer

spatie/laravel-image-optimizer shells out to system binaries, so they need to be installed on the server too:

sudo apt install jpegoptim optipng pngquant gifsicle
npm install -g svgo

2. PHP file

Here’s the core of the upload handler:

use Spatie\Image\Image;
use Spatie\ImageOptimizer\OptimizerChainFactory;

public function store(Request $request)
{
    $request->validate([
        'image' => 'required|image|max:10240', // 10MB raw upload limit
    ]);

    $file = $request->file('image');
    $filename = uniqid() . '.' . $file->getClientOriginalExtension();
    $path = storage_path('app/public/uploads/' . $filename);

    // 1. Resize with Spatie Image
    Image::load($file->getRealPath())
        ->width(1600)
        ->quality(75)
        ->save($path);

    // 2. Run the resized file through the optimizer binaries
    OptimizerChainFactory::create()->optimize($path);

    return response()->json(['path' => 'uploads/' . $filename]);
}

Key decisions here:

  • Resize cap at 1600px wide: most display contexts don’t need anything larger; this alone often cuts file size more than compression quality does.
  • Quality 75: set at the resize step; a common sweet spot for JPEG, visually near-identical to 90+ but meaningfully smaller.
  • Optimizer pass after resizing: spatie/image handles the resize/quality change, then laravel-image-optimizer runs the already-resized file through format-specific tools (pngquant for PNGs, jpegoptim for JPEGs, etc.) for a further size cut without visible quality loss. Doing it in this order avoids wasting optimizer time on a full-size original.

Here’s the comparison of original (868KB) vs compressed (179KB) image size:

Trade-offs

Compression is not free:

  • CPU cost on upload: resize + optimizer binaries both run synchronously in the request in the code above. The optimizer step in particular shells out to external processes, which is slower than a pure in-memory library call.
  • Server dependency: unlike Intervention Image (pure PHP), laravel-image-optimizer depends on system binaries being installed and on PATH. That’s an extra deployment step (and an extra thing that can silently fail in a Docker image or shared host that’s missing them).
  • Format limits: this approach assumes JPEG/PNG; if you accept HEIC (common from iPhones), you may need an extra conversion step before Spatie’s Image can process it.

Takeaway

Compress on upload, not on serve: you only pay the CPU cost once instead of on every request. Cap dimensions before you touch quality settings; resizing usually buys you more size reduction than lowering JPEG quality does.

Book a Free Consultation

Haven’t found the right solution yet?
Tell us about your needs, and let’s discuss the best solution together.

Project description.

Built a private marketplace research and purchase planning platform for Shopee. The system tracks product performance over time, estimates sales velocity and gross revenue, analyzes demand across product variants, and turns the research into actionable purchasing plans. It also calculates supplier costs, shipping, platform fees, margins, planned investment, and estimated earnings to support data-driven sourcing decisions.

Skills and deliverables

Full-Stack Development, Web Application Development, Data Analysis, Business Process Automation, Business Intelligence

Shopee Marketplace Research & Purchase Planning Dashboard

We built this application to solve a common problem in marketplace sourcing: finding products is easy, but deciding what is actually worth buying, which variant to prioritize, and how much inventory to purchase requires much more analysis. Instead of relying on a single product snapshot, the system organizes products into research collections and tracks their marketplace performance over time.

Product research & tracking

Products can be added individually or collected from marketplace stores and organized into dedicated research collections. The system keeps historical observations so users can compare changes between captures instead of relying only on the latest marketplace data. This makes it possible to estimate metrics such as: – Sales velocity – Estimated daily gross revenue – Price changes – Product movement over time – Variant-level demand

Variant demand analysis

One of the most important parts of the system is identifying which variants are actually driving sales. Instead of treating a product as a single item, the application analyzes sales movement at variant level and shows each variant’s contribution to recent demand. This helps identify which sizes, models, or variations should be prioritized when purchasing inventory.

Purchase planning

Research data can then be converted directly into a purchasing plan. For every product and variant, the user can enter supplier pricing, shipping costs, purchase quantities, exchange rates, and other operational costs. The system automatically calculates: – Planned inventory investment – Shipping cost – Marketplace/platform fees – Net margin per unit – Net margin percentage – Estimated earnings – Total batch investment This allows purchasing decisions to be evaluated before committing capital.

Why We built it

The goal was to replace a workflow that would normally require multiple spreadsheets, manual marketplace checks, and repeated calculations. The resulting workflow became: Discover products → Track performance → Analyze demand → Select variants → Plan purchasing → Estimate margins Everything is kept in one application, making the research and sourcing process easier to review, repeat, and scale.

Result

The platform turns raw marketplace observations into actionable purchasing information. Instead of choosing products based only on intuition or current sales numbers, users can evaluate sales movement, variant demand, sourcing cost, expected margin, and required investment before making a purchasing decision. Built as an end-to-end internal tool, from data collection and analysis to the final purchasing workflow.

Project description.

Built a browser-based tool that converts Shopee/SPX order exports into clean, print-ready shipping labels. It supports multiple Excel/CSV files, combines orders into one preview, and automatically generates QR codes, barcodes, tracking numbers, and product information for 68 mm thermal printers. All order data is processed locally in the browser for better privacy, eliminating repetitive manual label formatting.

Skills and deliverables

Laravel, Business Automation, CSV, Microsoft Excel

Shopee SPX Order Label Maker for Thermal Printing

This tool was built to simplify the shipping label preparation process for Shopee SPX orders. The existing workflow required order data to be exported from Shopee and manually formatted before it could be printed on a thermal printer. This became repetitive and time-consuming, especially when processing multiple orders at once.

We built a browser-based label generator that reads Shopee Excel/CSV exports and automatically converts the order data into clean, print-ready SPX labels. The tool automatically handles: – Tracking numbers – QR codes – Barcodes – Product names and variants – Order quantities – Multiple order files at once – 68 mm thermal printer formatting Users can review all generated labels before printing, without having to manually copy or reorganize the order information.

The order files are processed directly inside the browser instead of being uploaded to a server. This keeps customer and shipment data private while also making the tool fast and simple to use.