Using CloudFront request headers to speed up page loading

When someone visits www.prayersconnect.com, a few things happen before the page is displayed. We know our visitors come to our site to get nearby mosque info. So we “do not show” (more on this later) a typical landing page but rather display their nearest mosques with the lowest friction.

How does it happen?

Once someone visits our site, we detect their IP address. Because we use Amazon CloudFront to serve our frontend traffic, we need to take extra care to make sure CloudFront forwards the user’s actual IP address. Otherwise, the IP address that we get in the origin server is an IP of the AWS systems. Here is the cloud function that is attached to Viewer Request to preserve the original IP.

function handler(event) {
    var request = event.request;
    var clientIP = event.viewer.ip;

    request.headers['x-user-ip'] = {value: clientIP};

    return request;
}

Once we receive the IP address, we geocode the IP address to get its coordinates, locality name etc. Once all these are retrieved, we redirect to a relevant page.

While all these are working very well so far, we got one problem. Geocoding IP an address takes time and the slowness is almost always embarrassingly noticeable. We were thinking to cache geocoding results. However, we prefer to maintain as less things as possible; especially when we have a better alternative.

CloudFront (CF) Request Headers

CloudFront has the ability to forward viewers’ approximate location info to the origin request. We decided to use this as we won’t have to maintain any caching infra for IP geocoding. As we use terraform to create the CF distribution, all we had to add the forwarding headers to the list like following

forwarded_values {
      query_string = true
      headers      = [
        "Authorization",
        "CloudFront-Viewer-Latitude",
        "CloudFront-Viewer-Longitude",
        "CloudFront-Viewer-Country-Region-Name",
        "CloudFront-Viewer-Country",
        "CloudFront-Viewer-Country-Name",
        "CloudFront-Viewer-City",
        "CloudFront-Viewer-Region-Name",
        "CloudFront-Viewer-Postal-Code",
      ]
    }

In our backend, we actually kept both mechanisms. First, we tap into this ready geo data. If they are not available, we fall-back to legacy IP geocoding. However, when geodata from CF is available, now the page is rendered almost instantly. I hope our users will appreciate this increased speed.

Notes on the landing page

We show landing pages in two cases:

  • We do not support the country (yet; as we’re working to be fully global)
  • We could not determine the user’s location. Note: For initial routing, we do not use the GeoLocation service.

What’s Next

Currently, the redirection happens from our server. It may be possible to redirect users directly from the cloud function which will improve the experience even further. We’ll investigate that soon.

If this sounds interesting or you have a better idea, consider joining our team as a volunteer.

About The Author

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *