Infrastructure

Self-Hosted Image Transformation with Repix

Run Repix on Fly.io for $3.19/month and skip per-transformation fees. A cost comparison with Cloudflare Images at 100,000 transforms.
Jiten Bansal

Jiten Bansal

Fractional CTO and AI consultant.

Every app that serves user-uploaded photos eventually needs image resizing, cropping, and format conversion. Managed CDNs like Cloudflare Images solve this well — until your traffic grows and the meter starts running.

Repix is a self-hosted image transformation service I built for teams that want URL-based transforms without SDK lock-in or per-request billing. Resize, crop, and convert images on the fly via a simple path pattern. Deploy it once, pay a flat monthly fee, and keep your storage backend hidden behind your own domain.

What Repix does

Repix fetches images from any public HTTPS origin and transforms them at request time:

https://img.yourdomain.com/sm/cdn.example.com/photos/hero.jpg

The sm preset maps to w=128,q=85. No SDK, no upload pipeline — just URLs.

Out of the box you get:

  • Preset systemxs through xl, plus full and a blur placeholder for LQIP
  • Modern formats — JPEG, PNG, WebP, and AVIF with automatic conversion
  • Security controls — dimension limits, fetch timeouts, preset-only mode, and hostname allowlists
  • Docker-ready — multi-stage Dockerfile, deployable to Render, Railway, Fly.io, or Cloudflare

Your S3 bucket, R2 store, or CDN origin stays invisible. Users see img.yourdomain.com, not bucket.s3.amazonaws.com.

Why self-host?

Managed image services are convenient at small scale. Self-hosting wins when you care about predictable costs, control, and portability.

BenefitWhat it means
Flat pricingOne server bill regardless of how many transforms you serve
Your domainImage URLs and referrers show your brand, not a third-party CDN
Any originMix S3, R2, and other HTTPS sources in the same instance
No vendor lock-inMove hosts, change presets, or fork the code — it's yours
Abuse controls you ownCap dimensions, restrict presets, block slow origins
Use ALLOW_CUSTOM_TRANSFORMS=false with a tight PRESETS config to prevent open-proxy abuse. Pair it with SOURCE_HOSTNAME to allowlist only your storage domains.

Deploy on Fly.io for $3.19/month

Repix is a lightweight Node service. A single Fly Machine with 512MB RAM is enough for most personal sites and small SaaS apps.

On Fly.io's pricing page, a shared-cpu-1x Machine with 512MB RAM costs $3.19/month when running continuously. That's the entire compute bill — no per-transformation surcharge on top.

A minimal deployment looks like this:

  1. Build and push the Repix Docker image (or use the published one)
  2. Create a Fly app in a region close to your users
  3. Set environment variables: PRESETS, IMAGE_MAX_WIDTH, CORS_ORIGIN
  4. Attach a custom domain like img.yourdomain.com

Repix caches transformed output, so repeated requests for the same preset and source image don't re-run the pipeline. For a blog or product catalog, a 512MB instance handles thousands of daily transforms comfortably. For heavier traffic, scale horizontally — Fly.io lets you run up to 5 parallel Machines behind the same app.

Cost comparison: 100,000 transformations

Here's where self-hosting gets interesting. Cloudflare Images charges for unique transformations — one image plus one parameter set, counted once per calendar month. Repeat requests for the same combo don't add to the bill.

Assume you need 100,000 unique transformations per month (e.g. 10,000 images × 10 size variants, or a catalog that generates a new crop for each product view).

Repix on Fly.ioCloudflare Images
Base cost$3.19/month (512MB Machine)$0 (Free plan) or Paid plan subscription
Transform pricingIncluded — unlimited within server capacityFirst 5,000 included, then$0.50 / 1,000
Billable transforms95,000
Transform cost$0$47.50
Total (transforms only)~$3.19~$47.50

That's roughly 15× cheaper for this volume, and the gap widens as transforms grow. At 500,000 unique transforms, Cloudflare Images costs around $247.50/month in transformation fees alone. Repix still costs $3.19 on a single Machine — or run up to 5 parallel instances for high workload (~$16/month total) — but you're never paying per thousand.

Cloudflare's free tier includes 5,000 unique transformations per month. Beyond that, new transforms fail with error 9422 unless you're on the Paid plan. Repix has no monthly transform cap — only the limits you configure.

When Cloudflare Images still makes sense

Self-hosting isn't always the answer:

  • Under 5,000 unique transforms/month — Cloudflare's free tier costs nothing
  • You want zero ops — no Machines to monitor, no Docker deploys
  • Global edge caching built in — Cloudflare's network is hard to replicate on a single Fly region

But if you're consistently above the free tier — especially past 20,000–50,000 unique transforms — a $3.19 Fly Machine running Repix is the better economics.

Clean URLs with presets

One of Repix's best features is readable URLs. Compare:

# Clean — preset name
https://img.yourdomain.com/card/cdn.example.com/photo.jpg

# Verbose — inline parameters
https://img.yourdomain.com/w=400,h=300,fit=cover,f=webp,q=85/cdn.example.com/photo.jpg

Define your own presets in the PRESETS env var:

PRESETS='{"thumb":"w=200,h=200,fit=cover","card":"w=400,h=300,fit=cover","hero":"w=1200,h=600,fit=cover"}'

Short names in templates, full control in configuration.

Getting started

Repix is open source and ready to deploy:

If your image pipeline is quietly costing more than your app server, it's worth running the numbers. A self-hosted transform layer might be the cheapest upgrade you make this year.