Cloudfront, Function, and Edge@Lambda with Cloudformation

Fayas Akram
CodeX
Published in
3 min readJun 18, 2022

Recently, I have migrated our Landing/Blog page which is hosted on EC2 Server to an S3 static website and served via CloudFront. The site had multiple rewrite configurations (692) and I had to migrate the rewrite configurations along with that.

My initial idea was to use the S3 webpage redirect. But it has a limitation of 50 redirects per bucket and I had to write 692 redirection rules.

Later, I decided to use the Cloudfront Function which is similar to the Lambda function and at a better cost and 200+ Edge Caches. Also, it's less in execution time (1 millisecond) and memory (2MB). Whereas Edge@Lambda execution time from 5 seconds (viewer triggers) to 30 seconds (origin triggers) and 128MB (viewer triggers) Memory. The Cloudfront Function only supports the 10KB Package size and has no access to the request body.

My Compiled package is 64KB and I had to use Edge@lambda. Anyway in this blog, I have included Cloudfront Function Part and its Association with Cloudfront distribution

In this tutorial , I will be using cloudformation tamplate to deploy the all stack and CICD pipeline to automate and deploy for multiple environments (Stagging and Production)

Find the Cloudformation full code here https://github.com/5sfayas/Cloudfront-Function-EdgeLambda

CloudFormation Variable

From the above code, I have two deployments, DomainName: stage.fayas.com for stage and fayas.com for production. To specify the deployment stage, I have configured parameters in my template. Based on its value, staging or production, the template configures the CloudFront distribution with a corresponding custom domain name or CNAME and ACM ARN.

CloudFront Function

Type: AWS::CloudFront::Function property used create the CloudFront function resource.
Name: !Sub '${EnvType}-redirects-function' !Sub replace/substitute the parameter with EnvType.
FunctionCode: Cloudfront function code is defined and
Domain: !FindInMap [EnvType, !Ref EnvType, DomainName] !FindInMap to get DomainName for the given parameter and store to the Domain variable.
Fn::Sub: is an array that replaces Domain from the given parameter.

In this case, If my EnvType is the stage and the code block looks like the below.

var mapping = {"/who": "https://stage.fayas.com/fayas-akram/","/about-me": "https://stage.fayas.com/fayas-akram/","/home": "https://stage.fayas.com/","/root": "https://stage.fayas.com/"}

Edge@Lambda

As I have mentioned earlier in this block, I had to use Edge@Lambda instead of Cloudfront Function due to its limitations. If your function is less in size, please consider using the function, and if you want to use Edge@Lambda ignore the above configuration.

Lambda function resource creation is similar to a Cloudfront function where Code: is used instead of FunctionCode:
Type: AWS::Lambda::Version has defined which will create a new Lambda function version when there’s a new change to the code.

Cloudfront

I will be creating a default cache behavior with a custom s3 origin domain and Cloudfront will trigger Edge Lambda for viewer request.

Resource Type: AWS::CloudFront::Distribution defined to deploy the CloudFront stack. LambdaFunctionAssociations: block associated with the Edge Lambda function that we created earlier.
EventType: viewer-request Cloudfront will trigger Edge Lambda for view requests. !Join Function will join the Lambda ARN with its versioned number.

Origins: Custom S3 origin property is defined and OriginProtocolPolicy: http-only this will send the HTTP traffic to the origin

If you want to use the Cloudfront function, Use the FunctionAssociations: property.

That’s it for Cloudfront Based Static Site with Content Caching Redirection.

Find the full code here.

Thanks!!!

--

--