Create your own Image CDN using AWS CloudFormation and AWS Lamda
Tags: aws, serverless, cloud, cdn
Published: 2022-02-25 14:49:53

➥ In this article, I will demonstrate how to create your own Image CDN in a few simple steps using `AWS CloudFormation` and `AWS Lamda (Serverless)`. 

➥Before we dig in the tutorial, let's talk briefly about `IMAGE CDNs`

##● What is Image CDN and why to use it ?
➥ Image content delivery networks (CDNs) are used for optimizing images, or in another words, load images with the best possible optimized size in its placeholder in a website.
➥ This approach increases website performance and speed.
➥There is a lot of third party CDNs you can use like ImageKit, Cloudinary, Bunny CDN and much more ... 

##But today, I'll be talking about creating your own Image CDN:
**1-** Download [Serverless Image Handler CloudFormation Template](https://solutions-reference.s3.amazonaws.com/serverless-image-handler/latest/serverless-image-handler.template).
**2-** Login to your AWS Console, Go To `AWS CloudFormation` Page.
**3-** Select Create Stack > with new resource
![Create_Stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59jtawxbfqxyhem5p2zw.png)
you will then be redirected to create stack page.

**4-** In Prepare template section select Template is ready,
In Specify template select Upload a template file, and then upload the template file you previously downloads then click next

![Create_Stack_page1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgrzy4lxioioe6f6t398.png)
**5-** In Specify stack details page, just enter a name for your stack , let's assume we named it **My-New-Demo-CDN** and then in **Image Sources** field, here you should enter all the S3 Bucket names that will be the original source of the images will be uploaded (the images with the highest quality that will be resized later by the Lamda function depending in the requested size)
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kov71wgxcqawgrgjgng.png)
then hit next ...

**6-** In Configure stack options, you can enter any tag you want for the resources or leave it empty, no need to get into advanced details at the moment, click next

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6msre4w9591mtw4c10az.png)
**7-** You will be directed to the Review My-New-Demo-CDN, where you will review all the options you previously selected for the stack like template, parameters, stack options, permissions, policy ...etc.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ae9mcqom4xf65qv72y6h.png)
- Check `I acknowledge that AWS CloudFormation might create IAM resources` and hit **Create Stack**.

**8-** Creating process will start and it will take a few minutes to finish ...

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys4gup8hizooocj650dj.png)

**9-** Then you will notice that all resources are ready and your CDN create status will be `Create Complete`.

![stack_ready](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spzhnbihx2r1b9p833fs.jpg)

**10**- Navigate to Outputs Tab, you will notice that an API End Point has been created for your stack to use, in our example it is `https://r3fy67sunclsio8y5.cloudfront.net`, this link is the link that will replace your image bucket url.

![get_cdn_url](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4cpuj2f1p9fpedo90xx.jpg)

***Now your CDN is created and ready to use ...*

---

## How To Use it ?
**1-** Let's first upload an cute cat image with high quality to one of the buckets that we assigned as an image source for the CDN, don't forget to allow public access on uploading this image to be able to use it from the browser.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkn2m9vnx2xb3a266z09.png)

then we can view this image from the browser from its public url

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5qluznl1hf5fntaiu7rr.png)

_As we can see, the url consists of 2 parts:_
**a- Base Bucket URL** `https://default-bucket-test-image-cdn.s3.eu-west-3.amazonaws.com/`
**b- image path in the bucket** `cute-cat-4k-wg.jpg`

Also notice that the image is <u>loaded with its full size</u> when you open it in the browser

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9344tiyd7dgl305p00g.png)

So, what if I need to use this image multiple time in my website, once as a thumbnail, other time in **300x300 size** and other one with its full size, is it logical to save it in my storage three times with three different sizes , or may be load it each time with the full size ? 🤔

**2-** _Here will come the magic 🧙🏻 of the CDN,_ let's replace the bucket URL with our previously created CDN URL , and just enter a size for the image so that our link will be
`https://r3fy67sunclsio8y5.cloudfront.net/300x300/cute-cat-4k-wg.jpg`
and notice what happens

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ny51soljzoz6zvfumki0.png)

**Our image is now resized to 300x300 and only 21Kb is loaded to the browser instead of 3.1 Mb 🤯🤯.**
Try it with other sizes and see the magic yourself ...

---

## Actually, this CDN is not limited only to resizing .... 
✅ it also extends the functionality of many of the [Thmbor Filters](https://web.dev/use-thumbor/#:~:text=Thumbor%20is%20a%20free%2C%20open,%2C%20resize%2C%20and%20transform%20images.) to allow you to set **background color, blur, grey scale, image type, image format, quality, crop, rgb, sharpen upscale , setting watermark and other filters ...**
check the table below for the list of filters

| Filter Name                                           | Filter Syntax                                    |
|-------------------------------------------------------|--------------------------------------------------|
| Autojpg                                               | /filters:autojpg()/                              |
| Background color                                      | /filters:background_color(color)/                |
| Blur                                                  | /filters:blur(7)/                                |
| Color fill                                            | /filters:fill(color)/                            |
| Convolution                                           | /filters:convolution(1;2;1;2;4;2;1;2;1,3,false)/ |
| Equalize                                              | /filters:equalize()/                             |
| Grayscale                                             | /filters:grayscale()/                            |
| Image format (heic, heif, jpeg, png, raw, tiff, webp) | /filters:format(image_format)                    |
| Image type (jpeg, png, gif)                           | /filters:format(jpeg)/                           |
| No upscale                                            | /filters:no_upscale()/                           |
| Proportion                                            | /filters:proportion(0.0-1.0)/                    |
| Quality                                               | /filters:quality(0-100)/                         |

for example, our link will be like:

- `https://r3fy67sunclsio8y5.cloudfront.net/fit-in/500x500/cute-cat-4k-wg.jpg` for resizing
- `https://r3fy67sunclsio8y5.cloudfront.net/fit-in/500x500/filters:blur(7)/cute-cat-4k-wg.jpg` for resizing then blurring the image
- `https://r3fy67sunclsio8y5.cloudfront.net/fit-in/500x500/filters:quality(50)/cute-cat-4k-wg.jpg` for resizing then reducing quality to 50%
and so on for all the filters

---
##Archeticture of this CDN:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uaujpffsrixx9wr0cvyn.png)
---

##Cost of this CDN:
➥ You are responsible for the cost of the AWS services used while running this solution. As of December 2021, the estimated cost for running the Serverless Image Handler solution with an AWS Lambda processing time of two seconds per image, where each image is approximately 1 MB in size, and default settings in the US East (N. Virginia) Region is $15.29 per month for 100,000 new images, $149.30 per month for 1,000,000 new images, and $744.91 per month for 5,000,000 new images (refer to the following table for the cost breakdown). This includes estimated charges for Amazon API Gateway, AWS Lambda, Amazon CloudFront, Amazon S3 storage, and AWS Secrets Manager.

|                                                                                          | Cost to process # of new images per month |           |           |
|------------------------------------------------------------------------------------------|-------------------------------------------|-----------|-----------|
| AWS service                                                                              | 100,000                                   | 1,000,000 | 5,000,000 |
| Amazon API Gateway                                                                       | $0.35                                     | $3.50     | $17.50    |
|              AWS Lambda              (2 seconds processing time per image)               | $3.35                                     | $33.53    | $167.67   |
|              Amazon CloudFront              (process 1 MB images per request)            | $8.40                                     | $84.01    | $420.04   |
|              Amazon S3              (store 1 MB images)                                  | $2.29                                     | $22.86    | $114.30   |
| AWS Secrets Manager*                                                                     | $0.90                                     | $5.40     | $25.40    |
| Total monthly cost:                                                                      | $15.29                                    | $149.30   | $744.91   |


For a full documentation of this solution, please visit the [official documentation](https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/welcome.html)