Implementing Dynamic Website Origin Routing While Providing a Seamless UI Experience Using Lambda@Edge

Julian Glover
Jetty Product & Engineering
5 min readJan 14, 2022

The latest marketing and branding updates at Jetty presented a unique challenge regarding how to best serve content to our web users while providing a seamless user experience. In a simple website setup, a user visits a URL such as www.example.com/about and the server at example.com returns the content for the “about” page. However, we were in the process of moving the previous Jetty.com site to a new content management system (CMS). A CMS allows website administrators to quickly create and publish new web pages and other website content to their sites.

Here at Jetty we were migrating to a CMS to aid in our static content creation, however this would not be a simple transition. The Jetty.com site also serves dynamic content based on the specific web page address that is being visited. We needed to come up with a strategy that would allow us to both preserve our current infrastructure for creating and serving dynamic content while supporting the switch to a new CMS hosted on another server on a separate domain. Additionally, we needed to serve both the dynamic content from our old Jetty.com domain and the new CMS domain from the new Jetty.com site. This blog post will cover how we utilized Lambda@Edge to be able to efficiently serve data from two different domains to our website users.

The Challenges with Handling Static and Dynamic Content

When a user visits a url on Jetty.com, a request is made to CloudFront. CloudFront then figures out if the request should be routed to Amazon S3 where our dynamic content is stored, or to the server at Jetty.com which serves our static content and web pages. Our migration to a CMS meant that we were moving the static website content to another server on a different domain. However, we still needed to be able to serve the dynamic content from Amazon S3.

A diagram of the new Jetty.com setup can be viewed below.

Users who visit the Jetty.com website with a url that is mapped to dynamic content for example, jetty.com/<dynamic-content-slug> would need to be served the correct content from S3. However if the url is not requesting a dynamic page they need to be served content from CMS origin which contains all the static content.

Another design concern to the new web request routing logic is that our dynamic content is often updated so we need to be able to determine in real time whether or not a piece of dynamic content exists or if a request must be re-routed. Finally, providing a smooth web browsing experience is a major priority. We needed to make sure that our solution would not cause a noticeable increase in latency.

One simple solution to this problem could be to keep a record of all of the dynamically generated content, for example in a text file, and then when a user visits the Jetty.com site we could check the URL against those records and then handle the request appropriately. However, as the number of dynamic urls grows the latency incurred in parsing the file, or memory constraints of loading it into memory would lead to a slow site. Alternatively, we could try to keep the records in a database or other memory store which could cut down on inefficiencies. However, our dynamic content could be created or deleted at any time and keeping the data in sync in real time could pose an issue.

We did find a tool that was a great fit for our use case, Amazon Lambda@Edge. Lambda@Edge is a server-less service that allows you to run custom code to handle requests on a CloudFront instance. The service allows you to intercept user requests to an origin and format the response from an origin which is the exact requirement that we had. Next we will dive into how we used this tool to effectively build a technical solution.

Implementing and Optimizing Lambda@Edge

The most important challenge we needed to solve here was given a URL, how can we determine that an S3 bucket for that content exists. Since the dynamic content being served can change at any given time, we needed a way to ensure that whether an S3 bucket was newly created, edited, or destroyed users would always be served the correct content.

Our solution to this problem can be seen below.

In the above architecture, every HTTP request is routed through CloudFront and the Lambda@Edge function. The Lambda@Edge function then checks for the existence of the supplied URL in an in-memory read-through result cache. If no result exists in the cache then an HTTP request is made to S3. If the request returns a successful 200 response then we know that the request should be routed to S3. However, if we received a 404 then we know that the request origin should be changed to point to our updated site.

Conclusion

The most important part of this architecture is the Result Cache. Unlike many traditional serverless applications, Lambda@Edge functions reserve memory between calls meaning that we can cache results of previous HTTP requests to S3 and return them in subsequent calls. Using a cache saves each request from incurring the latency introduced from making http requests to S3. By utilizing the cache, we are able to return requests blazingly fast. You can view a snapshot of our DataDog logs below.

Our Lambda@Edge function completed in 1–2 milliseconds on average so our website users are still able to enjoy a smooth experience when navigating between our two sites.

Determining a way to route web requests between two separate domains in a seamless manner for our website users was a unique challenge for our front end architecture. However, by utilizing Lambda@Edge and optimizing our software performance using caching we were able to provide a smooth user experience and meet our requirements! We learned a lot during the scoping, implementation, and testing of this project and discovered the power and versatility of Lambda@Edge. If you or your team face a similar challenge in the future we hope this overview provides useful insights on how to possibly tackle the issue.

--

--

Julian Glover
Jetty Product & Engineering

Experienced Full Stack Software Engineer and Technology Enthusiast