How I optimized page loading by eliminating performance bottlenecks

How I optimized page loading by eliminating performance bottlenecks

Optimizing a legacy application

·

5 min read

In 2019 I started my journey as a Junior Frontend Developer at a company that had two legacy applications.

One was built in .NET C# and server-side rendered cshtml pages

The other was a mobile application built in Knockout.js, Durandal, TypeScript, and jQuery.

Even though I had only built fullstack applications in React, MongoDB, and Node.js, I did not feel too intimidated by this setup because I knew I had the foundational knowledge applicable to this stack.

I was hungry to learn more about how production apps work and the stakes attached to them. Once I started delving into it, it took me around a week to get up to speed with these technologies. At this point, I had enough knowledge to start contributing to the codebase and making minor fixes.

Issues

There were a few glaring issues with the optimization of both of the applications

  • It took more than 20s for the first-page load

  • The CDN server kept getting overloaded with image requests

    If you know about the standard, it’s never to make your users wait for more than 5 seconds before showing something.

After about 6 months or so at this place, I felt confident enough to work on these issues.

Working Towards It: I can’t REST my case

To do this, I had to delve into the backend of the application, which was a REST API built with .NET.

I had no experience working with .NET on the backend at this time. The only work I had done was build small games in XNA 6 years earlier. So, while I could navigate the syntax and understand what might be going on. There was a learning curve.

Taking alternate routes

Instead of trying to understand the system to optimize it, I took the route of observing the system. . I made a list of these.

So I approached it from a frontend perspective:

  • I went to the dev console on chrome and looked at what requests are taking the longest to resolve

  • These requests ranged from 10-20s and I noted them down

  • I checked the endpoint for each query to see what we are trying to do

  • I tallied it with the frontend to check what data we are actually using

I checked which Controller each request belongs to. Since we had a dual model happening here because of later feature development, we had duplicate endpoints, one returning JSON and the other returning an HTML page and unsurprisingly, the JSON endpoint was not filtering out any of the data that was specific to the HTML page.

So, it had all of these extra fields, more user data than we needed on the front end, and dozens of deprecated fields and objects.

I experimented with the endpoint and in the end, I had a really good idea of what I wanted to do.

Now, I could easily optimize the JSON endpoint. I was able to reduce the response size from 20KB to just 2KB, that was a 90% improvement. The request time reduced to 1 second and the website loaded much faster.

Takeaways

  • I learned from this experience was, that you don’t necessarily need to have a full understanding of the system to debug or optimize it.

  • And you don’t need to have full knowledge of syntax as long as you have a strong idea of what you are doing.

Give me the CDN

Another thing I noticed in the mobile application was that our CDN load was way too much. Considering that a lot of our images were static and used in multiple places. I was expecting that the browser cache would just store it and not even hit the CDN.

Then why is the CDN getting so many hits?!

Network tab to the rescue

I checked the network tab and found that images were not being cached. Turns out we were using a versioning technique on the whole app that was cascading to images.

That would’ve made the CDN overload because there was no browser caching going on and every request was a new request.

This was more a frontend issue so I was able to resolve it quickly, I specifically removed the randomly generated id on each load from the images and they started caching.

This reduced the load on our CDN by more than 50%.

Doing this kind of optimization has always made me excited, I am not a big proponent of optimizing as you go. We can see the big picture much clearer when it’s done and optimize to our heart’s content at that point.

Takeaways

  • Build first, optimize later

  • Cache as much as you can. CDN might be an edge cache but it still costs money, if you can cache something on the client, do it

How to make sure you optimize properly?

  • If you don’t track it, you can’t optimize it

I believe every team should have metrics for their application, there should be some form of tagging on them, let’s say Green, Yellow, and Red. Your goal should be to never hit the Red status on these.

  • Take action: Prioritize

When the performance metrics hit a Yellow, it should be a call to take action and see what’s going on.

  • Be fluid

These metrics don’t have to be static though, but they should be pretty difficult to change. The reality is that as our apps keep getting more complex, we do have to make tradeoffs, so at that point, you can raise the limit for these statuses.

Takeaway

  • Don’t be hesitant to delve into deeper systems of your application

  • Take the initiative by yourself to improve the application you are working on

  • You don’t need to have experience with the technologies to find bottlenecks

  • Have systems in place to measure performance and take action

  • You don’t need to wait for a ticket in JIRA to explore the product you are working on