DEV Community

Cover image for Your Image Converter Probably Doesn't Need Your Image on a Server
Muhaymin Bin Mehmood
Muhaymin Bin Mehmood

Posted on

Your Image Converter Probably Doesn't Need Your Image on a Server

Most online file tools follow the same architecture:

Choose file
   ↓
Upload file
   ↓
Server processes it
   ↓
Server stores a temporary result
   ↓
Download result
Enter fullscreen mode Exit fullscreen mode

That architecture is valid.

But for many image operations, it is not always necessary.

Modern browsers can decode, transform, and export common image formats locally. That means some tools can work without sending the original image to a backend at all.

This changes the architecture in an interesting way.

Choose file
   ↓
Browser reads it locally
   ↓
Browser transforms it
   ↓
Download result
Enter fullscreen mode Exit fullscreen mode

No upload step.

For the right use case, that is a meaningful improvement.

Why client-side processing is attractive

1. Privacy

If the file does not need to leave the device, you remove an entire category of questions:

  • Where is the file stored?
  • For how long?
  • Is it logged?
  • Is it copied to object storage?
  • Is a third-party processor involved?
  • Is cleanup actually happening?

Client-side processing does not magically make an application secure, but it can reduce the amount of sensitive data that needs to cross the network.

For personal photos, unreleased marketing assets, client work, screenshots, and internal images, that matters.

2. Less upload latency

Uploading a 2 MB file is usually fine.

Uploading 100 files is a different experience.

If the transformation can happen locally, the user does not need to wait for:

upload → server queue → processing → download
Enter fullscreen mode Exit fullscreen mode

before seeing a result.

Network conditions become less important.

3. Lower backend cost

If your backend is doing CPU-heavy conversion for every free user, infrastructure cost scales directly with usage.

Moving suitable work to the client can reduce:

  • CPU usage
  • temporary storage
  • bandwidth
  • queue pressure

This is especially interesting for free utility tools where the server cost of a single action can be larger than the revenue generated by that user.

4. Better offline potential

A browser tool that does not depend on a processing API can sometimes continue working even when connectivity is limited, depending on how the app itself is delivered and cached.

That is a very different user experience from a server-only tool.

What can the browser actually do?

For common formats, browser APIs can already handle a surprising amount.

Typical building blocks include:

  • File
  • Blob
  • FileReader
  • createImageBitmap()
  • <canvas>
  • OffscreenCanvas
  • Web Workers

A simplified flow can look like:

const file = input.files[0];

const bitmap = await createImageBitmap(file);

const canvas = document.createElement("canvas");
canvas.width = bitmap.width;
canvas.height = bitmap.height;

const ctx = canvas.getContext("2d");
ctx.drawImage(bitmap, 0, 0);

const result = await new Promise(resolve => {
  canvas.toBlob(resolve, "image/webp", 0.82);
});
Enter fullscreen mode Exit fullscreen mode

This is intentionally minimal, but the important idea is that the image can be decoded and re-encoded without a traditional upload-processing-download cycle.

The hard part is not the demo

A one-file demo is easy.

Production behavior is harder.

You have to think about:

  • memory usage
  • large dimensions
  • EXIF orientation
  • transparent images
  • browser support
  • output quality
  • cancellation
  • progress reporting
  • multiple files
  • UI responsiveness

If a user drops 200 high-resolution photos into the browser and you decode everything simultaneously, you can easily destroy the tab.

So "client-side" does not mean "process everything at once."

Controlled concurrency matters

A safer batch architecture uses a queue.

Instead of:

await Promise.all(files.map(processImage));
Enter fullscreen mode Exit fullscreen mode

you may want a controlled number of active jobs.

Conceptually:

200 files waiting

Worker 1 → image
Worker 2 → image
Worker 3 → image
Worker 4 → image

Complete one → take next
Enter fullscreen mode Exit fullscreen mode

The correct concurrency depends on workload and device capabilities.

The goal is not maximum parallelism.

The goal is useful throughput without making the browser unusable.

When a server is still the better choice

Client-side processing is not a religion.

There are many cases where a backend is appropriate or required:

  • unsupported codecs
  • extremely large files
  • expensive AI models
  • server-side persistence
  • shared team workflows
  • centralized processing rules
  • conversions that require native libraries
  • jobs that must continue after the tab closes

The architecture should follow the job.

A product-design consequence

Once basic image conversion can happen locally, the product can make a stronger promise:

"Your common image conversions do not need to be uploaded for processing."

That was one of the design goals behind the basic image workflows I am building in BatchSet.

You can try the Image Converter or the Bulk Image Converter.

I am mentioning it because it is the real product where I have been exploring this architecture, not because every transformation inside every application should be client-side.

The broader lesson

Before adding another API endpoint, queue, storage bucket, and cleanup job, ask one question:

Does the server actually need this file?

Sometimes the answer is yes.

Sometimes the browser is already powerful enough to do the job closer to the user.

And when the answer is "the browser can do it," you may get privacy, speed, and infrastructure benefits at the same time.

Top comments (0)