Skip to content

Image optimization (ecommerce assets)

We optimize product and content images into modern formats (AVIF/WebP) and multiple widths to improve LCP, reduce bandwidth, and maximize cache hit rate.

Image optimization pipeline diagram

What gets stored in S3

  • Originals: uploaded by the CMS/admin (e.g. assets/product/<id>....png)
  • Optimized variants: generated alongside the original, using a naming convention like:
  • ...<name>_opt_w256.avif
  • ...<name>_opt_w512.webp

The exact set of widths/formats is owned by the optimizer Lambda.

Delivery behavior (frontend)

Our frontend uses an “optimized image” component (SitiosOptimizedImage) that:

  • Requests the best available optimized variant via <picture> sources (AVIF → WebP → original).
  • Assumes that for an optimizable URL, the matching _opt_w{width}.{format} objects will exist shortly after upload.

Because <picture> selects sources before the <img> fallback, missing variants can cause user-visible “blank images” depending on browser behavior, caching, and timing. The key architectural goal is: variants should be generated automatically and quickly after upload.

How optimization is triggered

1) S3 emits an ObjectCreated event to EventBridge

Asset buckets have “Send events to Amazon EventBridge” enabled.

2) EventBridge routes matching events to an SQS queue

An EventBridge rule filters for:

  • Bucket name(s) used for ecommerce assets
  • Object key suffixes that represent images (.png, .jpg, .webp, etc.)

Current event pattern:

{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": [
        { "prefix": "sitios-ecommerce-bkt-" },
        { "prefix": "ecomm-assets." }
      ]
    },
    "object": {
      "key": [
        { "suffix": ".jpg" },
        { "suffix": ".jpeg" },
        { "suffix": ".png" },
        { "suffix": ".webp" },
        { "suffix": ".avif" },
        { "suffix": ".tif" },
        { "suffix": ".tiff" }
      ]
    }
  }
}

The rule sends a message to the image optimization SQS queue using Input transformation so the optimizer receives the shape it expects.

3) The optimizer Lambda processes the SQS jobs

The optimizer lives in the sitios-lambdas repo: Sitios-Agencia-Digital/sitios-lambdas.

The s3ImageOptimizer.mjs Lambda:

  • Consumes SQS messages (typically { bucket, key, ... })
  • Reads the original object from S3
  • Produces optimized variants (formats + widths)
  • Writes the variants back to the same bucket under the _opt_w... naming convention

Operational notes

  • Backfill: if you migrate/copy buckets or discover missing variants, run a backfill job that enqueues {bucket, key} for existing originals (either via an internal admin endpoint or a one-off script).
  • Filters: keep the EventBridge rule filters aligned with the buckets and key patterns we actually use, so new asset buckets automatically participate in optimization.