Fight with Lambda@Edge pitfall

Lambda Edge is a niche feature of CloudFront and is highly used by customers for different requirements which are a fit to be processed at edge level.

I used the lambda edge in two following cases:

  • Security & Compliance

  • Cache optimisation

  • A/B Testing

Lambda Edge:

Lambda Edge can be used for 4 different phases of client and origin interactions

  • Viewer Request: This phase trigger a function when a client request is received by CloudFront distribution.

  • Origin Request: This phase trigger a function before reaching the origin when CloudFront distribution detects a need to send the request to the origin.

  • Origin Response: This phase trigger the function when CloudFront Distribution receives the response from origin and before CloudFront send back response to client.

  • Viewer Response: This phase triggers a function before sending back response to the client.

💡
To find more about Lambda Edge have a look at AWS CloudFront Documentation

CloudFront Integration:

When a function is created and tested , now we integrate it with CloudFront

const viewerRequestEdgeFunction = new EdgeFunction(this, viewerRequestEdgeFunction.name ,  {
    ....
};

new cloudfront.Distribution(this, 'distro', {
  defaultBehavior: {
    origin: new origins.S3Origin(s3Bucket),
    edgeLambdas: [
      {
        functionVersion: viewerRequestEdgeFunction.currentVersion,
        eventType: LambdaEdgeEventType.VIEWER_REQUEST,
      },
    ],
  },
});

Critical Situation:

When dealing with CloudFront as many other companies we used lambda edge as a compliance checker @Edge to better protect our public side of system, to avoid duplication in all teams and all softwares we had a central lambda that was used by all teams and this seems cool. actually the this function evolves rarely but if it needs changes there is a critical path to consider.

  • CloudFront Integrates with Lambda Edge with and only just with a specific function version and does not support function alias.

  • Lambda Edge deployment takes always a significant time, this was randomly between 15 and 45 minutes in my experience, but recently we found an improved deployment duration around 4 to 5 minutes in practice.

  • All Other applications need to redeploy their distributions to integrate the new version.

All these points made it hard to evolve a lambda @edge.

Assets Isolation

As a workaround we thought about our requirements in a new way, what are the changes we apply any time and why.

We had some remarks that mostly the changes are based on static objects in code like enums in out case. and those changes are just based on compliance requirements. so we isolated the assets Generic Code and Static Code to avoid redeploy of lambda function for any small change.

  • The Static code or assets are stored as a json content in S3

  • The lambda interacts via cloudfront and this helps to have a long TTL.

  • The Application will stay safe for any kind of static changes.

A Simpler solution

As per our requirements we found it mandatory to keep going with this solution and the below solution was not a fit based on restrictions that did not cover our needs.

CloudFront Functions is an alternative way of this solution as that will remove the burden of redesigning the stack and adding s3 bucket.

CloudFunctions KeyValueStore can helps to cover the need for small set of key value requirements Supported formats for values covers followings

  • string

  • byte-encoded string

  • JSON

The nice part of KeyValue store is that changing a Store does not need a function redeployment and re-association.

💡

Lambda @Edge Or CloudFunctions

When choosing edge functions verify requirements and assure those limits will not impact the runtime.

Here a detailed comparison provided by AWS : Documentation.

Enjoy practicing