Migration from Netlify to Amplify

Thomas Mosmant
Luko
Published in
8 min readJun 27, 2022

We’ve been using Netlify since November 2019 as the main building and hosting platform for all our frontend applications at Luko. The experience has been really good as it is an amazing tool for the job. However, a few months ago, a change in our Netlify pricing plan made us rethink our frontend infrastructure. This change was mostly about considering every committer on our repositories as Netlify user even though most of them would never use Netlify. As we are very cautious with our expenses and always compare the cost with the benefits, we decided to take a look around and see if in an attempt to reduce our expenses we would lose anything important.

That’s how we ended up comparing Netlify, Vercel and AWS Amplify Hosting. We found that Vercel and Amplify were very similar to Netlify. The main difference for us was how they bill their customers. We found the Amplify pricing model — pay for what you use — the right one for us, and being AWS customers since Luko inception, it made sense to give this PaaS a serious try.

This article shares our experience with the migration because, as you can probably guess, not everything went as smooth as we would have expected. We have specific needs such as 1) SEO constraints and 2) product and marketing needs across multiple countries and languages. If you have similar needs, you will most likely find this article interesting.

Pitfalls and how we dealt with them

Region/language redirections

The PaaS supports region-based redirects, which is great, but it doesn’t support language-based redirects. At Luko we have a marketing website for each country and we want people landing on www.luko.eu to be redirected to the marketing website of their country. This is based on GeoIP detection. We also want them to be redirected to the /en path if their browser language is set to English.

Netlify allowed us to do that by using rules in the _redirects file or netlify.toml:

Sadly, Amplify doesn’t deal with language redirects and we had to use another service early on in our setup. We went for CloudFront, coupled with the Amplify distributions that required such redirect rules. By using a CloudFront function we were able to implement this by writing a little JavaScript code.

Here is how it works.

  1. Custom origin request policy

First, you need a custom origin request policy to make CloudFront enrich the origin request with information, such as the viewer country. You should also create a new origin request policy to include all viewer headers and the CloudFront-Viewer-Country CloudFront header. When this header is included, the viewer’s location is determined based on the IP address.

CloudFront policies interface

2. CloudFront function

Second, create a CloudFront function that will read the user Accept-Language header and redirect accordingly. You can create such a function by following the menu - CloudFront > Functions > Create function.

Toss it a name, a description, and your smartest code. You can test it with different paths/parameters/headers/cookies/… directly from the AWS console, and publish it when ready.

CloudFront functions interface

Spoiler alert, here’s the function we use:

3. Bind the function to your CloudFront distribution

In CloudFront’s distribution behaviours setup, edit the concerned path and bind it to a new Origin request policy and CloudFront function that you have just created. Once we have all the information and when the request hits CloudFront, we can bind this function to the viewer request hook.

CloudFront distribution setup interface

💥, we have a solution for this problem. Based on their location and browser language, all users are now redirected to the right marketing website displayed with the correct user language.

301 and query string conservation

The feature we missed the most while migrating to Amplify was the conservation of the query string during 301 redirect. For some reason, Amplify does not keep the URL parameters. As we actively use paid ads and have many 301 redirects, it was hard for us to live without it. So, we had to find with a solution.

CloudFront provides a Viewer response hook that contains the client’s request and the origin response. By checking if the origin response statusCode is 301, we can copy/paste the query string coming from the request, and append it in the location header yielded by the origin.

Here is our implementation.

The stringify function is needed because the request.querystring field is an object 🤪. It takes a query object as parameter and converts it into a query string.

That way, this:

becomes this: ?utm_campaign=20percentpromocode&utm_source=Facebook&utm_medium=socialmedia&utm_content=sidebarlink&utm_term=marketing

This issue was present on Netlify until January 2021. By comparing the state of their documentation (before and after), it appears they fixed it between January 1, 2021 and January 10, 2021.

Netlify documentation on redirects until January 2021

became

Netlify documentation on redirects after January 2021

Rolling back to a previous build

One Netlify feature we really miss is the ability to rollback to a previous builds. Netlify keeps the artifacts of all your builds for an indefinite period of time and allows you to restore them with just a couple of clicks.

This is how you can do it.

  • Go to the Deploys tab
  • Choose the build you want to restore
  • Click Publish deploy.

After this operation is complete Netlify will serve the previous build artifacts.

Select your build
Deploy it!

On Amplify, it is a different story. You have access to the entire build history — what triggered the build, how long it took, all the build logs but the Redeploy this version button triggers a new build of the selected commit. On an SPA this is perfectly fine. When it comes to an SSG like our marketing website it is a big problem. As the content of the website is fetched at build time, triggering a redeploy of the same build could lead to a different result. Hence, we are not able to Redeploy this version. We don’t have a proper solution to this problem yet, but we are working on it.

Fake redeploy button 🥲

We noticed a faster build time. As an example, the build of our french marketing website generates 750 index.html files. The build time on Netlify was 14 minutes average, and it is now 8 minutes and 30 seconds with Amplify.

It is not clear what is the reason but we assume that this could be the host infrastructure. The specifications of the hosts that Netlify are not publicly available, or we couldn’t find those. Amplify’s host has 4 vCPU and 7GB memory.

The cache

We wanted to improve the website performance and the user experience. We introduced two types of cache that we were not using when on Netlify. We just never took the time to work on it.

Custom headers

This is the quickest solution to setup. It is very straightforward:

  • Go to the Custom headers section of your project
  • Edit the headers Amplify generates by default.

This is how it looks like for our project. We instruct Amplify to send a cache-control header for all the assets under the /_nuxt/ folder. Those assets are blueprinted at build time and then have a different filename for each build, so we can indicate to the client’s browser to keep them in cache indefinitely.

AWS Amplify Hosting interface on custom headers

CloudFront

We use CloudFront to take advantage of the CloudFront functions. With the default cache policy, Managed-CachingOptimized, which has a high TTL and compresses the objects with gzip and brotli, we were able to reach a decent PageSpeed index. Our PageSpeed score is 84 at the time of writing, you can check it here. We invalidate the cache at each deploy from the Amplify CI by using the awscli.

Weird resource management

We had a little surprise after the first app deployment — where were our new AWS resources? We could see records of CloudFront, S3, even Lambda functions but where were they hosted?

We were a bit disappointed to learn that those resources, except of course the SSL certificates and the Route53 records, are 100% managed by Amplify, and we have a little control over them. Note that there are some configuration options available via the Amplify CLI (docs).

Higher Time To First Byte (TTFB)

With 135k unique users each month coming from organic SEO, we pay great attention to our ranking. It is often considered as voodoo and this is not completely inaccurate because the rules are complex and change often. You also need a high-quality content to achieve a good ranking. I know very little about it and we have in house experts for that. I’ll focus instead on what we can measure.

One of the top metrics here is the TTFB which measures the latency of the first call between the client’s browser and your infrastructure. To monitor it, we rely on the Google Search Console. Every time a Google Bot accesses our website, the metric is stored and shows up in the following graph.

Google Search Console report interface

We had a very low latency with Netlify, around 60ms average. The big increase you can see on the 23rd of May is the day we migrated to Amplify. Our TTFB increased and despite our efforts hasn’t been restored to what it was before. It is still not clear to us what caused this. However, a TTFB below 200ms is considered great, so we considered this increase acceptable for now. Don’t get us wrong, we feel like we lost something here and this is hard to accept. You can find here a few issues related to this on GitHub.

The rollout strategy

We executed a simple rollout. These are the steps we took:

  • Duplicated our development and production setup from Netlify to AWS Amplify Hosting.
  • Updated our DNS records in Route 53 to make them point to Amplify instead of Netlify, in development.
  • Let that run for two weeks and tackled a few issues that came up. They were mostly related to our environment variables.
  • Updated our production DNS records.
  • Monitored closely with our monitoring and bug reporting tools that everything was working as expected and we had no more issues.
  • Kept until now the setup in Netlify in case we needed to quickly rollback and fortunately we haven’t had the need to do that yet.

To conclude

This move wasn’t as scary as it might appear. If you have similar needs to what we have, in this article, we covered most of the potential issues you may encounter. As for suggesting one or another platform, we believe that Netlify and Vercel are well adapted when you have a small team and not much time to spend on frontend infrastructure. As soon as your team and needs grow, it makes sense to consider your options and asses the benefits vs cost.

--

--