Redirecting old links
Recently, I am helping my Thai language school to build their new website. It is a complete rebuilt from application to infrastructure. During this rebuild process, when I start checking SEO, I accidentally find something odd in the Google Search Console for my very own blog site.
Apparently, nearly 80% of my pages are not indexed by Google because of 404. Soon I realise this is an issue from the recent UI refresh work
that I did back in March. During that work, I created my very own hugo theme for my blog. In that theme, I changed the slug of many pages. For example, /refresh-the-blog-look/ is now /posts/20260329-refresh-the-blog-look/.
After the change is deployed, soon Google has sent me an email notifying this issue. Unfortunately, I didn’t pay attention. In my mind, I thought Google is going to figure this out, and get this corrected automatically soon.
That is not the case. After a quarter, those pages still remains not indexed due to 404 error. Looks like Google is still trying to fetch some of those pages from time to time, but they never actually re-fetch my updated sitemap.xml.
It looks like my sitemap was last fetched in 2025. I think this is why Google insists fetching the old URLs. There is not a button on Google Search Console to force a sitemap refresh. I suppose I could remove this sitemap and resubmit it, but I think I will just skip that and do what I really should do in this case, which is add 301 redirection.
So I exported a list of those 36 pages, and dumped them to OpenCode. OpenCode put together a list of the old and new slugs. From there, I added a new CloudFront viewer request function to handle these 301 redirection, and this is where a problem arose.
As I explained in the post Modernise Infrastructure of This Blog
, I have already had one viewer request function for my CloudFront distribution. This is nearly impossible in my case to separate the function because one behaviour can only have one function of the same type. I have already had a behaviour for * to append index.html at the end of the request URL to the origin (S3 bucket), so I can’t add another behaviour to match those URLs that need to be redirected. Since I have to use the same behaviour, then I can only have one viewer request function. This forces me to combine the logic of appending index.html and 301 redirection into the same CloudFront function. I actually dislike this design, but AWS forces me to do it.
Alternatively, if I really want to keep them separated for the simplicity, I will have to give up CloudFront function and use Lambda@Edge function instead, which is heavier and more pricey, and I don’t necessarily need that.
Having to maintain the JavaScript code for CloudFront function also made me wonder if I am really satisfied with AWS with my blog operation task. To be honest, the main purpose of hosting this blog on AWS is to facilitate my learning on AWS, and now I think I have gained most of it. Now I am at the point to critically assessing AWS services, and I have to say I am not fully happy with many things in AWS. For sure AWS is compliant, convenient and versatile. Its uptime is possibly one the best too. It’s definitely the cloud leader. But I just feel its user experience isn’t that great. As my previous journey to try QuickSight out , which turned into a performance and billing disaster, suggested, AWS tries to promote a lot of things through their certification programme, but its use case doesn’t necessarily naturally fit everything. At least those data products don’t fit this blog. However, when I switched to Datadog, things suddenly became so much easier and straightforward. I suppose there are many ways to build a product, but some AWS products are built for some rather niche or enterprise level use cases, which do not really suit personal scenario. My epiphany about the S3 storage transition fee is another example. Following the AWS recommendation to set up proper storage transition actually would cost me more money. This is something that I have never imagined. This time again, from a technical aspect, AWS forces me to combine two totally unrelated functions into one, breaking the single responsibility principle. All of these frustrations make me wonder if I really want to keep using AWS.
When I rebuild the website for my Thai language school, I choose Cloudflare. This is the first time I seriously use Cloudflare, and I have to say I am very impressed. Getting into Cloudflare dashboard for the first time was super daunting. Cloudflare has created a lot of technical jargons, and they also cover almost everything from building, deploy to monitor and testing. I used to see Cloudflare as a CDN + Security platform. This time my view has changed. And more importantly, I have made a similar change on Cloudflare to do old URLs redirection. The experience was a braze. Cloudflare natively supports rules, and you can add many rules independently. No need to mix them together (and there is actually no way to mix them together either). They provide a lot of template, so you don’t need to write JavaScript.
I have also explored a lot of cool features on Cloudflare. For example, dynamically transforming media (such as image to webp), managed robots.txt, out-of-box analytics. I have to say I am really becoming interested in Cloudflare and I would like to learn more. My only concern is its accessibility from Chinese mainland because China Access appears to be a feature for the enterprise plan. Next time when I go back to Chinese mainland, I am going to test it out.
Back to the topic of 301 redirection for the old links of this site. I think the lesson learnt is never to assume the search engine will correct themselves. The correction loop can take long. Always doing your part is the way to go. For my site, after I finished this 301 redirection for those pages, I have requested Google to validate my fix for those 404 pages. Hopefully those pages will be indexed again after a few days.