---
title: "Images"
---

> Documentation Index
> Fetch the complete documentation index at: https://ermahgerd-docs.t-bd7662a5eeb4.workers.ermahgerd.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Images

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:

```json
{
  "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:

```js
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.
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. These are input ceilings, not a promise that every
combination fits the execution budget described below. Rejected headers, invalid
options, and admission refusals do not consume a transformation allowance.
The photo publishing example applies its own tighter
64-megapixel editorial policy before invoking Images.

## Shared capacity and failure isolation

Images accepts parallel transformations without decoding them in its API process.
Each upload first reserves an admission ticket, then streams to private disk
staging. Header inspection runs in a limited child process; its dimensions and
requested output determine the memory reservation for decoding and encoding.
The same reservation becomes the executor's Linux address-space limit. A child
that cannot allocate memory or finishes too slowly fails its own operation;
the API does not need to restart. Executors are fresh processes drawn from a
fixed number of execution slots, not per-Worker services.

The compact and public profiles use the following defaults:

| Control                                          | Default                                            |
| ------------------------------------------------ | -------------------------------------------------- |
| Simultaneous executors                           | 2, at most 1 per organization                      |
| Total executor memory reservations               | 1 GiB, inside the existing 1.5 GiB service ceiling |
| Admitted requests, including upload and response | 12 total, at most 4 per organization               |
| Capacity wait                                    | 30 seconds per stage                               |
| Header inspection / transform deadline           | 5 / 20 seconds                                     |
| Upload / response transfer deadline              | 30 / 30 seconds                                    |
| Encoded output ceiling                           | 64 MiB                                             |

Eligible tenants take execution slots in arrival order. A smaller operation from
another organization may run alongside a large one when its reservation fits;
one organization cannot occupy both executors. This is bounded local fairness,
not dedicated CPU or memory per tenant and not a hard latency guarantee.

Temporary saturation returns `503 capacity_busy` with `Retry-After: 2` on the
private binding transport. Use bounded retries with backoff. A transform that
exceeds its individual memory or time budget returns `422 execution_budget` or
`422 execution_deadline`; replaying the same operation is not a capacity fix.
The Worker binding surfaces these failures as exceptions. Accepted execution
attempts consume an operation even if the codec later fails. No per-image CPU
charge is inferred from shared service telemetry.

The photo application's object-upload path has a separate known compatibility
boundary: a fully buffered value larger than workerd's 32 MiB RPC-message limit
can fail before Images is called. Images admission does not remove that transport
limit; large-object binding streaming needs separate work.

## 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.

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`](/self-hosted/examples/#photo-publishing-workflow) shows
that composition.

Source: https://ermahgerd-docs.t-bd7662a5eeb4.workers.ermahgerd.io/build/images/index.mdx
