Image processing pipelines with Sharp in Node.js
2 min read
By Juliano Alves
Sharp wraps libvips for fast image transforms in Node: resize, crop, composite, and output to WebP, AVIF, PNG, JPEG. It is the backbone of next/image on many deployments and works well in standalone upload workers.
Resize and format
import sharp from 'sharp';
await sharp(inputBuffer)
.resize(1280, 720, { fit: 'inside', withoutEnlargement: true })
.webp({ quality: 80 })
.toFile('out.webp');
Streaming
For large uploads, pipe streams to avoid buffering entire files in RAM:
import fs from 'node:fs';
const pipeline = fs.createReadStream('in.jpg').pipe(
sharp().resize(800).webp(),
);
pipeline.pipe(fs.createWriteStream('out.webp'));
Concurrency limits
Each transform uses memory proportional to decode width/height. In worker pools, cap concurrency (e.g. p-limit) so spikes do not OOM the pod.
Metadata stripping
Strip EXIF for privacy unless you explicitly need orientation tags—rotate() based on EXIF when retaining.
Summary
Sharp is the pragmatic choice for server-side thumbnails and responsive variants. Tune quality/size tradeoffs with real assets and enforce memory-safe concurrency in workers.