Sharp (Node.js) Integration for Server-Side Image Processing

Sharp — Fast Image Processing Without Compromises

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1418
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1286
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    983
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1243
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    998

Sharp — Fast Image Processing Without Compromises

Server-side image processing becomes a bottleneck when users upload RAW photos from cameras or 12MP images from phones. Jimp consumes 200+ MB per image, ImageMagick requires system installation and is unstable under load. We encountered a project where 10 concurrent uploads crashed the server due to OOM. The solution is Sharp based on libvips. It processes images in a streaming fashion without loading the full file into memory, and is 4–5 times faster than alternatives.

Why Sharp Is Faster Than Alternatives

Sharp doesn't hold the entire file in memory — it parses it in chunks, applies operations, and writes the result immediately. This halves memory consumption under the same load. Compare with ImageMagick: it converts via temporary files on disk, slowing down high-load systems. In our tests, Sharp processed 1000 images (1920×1080 → 800px WebP) in 12 seconds — ImageMagick took 38 seconds.

Library Memory per image Conversion time (1000 images)
Sharp 20–30 MB 12 s
Jimp 150–250 MB 45 s
ImageMagick 100–150 MB + I/O 38 s

How Sharp Protects Against Decompression Bombs

A decompression bomb is an image with enormous dimensions (e.g., 100k×100k pixels) that would allocate all memory if fully loaded. Sharp lets you check metadata before full loading: call metadata() and reject the file if width × height exceeds a limit (e.g., 50 MP). This prevents OOM without extra overhead.

How We Implement the Integration

On one project (an online clothing store), we needed to automatically convert uploaded photos to WebP in multiple sizes, preserve EXIF for SEO, and prevent decompression bombs. We built a pipeline:

  1. Multer saves the file in memory (buffer).
  2. Sharp reads metadata — if area > 50 MP, reject.
  3. Apply .rotate() for auto-rotation based on EXIF.
  4. Use clone() to create three branches: thumbnail (150×150 cover), medium (800px), large (1920px).
  5. Each branch converts to WebP (quality 82, effort 4) and saves to S3.
  6. Return JSON with URLs.

Result: upload time dropped from 3 seconds to 0.8, the server handles 50 concurrent requests.

Choosing a Format: WebP or AVIF?

Format Compression vs JPEG Browser support (2025) CPU consumption
WebP ~30% smaller 96% Moderate
AVIF ~50% smaller 87% High
JPEG XL ~60% smaller 10% Medium

For most projects, WebP offers the optimal balance. AVIF is chosen when file size is critical and CPU is abundant.

Concurrency configuration in production

Sharp uses all CPU cores by default, which can overload the server. We recommend limiting:

sharp.concurrency(2) // two threads 

Also use a queue via p-limit to control concurrent processing, controlling concurrency.

Process

  • Analysis: audit current pipeline, measure load, define target formats and resolutions.
  • Design: choose caching strategy (CDN, Cache-Control headers), configure pipeline for your stack (Express, S3, Cloudflare).
  • Implementation: write code with error handling, decompression bomb protection, integration with Multer or busboy.
  • Testing: load test with 1000 images, verify all formats and resolutions.
  • Deployment: documentation for rollout, monitoring (processing time, memory metrics).

Timeline: approximately 2 to 5 business days depending on integration complexity (number of formats, S3, watermark). Pricing is individual after auditing your project. Savings on server resources — up to 70% on CPU and memory.

What's Included

  • Ready image processing pipeline (resize, conversion, watermark).
  • Integration with your web server (Express, Fastify, Next.js API routes).
  • Deployment and configuration documentation (environment variables, Sharp fork limits).
  • Access to the code repository.
  • 2-week support guarantee after delivery.

Common Integration Mistakes

  • Forgetting concurrency: Sharp uses all cores — in production, limit sharp.concurrency(2) and queue via p-limit.
  • Not verifying format via metadata: MIME type can be faked. Sharp automatically detects the real format — use meta.format.
  • Keeping EXIF with GPS: for public publication, remove metadata .withMetadata(false), otherwise there's a risk of coordinate leakage.

We'll evaluate your project for free — just send your current processing code. Get advice on image optimization without purchasing expensive libraries.

// Example pipeline with decompression bomb protection async function safeProcess(buffer) { try { const meta = await sharp(buffer).metadata() if (meta.width * meta.height > 50_000_000) { throw new Error('Image too large: exceeds 50MP limit') } return await sharp(buffer) .rotate() .resize(2000, 2000, { fit: 'inside', withoutEnlargement: true }) .webp({ quality: 82 }) .toBuffer() } catch (err) { if (err.message.includes('Input buffer contains unsupported image format')) { throw new TypeError('Unsupported image format') } throw err } } 

Our expertise: 10+ years in web development, 50+ projects with Sharp integration. We guarantee compatibility with your stack.