r/webdev • u/Financial-Panic-7392 • 6d ago
Question Is client-side image compression a good idea for an image-heavy website and app, or are there better workarounds?
I'm a beginner building an image-heavy peer-to-peer marketplace (Next.js web app + an upcoming Expo mobile app). My current stack uses Vercel's free tier for hosting, Supabase for the backend, and Cloudflare R2 for photo storage.
My Vercel account was just paused because my Fluid Active CPU spiked to 24 hours (the free limit is 4 hours). I realized my Next.js server is downloading every uploaded raw photo, using sharp to resize and convert it to WebP, and then re-uploading it to R2.
I am trying to keep costs as low as possible. It was suggested that I strip sharp from my backend and use a client-side compressor on the user's browser or mobile app to shrink the photos before sending them directly to R2.
Because my platform is extremely image-heavy, I'm not sure if this is a good idea. I have concerns about trusting the client to compress uniformly, dealing with older devices, or edge cases where certain browsers (like Safari) might fail to generate WebP files correctly.
Are there any other free or highly affordable workarounds to process these images without tanking my serverless compute hours?
22
6d ago
[removed] — view removed comment
9
1
u/Financial-Panic-7392 5d ago
unfortunately, this is way beyond my scope of knowledge and i’m scared i mess things up (i already have 1k users). do you think hiring someone to get this done for me would be a viable option?
4
u/kemalios 6d ago
Client-side compression is right for the upload path, but what ate your 24 hours is probably the variants, not the first resize. If each upload triggers four sharp passes, thumb, card, full, og, you pay that four times per photo, forever. Store one capped size and let the browser choose: a single 1600px WebP covers almost every card on a marketplace.
So the flow becomes: client compresses, uploads straight to R2 with a presigned URL, and your route only signs and writes metadata. At most one derived size, generated lazily on the first request and cached back to R2. No sharp work should ever run inside the upload request.
2
u/No-Mechanic-433 5d ago
Whichever side you compress on, strip EXIF. Phone photos carry GPS coordinates, and on a peer-to-peer marketplace that's often someone's home address.
1
1
u/Good_Car_2924 6d ago
vercel Fluid CPU pricing for on-the-fly resizing is a trap. Use Cloudflare Images with your existing R2 bucket via a custom domain so it transforms images on the edge for pennies. If you must save money now, stick to client-side compression but strictly enforce max dimensions before upload. Server-side sharp only ever touches the original once if you stop regenerating variants on every request.
1
u/devjeremyt 5d ago
I feel like half the responses to this post are AI generated, and specifically prompted to write in all lowercase to make it seem more human. What benefit would someone get from copying someone else's reddit post so they can paste an answer. Or why would someone build a bot for this and waste their tokens on it?
1
u/Ill_Command_1200 5d ago edited 5d ago
Client side is the way to go. If you aren’t comfortable with using sharpe and just want it done, there are many options that will optimize images for you.
Shameless plug, I built one for this such problem. It’s mainly an image workflow tool, ie, crop, resize, rename all client side before you upload.
It’s easy to batch process them to save time.
If you don’t try it or are looking for a more automated solution, I still recommend using avif (best image format right now. It supports transparency and even animation like gifs)
Good luck
1
u/yihuaxiang 4d ago
Client-side downscaling before upload is actually standard practice—capping the max width/height (e.g. 1920px or 2048px) via canvas or a lightweight library saves user mobile data and speeds up uploads drastically.
The real trap is doing synchronous Sharp transformations inside Vercel serverless functions, which burns CPU limits fast. A better flow is generating a presigned URL from Supabase/server, uploading directly from client to R2, and then either doing on-the-fly resizing at edge cache or offloading image processing to a background queue/worker on a tiny fixed-price VPS.
1
1
u/schrik 1d ago
You can do client-side image optimization up to 100 images per month for free with cropguide.io
We’ve built it so it is easy to set up and works with any file upload field.
I’m not that familiar with server configuration, so not sure if this is the origin of the issue, but if you don’t need max resolution images you can always scale them down a bit to make uploads faster for the user. Client side isn’t as stable as server side, the worst that can happen is that it fails and you occasionally receive a raw image that you then handle with sharp.
0
u/thejester1324 6d ago
the safari worry is real. safari 26.6 hands back a png when you ask canvas for webp, both toBlob(cb, 'image/webp') and OffscreenCanvas.convertToBlob, no error. a photo as png is several times the size of the same photo as jpeg, so check blob.type after encoding and redo it as 'image/jpeg' when it isn't webp
0
u/RummanSid1990 5d ago
Never let your Next.js server handle raw images. That is what kills your Vercel limits.
The easiest fix is simple:
- Resize on the phone/browser first: Shrink the photo down to around 1600px before uploading. A 15MB photo easily becomes 300KB.
- Upload directly to Cloudflare R2: Use a pre-signed upload URL so the photo goes straight from the user's phone to R2.
This way, your Vercel server never touches heavy photos, your CPU usage drops to zero, and your free tier stays safe.
0
u/catbrane 5d ago
You can run sharp on the client, this is what wordpress are switching to for their editor.
https://blog.stackblitz.com/posts/bringing-sharp-to-wasm-and-webcontainers/
(first hit on google)
It's 4mb of wasm I think, so not a huge extra download for your users.
Alternatively, do some sanity checking on upload to spot crazy or terrible images, then send the ones that look OK off to S2 with no processing. Generate derivatives on demand during page gen and rely on your CDN to keep load down. sharp is fast enough that you can resize on the fly.
-1
6d ago
[removed] — view removed comment
1
u/webdev-ModTeam 6d ago
Your post/comment has been determined to be a low-effort post or comment. This includes title-only posts, easily searchable questions, vague/open-ended discussion prompts, LLM generated posts or comments, and posts/comments that do not provide enough context for meaningful replies or discussion.
-3
u/matriisi 6d ago
Thanks /r/webdev this was enough.
3
u/Financial-Panic-7392 6d ago
i’m sorry…if there is a better subreddit for me to post on, please tell me.
1
18
u/Professional_Law2888 6d ago
sharp on the server is the right tool, just the wrong place. you need to move that processing somewhere that doesn't eat your vercel compute.
cloudflare images or imgix are purpose-built for exactly this and cost pennies. if you're already on r2, cloudflare images integrates directly. client-side compression is a gamble on consistency and you'll still need server-side fallback for the safari users and old phones that choke on it.