ermahgerd provides a native, organization-metered image transformation capability to Workers. A deployment declares an Images binding in the same place it declares R2, D1, KV, queues, and assets:
{
"images": {"binding": "IMAGES"}
}Wrangler includes the binding in the immutable Worker version. At invocation
time the trusted runtime injects the public builder interface as env.IMAGES
and retains the private service credential. Image bytes and credentials are
never placed in deployment metadata.
Transform an image
The binding follows Cloudflare’s stream-oriented Images API:
const source = await env.MEDIA.get("originals/photo.jpg");
if (!source) return new Response("Not found", {status: 404});
const result = await env.IMAGES
.input(source.body)
.transform({width: 1200, height: 800, fit: "scale-down"})
.output({format: "image/webp", quality: 86});
return result.response();The current surface accepts scale-down, contain, cover/crop, and pad
fit modes and emits AVIF, GIF, JPEG, PNG, or WebP. Width and height are optional;
at least one must be supplied. The service preserves aspect ratio where the fit
mode requires it and re-encodes output without source metadata.
Input is bounded at 128 MiB, decoded images at 100 megapixels, and either output dimension at 12,000 pixels. A rejected or malformed input does not consume a transformation allowance. The photo publishing example applies its own tighter 64-megapixel editorial policy before invoking Images.
Quotas and operations
Open Media → Images in the tenant console to inspect the capability:
- Overview shows transformation rate, observed p95 duration, unsuccessful operations, and the authoritative monthly allowance. Rejected inputs and quota enforcement are included in unsuccessful operations; these are not all platform failures.
- Workers lists the active Images bindings and links to each Worker and deployed version. Add or remove bindings through Wrangler.
- Activity shows the latest 200 organization-scoped transformations in the selected window, paginated in the browser, with outcome, duration, and trace identity. Image content is never included.
Charts and activity are derived from retained operation logs, not the monthly quota ledger. A quiet window has a zero operation rate; duration is only shown when observations exist. Telemetry unavailability is reported as an error, not a healthy zero. The time range, selected tab, filters, and pagination can be bookmarked or shared within the organization.
Every accepted transformation reserves one idempotent monthly operation at the trusted Images service boundary. Free, Standard, and Enterprise tiers include 1,000, 25,000, and 100,000 transformations per month respectively. The tenant console reports this under Usage & limits → Images; platform operators can apply an explicit support override without changing the organization’s tier.
The service runs on data-01 with a bounded systemd resource envelope. Alloy
collects its structured operation events and OTLP traces, and Prometheus scrapes
success/error counts and transformation duration. Logs and traces record scope,
outcome, and timing—not image bytes or internal credentials.
This is an image transform primitive, not durable image storage. Store source
and derived objects in R2, and use versioned keys when queue retries or concurrent
edits can race. photo-gallery shows
that composition.