Image and video hosting with transformation in the URL: resize, crop, convert format and optimise on the fly, cached at the edge.
Build me image and video delivery that replaces Cloudinary — and know why this is ALMOST. Resizing images is easy. Three things are not: **format negotiation** that serves AVIF, WebP or JPEG based on what each browser actually accepts, **smart cropping** that keeps the subject in frame at any aspect ratio, and **video transcoding** into the ladder of qualities a player needs. The first two are an afternoon each. The third is where the effort and the machine cost really are — read that section before committing. STACK - Node 20+ with Fastify - sharp for images, ffmpeg for video - SQLite through better-sqlite3 for the asset index and the transform cache - Local disk or an S3-compatible bucket, with a CDN in front - Caddy in front THE DATA MODEL - assets: id, public_id, kind, original_path, sha256, bytes, width, height, duration_ms, format, colour_profile, focal_x, focal_y, created_at, deleted_at - derivatives: id, asset_id, transform_hash, params_json, format, path, bytes, width, height, created_at, hits - video_renditions: id, asset_id, height, bitrate, codec, path, bytes, status - uploads, folders, tags — the ordinary library shape - Every derivative is regenerable from the original, so the original is what gets backed up and the derivatives do not THE URL - Transformations expressed in the path: width, height, fit mode, quality, format, gravity, and effects - **Signed.** An unsigned transform URL means anybody can request ten thousand sizes of your images and use your machine as a free rendering farm. Sign the parameters, or maintain an allow-list of named presets — the second is better, because it also stops your own templates from inventing forty variants of the same image - Cached by transform hash, with immutable headers and a content hash in the path - Generated once, on first request, then served from the cache forever FORMAT NEGOTIATION - Read the browser's Accept header and serve AVIF where accepted, then WebP, then the original format. Vary on Accept so the CDN caches each separately, or the wrong format will be served to somebody - AVIF is meaningfully smaller and much slower to encode. Encode it lazily and in the background, serving WebP until it is ready - Quality chosen by a perceptual target rather than a fixed number, measured once per image and cached — quality 80 is wasteful on a flat illustration and visibly poor on foliage SMART CROPPING - A focal point stored per asset, set by hand in the interface, is the cheapest and most reliable answer and it covers most cases - Automatic: face detection, or a saliency heuristic based on edge density and contrast, to propose a focal point that a human confirms - Never crop automatically without a stored focal point on anything user-facing. A logo cropped in half is worse than a letterboxed image VIDEO, WHICH IS THE EXPENSIVE PART - A ladder of renditions — several heights and bitrates — packaged as HLS or DASH so a player can adapt to the connection - Transcoding is CPU-hours per video. Queue it, cap the concurrency, and be honest about the machine cost. This is the part where the hosted service starts to look reasonable - A poster frame, and a short preview clip for hover, both generated automatically - Store the original untouched, always DELIVERY - Put a CDN in front. Serving media from one machine is the mistake that makes everything feel slow, and it is the one part of this that money genuinely solves - Correct cache headers, range support, and a stale-while-revalidate policy on derivatives OPERATIONS - .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, SIGNING_SECRET, CDN_URL, TRANSCODE_CONCURRENCY - Migrations on boot, each once - Disk watchdog, and a sweeper for unused derivatives by last hit - Backup the originals; derivatives are regenerable - Health endpoint that runs one transform through the real path WHAT MATTERS MOST Signed or named transforms, and Vary on Accept. Get those two wrong and you have either an open rendering farm or a cache serving AVIF to a browser that cannot read it.
What you lose
- Format negotiation that serves AVIF, WebP or JPEG based on what the browser actually accepts
- Smart cropping that keeps the subject in frame at any aspect ratio
- Video transcoding into a ladder of resolutions, which is genuinely heavy work
If you would rather not build
- Thumbor, the long-standing option
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $89/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
imgproxy
$0Fast on-the-fly image resizing with signed URLs, one binary.
imgproxy/imgproxyfree · open source
Why this verdict
our own opinion · changed only by a person
58/100
Verdict kinda at 58. Images are a weekend with sharp; video transcoding and smart cropping are what keep this from being a yes.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Cloudinary
answered from the record above
Is Cloudinary free?
No — the plan we track is $89 a month. Plus from around $89/month billed monthly, priced on credits covering storage, transformations and bandwidth.
Can you replace Cloudinary by building your own?
ALMOST. A weekend of work, and real gaps remain. Replacement score 58 out of 100, build time a weekend. Read what you lose before you decide.
How much does Cloudinary cost?
$89 a month on Plus — $1,068 a year. Recorded 10 Aug 2026.
What do you lose by replacing Cloudinary?
Format negotiation that serves AVIF, WebP or JPEG based on what the browser actually accepts; Smart cropping that keeps the subject in frame at any aspect ratio; Video transcoding into a ladder of resolutions, which is genuinely heavy work. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Cloudinary?
Yes: imgproxy, sharp. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

