Programmatic Image Conversion to WebP Using Amazon S3, CloudFront, and Lambda

Migrations

Learn how to optimize website performance by converting images to WebP format using Amazon CloudFront and S3, improving load times and user experience.

Website performance has a direct impact on user retention and conversion rates. Increasing brand promotion, reducing rendering times, and simply helping the browser give quick visual feedback to the user is a never ending optimization task. You have around 3 seconds to display content before the user leaves for a different site.

If you run a web app performance tool, like Lighthouse, against your site you will receive a performance score along with a breakdown of potential improvements. Specifically for images, Lighthouse will suggest migrating any JPEG or PNG assets in the website to a more modern format like WebP. In the example below you can see the potential savings that image compression would provide.

Migrating assets to WebP and realizing these potential savings sounds great. So where do we start?

A better way to deliver images

In this blog, we will describe how to implement the conversion to WebP and how Amazon CloudFront and Amazon S3 can be configured to optimize and cache any website asset in order to gain web performance, improve image delivery, and give your users an accelerated experience.

Using a combination of Lambda@Edge and Amazon S3 Object Lambda we’ll show how an asset can be transformed according to the requirements of the browser, stored in S3 for future reuse, cached within Amazon CloudFront and finally cached in the browser.

What would the solution look like?

For this blog post, we’ll use the following reference implementation to explore each step of the process in detail. When you’re ready to implement this on your site see the repo here.

Let’s walk through the chain of events triggered when a user clicks a link on your site.

Initial Request

First, the browser is checked for WebP support. After that support is confirmed, it appends the query string transform=ABC to the HTTP request when fetching the asset cat.jpg.

Then Amazon CloudFront executes an origin request (a Lambda@Edge function) to determine if a transformation was requested. If a transformation is needed it will mutate the S3 key to fetch the correct object from Amazon S3.

The Lambda@Edge function tells Amazon CloudFront to use transform=ABC/cat.jpg rather than cat.jpg as a S3 key as indicated in the code snippet #1

Failed Request and Image Conversion

The original request through Amazon CloudFront tries to fetch the S3 key transform=ABC/cat.jpg from the S3 bucket, but does not find it because it hasn’t been produced yet. Based on this failed response Amazon CloudFront executes an origin response Lambda@Edge function to try to convert the failed response from S3 into a resized image. The origin response Lambda@Edge function directs the requested transformation ABC to a specific Amazon S3 Object Lambda access point and fetches the cat.jpg S3 key through it as indicated in the code snippet #2.

Amazon S3 Object Lambda executes an AWS Lambda function to transform the image cat.jpg using the reference transformation ABC.

Storing in S3 for Future Reuse and Delivering the Image

The AWS Lambda function will keep a copy of the transformed image in the S3 bucket for the next time that Amazon CloudFront needs it. But to help the origin response Lambda@Edge function finish its execution, it saves it after delivering the optimized asset to Amazon S3 Object Lambda.

The origin response Lambda@Edge function embeds the optimized image bytes into the response object that it will return to Amazon CloudFront as indicated in the code snippet #3.

Amazon CloudFront returns the resized image to the browser with a Cache-Control HTTP header that will instruct it to cache the asset for a long time while Amazon CloudFront will also cache it for as long as its cache policy allows it.

An Example

Given this original image in its current form as a non-optimized JPG:

If it is fetched from this updated URL which uses the query string transformation-template = webp-20230802-460 to optimize the delivery of a transformed image, a significant reduction in size can be seen.

The original image weighs 727,763 bytes versus the transformed image weighing only 16,730 bytes. This significant reduction means that the 700,000+ bytes that weren’t delivered to your user will speed up the user experience every single time that asset is requested.

If you haven’t already, click the links for the original, non-optimized image and the transformed, optimized image and compare the speed of the request and optimization of the delivered image. The results are striking.

Conclusion

With today’s modern technology that includes screaming fast WiFi and gobs of RAM in every device it may feel like the need for image optimization has become less important. However, as the example above shows, you can measurably and significantly speed up image delivery on your site and have a direct impact on the browsing experience for your users.

Migrations
Carlos Espin

Carlos Espin

Carlos Espin is a Senior Cloud Software Architect in the Cloud Native Applications practice at Caylent. Carlos grew up in La Guaira, Venezuela where it is normally around 40 degrees Celsius and now lives in Montreal, Canada where it is sometimes around -40 degrees Celsius. He is a father of two and a husband to one. He jokes more than he should and is passionate about the craft of technology architecture and the mindset that comes with it. His favorite books are "Thinking in Systems: A Primer" by Donella Meadows and "Cien años de soledad" by Gabriel G. Marquez. When he is not busy trying to find equilibrium between business, technology, and people he is snowboarding or thinking about the mechanics of existence.

View Carlos's articles

Accelerate your cloud native journey

Leveraging our deep experience and patterns

Get in touch

Related Blog Posts

Moving from VMware to Amazon EC2

Learn how to migrate from VMware to Amazon EC2 and avoid VMware licensing and cost uncertainties while unlocking transformative cloud scalability and efficiency.

Migrations
Infrastructure & DevOps Modernization
Cost Optimization

Best Practices for Migrating to Aurora MySQL

Aurora MySQL is a high-performance, fully managed database with Amazon RDS benefits, simplifying infrastructure for business focus. Learn migration best practices and essential components for a successful journey toward Aurora MySQL that can lead to increased scalability, resiliency, and cost-effectiveness.

Data Modernization & Analytics
Migrations

Top 7 Cloud Migration Mistakes

Migrating to the cloud is deeply desirable due to ease of the management, scalability and many other factors, however poor choices in the migration process can lead to increased costs, poor performance and tech debt. Learn about the top 7 cloud migration mistakes and how to avoid them.

AWS Foundations
Migrations