Setting Up Your Own Image Transform Service
Tags: images, frontend, lambda
Published: 2020-02-25 21:20:49

---
title: Setting Up Your Own Image Transform Service
published: true
date: 2019-07-05 15:33:00 UTC
tags: images,frontend,lambda
canonical_url: https://nystudio107.com/blog/setting-up-your-own-image-transform-service
---

# Setting Up Your Own Image Transform Service

### Cre­ate optimized/​transformed images for pen­nies by lever­ag­ing the pow­er of AWS Lamb­da to cre­ate your own Server­less Image Handler

Andrew Welch / [nystudio107](https://nystudio107.com)

![Image transforms serverless image handler](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/image-transforms-serverless-image-handler.jpg)

Image trans­forms are a nec­es­sary part of mod­ern web devel­op­ment, because we want to deliv­er opti­mal­ly sized image <kbd>srcset</kbd>s to the client browser.

Whether you’re using a serv­er-ren­dered web­site or a [JAM­stack](https://jamstack.org/) set­up, image manip­u­la­tion is some­thing that needs to be done as a part of the process.

Even if you’re using some­thing like [Gats­by JS](https://www.gatsbyjs.org/), the work of trans­form­ing images still needs to be done, it just moves to build time. We’re just chang­ing where it gets done.

<aside>
                                Unfor­tu­nate­ly, image trans­forms are also very proces­sor intensive.
                            </aside>

Many CMS’s and oth­er serv­er-side ren­dered tech­nolo­gies have image trans­forms built into them. How­ev­er this essen­tial­ly means that you’re self-host­ing proces­sor-inten­sive image trans­forms on the same serv­er that you’re using to serve up your website.

If you haven’t run into issues self-host­ing image trans­forms, rest assured that you even­tu­al­ly will.

![Image transforming optimization problems](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/image-transforming-optimization-problems.jpg)

This is not a recipe for suc­cess in terms of serv­ing up your web­site in a per­for­mant man­ner. I’ve seen some web­servers fall over if the image trans­form cache is ever bro­ken, due to the CPU pow­er required to re-cre­ate the trans­formed images.

Addi­tion­al­ly, most built-in image trans­form sys­tems do not include an image opti­miza­tion phase.

For more infor­ma­tion on the how’s and why’s of image opti­miza­tion, check out my [Cre­at­ing Opti­mized Images in Craft CMS](https://dev.to/gaijinity/creating-optimized-images-in-craft-cms-2hc5-temp-slug-2354251) arti­cle or the com­pre­hen­sive [Essen­tial Image Opti­miza­tion](https://images.guide/) arti­cle from Addy Osmani.

<aside>
                                <span>“</span>We should all be automat­ing our image com­pres­sion.” — Addy Osmani
                            </aside>

Because image trans­forms are so proces­sor inten­sive, ser­vices like [Imgix](https://www.imgix.com/) and [Cloud­i­nary](https://cloudinary.com/) allow you to offload the work to their scal­able servers. Both ser­vices are excel­lent, but they also cost mon­ey, and often do more than we actu­al­ly need.

## Enter AWS Server­less Image Handler

Ama­zon AWS has offered a [Server­less Image Han­dler](https://aws.amazon.com/solutions/serverless-image-handler/) for a while that allows you to spin up an AWS Lamb­da func­tion to cre­ate your own pri­vate lit­tle image trans­form ser­vice that is inex­pen­sive, fast, and is front­ed by the [Cloud­Front](https://aws.amazon.com/cloudfront/) con­tent deliv­ery net­work (CDN).

[AWS Lamb­da](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) is part of the new wave of ​“server­less” func­tions that allow you to run code in the cloud with­out pro­vi­sion­ing or main­tain­ing a serv­er. It’s inex­pen­sive, and has­sle-free, which is a fan­tas­tic com­bo in my book.

Here’s what the [AWS Lamb­da pric­ing](https://aws.amazon.com/lambda/pricing/) looks like:

![Aws lambda pricing](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x399_crop_center-center_100_line/aws-lambda-pricing.png)

For many small­er sites, you may nev­er leave the free tier.

Under the hood, the [AWS Server­less Image](https://aws.amazon.com/solutions/serverless-image-handler/) Han­dler uses [Sharp JS](http://sharp.pixelplumbing.com/en/stable/), which is a [Node JS](https://nodejs.org/en/) pack­age built on high­ly per­for­mant [lib­vips](https://github.com/libvips/libvips) image pro­cess­ing library. Here’s an overview what it looks like:

![Aws lambda overview chart](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x600_crop_center-center_100_line/aws-lambda-overview-chart.png)

You can look at all of the [code under the hood](https://github.com/awslabs/serverless-image-handler) if you want, but the nice thing is that you don’t have to.

## Set­ting up an AWS Server­less Image Handler

The won­der­ful part of all of this is that you can set up your own AWS Lamb­da func­tion with­out hav­ing to do a deep dive in how it all works.

You’ll need some minor expe­ri­ence with AWS, and maybe some sooth­ing music while you wade through the AWS UI/UX, but that’s it!

<aside>
                                This is a point <span>&amp;</span> click no-code solution 🎉
                            </aside>

This works because you can spin up your ser­vice via [AWS Cloud­For­ma­tion](https://aws.amazon.com/cloudformation/) that uses pre­fab tem­plates for the cre­ation of a stack that com­pris­es your set­up. This means it’s essen­tial­ly point and click to set every­thing up on the serv­er side:

- You need to have an [Ama­zon AWS](https://aws.amazon.com/console/) account; if you don’t have one, get one
- Go to the [Server­less Image Han­dler](https://aws.amazon.com/solutions/serverless-image-handler/) page, and click on **Launch Solu­tion in AWS Con­sole**** , t**hen go through the tem­plate setup:

![Launch in management console](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_768x685_crop_center-center_100_line/launch-in-management-console.png)

**1. SPEC­I­FY TEMPLATE**

You won’t need to change any­thing here, unless you want to use your own cus­tomized tem­plate. Click **Next** to proceed.

![Step 1 specify a template](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x777_crop_center-center_100_line/step-1-specify-a-template.png)

**2. SPEC­I­FY STACK DETAILS**

Here there might be a few things you might choose to change (don’t wor­ry, you can go back and change these lat­er, too):

- **CORS Options**  — If you want to enable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), you can con­fig­ure it here
- **Image Sources**  — You need to list the [AWS S3 Buck­ets](https://aws.amazon.com/s3/) that the Server­less Image Han­dler can access
- **Demo UI**  — This will cause it to set up a demo UI you can play with to test your API. This is option­al, but I think use­ful when you’re get­ting start­ed. You can delete the Demo resources lat­er on

Click **Next** to proceed.

![Step 2 specify stack details](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x972_crop_center-center_100_line/step-2-specify-stack-details.png)

**3. CON­FIG­URE STACK DETAILS**

You won’t need to change any­thing here, unless you have a more involved AWS set­up in terms of per­mis­sions & poli­cies. Click **Next** to proceed.

![Step 3 configure stack options](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x1024_crop_center-center_100_line/step-3-configure-stack-options.png)

**4. REVIEW**

There’s noth­ing to change here, you can just see an overview of what you’re going to cre­ate. Click **Next** to pro­ceed after check­ing the **I acknowl­edge that AWS Cloud­For­ma­tion might cre­ate IAM resources with cus­tom names** checkbox.

![Step 4 review](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x332_crop_center-center_100_line/step-4-review.png)

If you run into issues, use the [Server­less Image Han­dler Deploy­ment Guide](https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/welcome.html) as the canon­i­cal source.

## Using an AWS Server­less Image Handler

Now that you’ve spun up your ser­vice, assum­ing you set up the Demo UI as well, you’ll have the fol­low­ing Cloud­Front dis­tri­b­u­tions set up:

![Cloudfront distributions](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x252_crop_center-center_100_line/cloudfront-distributions.png)

- **Image han­dler dis­tri­b­u­tion**  — this is your Server­less Image Han­dler dis­tri­b­u­tion that you’ll access from your fron­tend code to get your opti­mized, trans­formed images
- **Web­site dis­tri­b­u­tion for solu­tion**  — this is a dis­tri­b­u­tion cre­at­ed by the Demo UI so you can play with

While this will cre­ate an S3 buck­et for you if you cre­ate the Demo UI, any S3 buck­ets that you need for your actu­al website/​webapp are up to you to create.

Just make sure you then add them to your [Cloud­For­ma­tion stack](https://console.aws.amazon.com/cloudformation). Typ­i­cal­ly your S3 buck­ets should be com­plete­ly pri­vate, and you set up Cloud­Front dis­tri­b­u­tions as gate­ways to the S3 buckets.

**Pro tip:** You don’t real­ly want to serve sta­t­ic assets like images out of an S3 buck­et, it’s intend­ed for stor­age, not dis­tri­b­u­tion. Use a CDN dis­tri­b­u­tion lay­er on top of S3, such as CloudFront.

**Pro tip:** if you don’t see a par­tic­u­lar ser­vice in AWS that you know you have cre­at­ed, make sure you’re in the cor­rect Region.

If you copy the URL to the Demo UI **Web­site dis­tri­b­u­tion for solu­tion** you’ll get a play­ground you can use to play around:

![Serverless image handler demo](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x865_crop_center-center_100_line/serverless-image-handler-demo.png)

So the fun thing about the API is that all you need to do is cre­ate a JSON blob of options:

```

{
  "bucket": "images.nystudio107",
  "key": "Octagon-Titlarks-House-02.jpg",
  "edits": {
    "resize": {
      "width": 500,
      "height": 300,
      "fit": "cover"
    },
    "grayscale": true,
    "flip": true
  }
}

```

Here are the impor­tant top-lev­el keys in the JSON:

- <kbd>bucket</kbd> — This is the id of the S3 buck­et that the source image is in
- <kbd>key</kbd> — This is the path to the source image in the S3 bucket
- <kbd>edits</kbd> — A JSON-ified ver­sion of the [Sharp JS API](http://sharp.pixelplumbing.com/en/stable/api-resize/), con­tain­ing the changes you want applied to the image

Then in what­ev­er pro­gram­ming lan­guage you’re using, you just con­vert the JSON to a string, and then base64 encode it into a URL:

```

https://d3dvp96ru4zk60.cloudfront.net/eyJidWNrZXQiOiJpbWFnZXMubnlzdHVkaW8xMDciLCJrZXkiOiJPY3RhZ29uLVRpdGxhcmtzLUhvdXNlLTAyLmpwZyIsImVkaXRzIjp7InJlc2l6ZSI6eyJ3aWR0aCI6NTAwLCJoZWlnaHQiOjMwMCwiZml0IjoiY292ZXIifSwiZ3JheXNjYWxlIjp0cnVlLCJmbGlwIjp0cnVlfX0=

```

There’s an exam­ple of how to do this via JavaScript in the <kbd>scripts.js</kbd> that is cre­at­ed in your Demo UI S3 buck­et. Oth­er lan­guages are sim­i­lar­ly triv­ial to do it in.

All of the options that are imple­ment­ed in the [Sharp JS](http://sharp.pixelplumbing.com/en/stable/api-resize/)API are avail­able to you! All of your trans­form options that would nor­mal­ly be chained func­tions in Sharp JS just are in JSON for­mat in the <kbd>edits</kbd> key.

You can resize, crop, rotate, tint, sharp­en, and a whole bunch of oth­er image manip­u­la­tions, includ­ing con­vert­ing between for­mats such as <kbd>jpeg</kbd>, <kbd>webp</kbd>, <kbd>png</kbd>, and <kbd>tiff</kbd>.

You have exquis­ite con­trol over the exact encod­ing meth­ods should you want it, and by default, all images are opti­mized for size.

## Craft CMS Server­less Image Handler

The solu­tion described here works with any frontend/​backend set­up that you might be using.

How­ev­er, if you’re using [Craft CMS](https://craftcms.com/), the [Ima­geOp­ti­mize](https://nystudio107.com/plugins/imageoptimize) plu­g­in allows you to switch the Trans­form Method used site-wide to what­ev­er you want, from built-in Craft image trans­forms to Imgix image transforms.

Ver­sion 1.6.0 has added a Sharp trans­form method that works with the afore­men­tioned setup:

![Image optimize plugin sharp demo](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x953_crop_center-center_100_line/image-optimize-plugin-sharp-demo.png)

The nice thing about it is that you can change over to using dif­fer­ent Trans­form Meth­ods with zero tem­plate changes.

## Wrap­ping Up!

That’s all it takes to cre­ate your own AWS Server­less Image Han­dler! Try it for a personal/​demo site to gain con­fi­dence in how to set things up, and then away you go.

It real­ly is very inex­pen­sive com­pared to services:

![Aws lambda bill](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x968_crop_center-center_100_line/aws-lambda-bill.png)

Yes, you’ll have to wade through a bit of AWS UX/UI that’s not fun, and learn a bit about AWS per­mis­sions… but I think it’s absolute­ly worth the effort.

Whether you’re using a serv­er-ren­dered solu­tion, a JAM­stack solu­tion, or some­thing like Gats­by, you’ll ben­e­fit. No mat­ter where the work of image trans­form­ing is done, a Server­less Image Han­dler will speed up the process.

![Aws lambda setup worth it](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/aws-lambda-setup-worth-it.jpg)

Not only will you be able to offload CPU inten­sive image optimization/​transformation to your AWS Lamb­da func­tion, but you prob­a­bly can then down­size your serv­er (assum­ing you have one).

Addi­tion­al­ly, you’ll be learn­ing a bit of AWS in the process, which is a good thing to be famil­iar with in our business.

Hap­py transforming!

## Further Reading

_If you want to be notified about new articles, follow [nystudio107](https://twitter.com/nystudio107) on Twitter._

<small>Copyright ©2020 nystudio107. Designed by nystudio107</small>