Most articles here are about delivering images in general. This one is about this service in particular: what it does, who it is for, who should use something else, and what is not finished. It is longer than the others and less useful to a reader who has no interest in the product.
What it is, in one paragraph
A transforming image CDN that sits in front of an origin you already run. You keep your
images where they are; a request for
/v1/hero.jpg?w=1200&f=auto is fetched from your origin, resized, encoded in
whatever format the requesting browser said it accepts, cached at the edge, and delivered.
The URL is the API. There is nothing to upload and no SDK to install.
The problem it was built around
Three facts about image delivery sit awkwardly together.
The right format depends on the browser, not on you. AVIF is smaller than WebP, which is smaller than JPEG, and the set of clients that can read each is different and keeps changing. The only place with enough information to choose is the moment of the request, which means the decision cannot be made when the image is stored.
The right size depends on the layout, not on the file. One photograph is a thumbnail in a list, a card on a grid and a hero on a product page. Storing one rendition per use is a job that never ends; deriving them on demand is a job a machine does.
Both of those are the same small program, and almost every team writes it again. Fetch, decode, resize, encode, cache, serve. The interesting part is never the resizing — it is the cache key discipline, the negotiation, the bounds that stop one URL parameter turning one image into two million renditions.
So why not use one of the existing ones?
For most teams, you should. The honest recommendation for one product with images on S3 is a single-purpose self-hosted proxy, or the optimizer add-on on whichever CDN you already pay for. Less to run, and nothing here would improve it.
The gap this was built for is narrower and specific: serving images for other people's accounts, on infrastructure you control.
That combination is badly served. Reselling a hosted image CDN means reselling somebody else's bill and somebody else's limits, and it puts your customers' images on a third party's disks. Self-hosting a single-purpose proxy means it has no idea what an account is: no keys, no quotas, no per-tenant hostnames, no billing, and no way to tell one customer's traffic from another's. The apparatus around the transformation turns out to be most of the work, and it is the part nobody publishes.
Who it is for
- Platforms that serve images on behalf of their own customers — a marketplace, a site builder, a headless CMS. The tenancy machinery is the point.
- Anyone bound by data residency, or working somewhere a third-party proxy fetching from an internal origin is not acceptable. Every byte stays on hardware you chose.
- Teams whose transformation bill scales with their catalogue rather than their revenue. Per-transformation pricing is fine until the catalogue is large and the traffic is not.
Who should not
- One team, one product. Use the simplest thing that resizes an image.
- Anyone wanting to stop running an origin. There is no upload endpoint and no plan for one. That is a category difference rather than a missing feature — this is a proxy, and a proxy needs something to proxy.
What is actually interesting about it
Nodes hold no database credentials
An edge node is the machine most exposed to the internet, and it needs to know things that live in the database: whether an API key is valid, what an account's quota is, which preset a URL names. The obvious arrangement gives every node a connection string, which makes a compromised node a compromised database.
Instead a node asks the console over a narrow internal API and holds no credentials of its own. It can look a key up, report usage and append rows. It cannot enumerate accounts, read a user, or change anything. The blast radius of a lost node is those operations.
The cache key is treated as a budget
Every parameter a URL may carry multiplies the renditions of one image, and the multiplication is the bill. So an account can name presets and publish only those; restrict which widths and heights are permitted at all; or switch on a mode where transformation parameters are refused outright and a URL may name a preset and nothing else. Refusals are explicit — a size that is not offered is a 400 with its own reason in the account's request log, not a quiet snap to the nearest permitted value, which would make the URL a lie about what it returns.
Weak nodes can borrow strong ones
Transformation is CPU-bound and delivery is not, so a fleet does not need every node to be the same size. A node can be configured to pass CPU-intensive work to a stronger one and serve the result, which lets a small machine sit close to users without being able to do the expensive part itself. If every upstream is unreachable it transforms locally rather than failing.
Routing is by distance, and drains cleanly
An authoritative nameserver answers with the nearest node that has recently reported in, honouring EDNS Client Subnet so that a resolver's location does not stand in for the client's. Nodes register themselves; one that stops heartbeating drops out of the answers without anybody editing a zone file. Clearing a node's public address drains it from DNS within a heartbeat while it carries on serving whatever still reaches it.
Content negotiation done properly
f=auto picks the format from the request's Accept header, and the
response carries Vary: Accept — but only on those responses, so a URL that named
an explicit format keys exactly as it did before. Without that header a shared cache will
eventually serve one client's AVIF to a browser that cannot read it, which is the failure
that looks like a corrupt image and is not.
Work not done is the cheapest work
Making a small thumbnail from a large JPEG does not require decoding the large JPEG. The format's block structure allows a scaled decode at simple fractions, so the decoder can hand back a much smaller bitmap and never build the full one. The saving is quadratic in the scale factor, and the arithmetic is worth doing against your own sources rather than trusting anybody's figure.
The operator console is a separate application
The surface that can read every account and close any of them is its own container, with its own sign-in, its own cookie under its own key ring, and no Stripe key, mail credentials or certificate account in the image at all. It is meant to sit on a network the internet cannot reach. Closing an account is the one thing it cannot do by itself — it asks the console, which owns the billing credentials, so there is exactly one implementation of the most destructive operation in the product.
Every action it takes is recorded, reads included, in a table that deliberately does not cascade from the account it describes. The most important row it will ever hold is somebody closing an account, and a cascade would delete that row at the moment it started to matter.
The application account is not root
Neither application issues schema changes at runtime, so the database account they use needs four privileges — select, insert, update, delete — on one schema and nothing else. Schema work is done separately by an operator with a different account. A compromised console can read and change rows, which is bad enough, and cannot drop a table or reach another schema.
What it does not do
Stated plainly, because a page that lists only capabilities is not describing a service, it is selling one.
- No uptime commitment. Nothing here measures availability, and the terms of service say so rather than publishing a number nothing backs.
- No ingest, as above, and no data export — deletion has shipped and export has not, which is a conspicuous shape for a data-rights obligation and is on the list.
- AI transformations cannot be bought. Smart cropping, background removal, upscaling and colour grading are implemented and credit-metered, but nothing takes payment for the add-on, so an operator has to enable it per account by hand.
- An account has one sign-in method or the other, password or a provider, with no way to add the second.
How finished is it?
Less than the rest of this article implies, and it is worth being exact about which parts.
Five integrations are complete code with passing tests and have never once run against the real thing: Stripe, ACME certificate issuance, local model inference, the hosted vision API, and the GeoIP database. Tests against a fake prove the shape of a conversation, never that the other party agrees to it. Treat all five as unverified rather than as features.
The delivery path itself — fetch, transform, negotiate, cache, authenticate, meter — is the part that is exercised, and it is the part everything else exists to support.
There is also no published licence yet, which means "self-hosted" currently describes the architecture rather than an offer anybody can accept.