At BOOM we produce and manage hundreds of thousands of images that need to be browsed and visualized by our web app’s users.
When we faced the problem of creating an image gallery, our first approach was to generate a set of optimized thumbnails for each image and store them on S3 so that they could be displayed inside the web app.
This naive approach had some evident drawbacks:
- We had to know the optimal resolutions needed for every device ahead of time
- Storage consumption would constantly increase over time, regardless of the actual usage of images. For example, an image produced two years ago is less likely to be viewed than a new image, but its thumbnails would be stored forever anyway
- What if requirements changed and we need new types of thumbnails? In that case, we would have to regenerate the missing images from scratch.
As such, we came to the conclusion that the best thing to do would be to generate images on the fly and cache them in a CDN for as long as needed. This way, no permanent storage was required, but we still needed to figure out how to perform lots of concurrent manipulations on demand.
The natural answer was “it has to be serverless”. That’s when we discovered that such a solution was already provided by AWS Serverless Image Handler.
AWS Serverless image handler
Serverless image handler is an AWS solution implementation that allows to store a single version of every image on an S3 bucket and at the same time deliver as many dynamic versions as desired. This approach drastically cuts storage costs and eliminates all the management complexity required by maintaining multiple image copies.
The solution comes with an AWS Cloudformation template that deploys the following resources:

- An Amazon CloudFront distribution that acts as a caching layer, reducing the latency of image delivery and the cost of image processing
- An Amazon API Gateway to forward requests that were not already cached in the CDN to a Lambda function
- A Lambda function to retrieve the image from the S3 bucket and returns the modified image after applying the necessary manipulations using Sharp.
In addition to that, the solution can also use AWS Secrets Manager if you wish to secure the requests through the signature feature, or Amazon Rekognition when using the smart crop or content moderation features.
Request examples
The serverless image handler features include the ability to resize, crop, flip images, change their background colors, convert to grayscale, perform smart cropping through face detection and content moderation, add watermarks, and more.
Most of these features can be explored through the demo app available in the solution; just import an image from your bucket and select the transformations you want to apply, and you’ll see the corresponding request json on the right-side panel.

For example, if you need to resize an image – keeping its aspect ratio – and convert it to jpg, the request json will look like this:

The demo app generates requests only for some of the available Sharp.js image manipulations.
In the official documentation, you won’t find an exhaustive list of all the supported parameters because you can refer to the library documentation. In fact, the parameters contained in the edit section of the json are passed directly to Sharp, as you can see in the default case of the lambda’s applyEdits function here below:

In addition to Sharp transformations, you can also use Thumbor filters that respond to different kinds of requests.
For example, if you want to add a watermark to your image you can call
<distributionName>.cloudfront.net/filters:watermark(bucket,key,x,y,alpha,w_ratio,h_ratio])
For the complete listing of supported filters, just refer to the supported Thumbor filters page.
Securing images
If you wish to keep your images secure you can enable the signature feature that will make the lambda check for a valid signature query string in every image request.
An error message will come up if the signature is either invalid or not present.
To activate the feature, you need to set the following lambda ENV variables:
- ENABLE_SIGNATURE: Yes
- SECRETS_MANAGER: a valid secret created in AWS Secrets manager
- SECRET_KEY: a valid key created in in AWS Secrets manager
Here below is an example of a Java method to create a valid signature, provided the request path and the signature key as input parameters:

With the signature feature enabled, the image request becomes:
<distributionName>.cloudfront.net/<path>?signature=<signature>
Limitations
Of course there is a limitation to this AWS solution, involving the Lambda’s invocation payload quota, as both request and response cannot exceed 6MB.
In case the resulting image is larger than 6MB you will receive the following error in the response:

Interested in joining BOOM’s team of engineers and developers? Check out our current job offers.