Performance Optimization for Lightning-Fast Apps

performance optimization

You can lose potential customers because your website or app takes too long to load. That’s right - performance issues can turn away users in an instant. A 1-second delay in page load time can result in a 7% reduction in conversions.

That's a huge impact on your bottom line.

By optimizing your platform's performance, you can create a faster, smoother user experience that keeps visitors engaged and happy.

If you clicked on this article, you’re likely looking to get more out of your current system or just curious. Either way, let’s get straight into it ⚡️

What is performance optimization?

Performance optimization (also performance tuning) is the process of improving the speed, efficiency, and responsiveness of software applications. Everything from a website to SaaS, web and mobile apps should be optimized regularly.

If you’ve ever been frustrated by a slow website or app, you know how important performance is. The goals of performance optimization are to reduce load times, improve responsiveness, and ensure stability across different platforms, network and client speeds.

When your application runs smoothly, it's not only more enjoyable for users but also easier for developers to work with and manage.

As your application grows, so does the complexity. New features, bug fixes, and integrations can make the code harder to understand and maintain. Legacy code, written with outdated practices or technologies, can be particularly problematic, slowing down progress.

Accumulated shortcuts and temporary solutions (technical debt) can also slow down future development. Over time, these debts need to be "repaid" through refactoring and optimization.

How to identify performance bottlenecks

Slow load times, lagging responsiveness, and high bounce rates are some of the most frequent complaints from users. Here are some of the common culprits:

  • Large, unoptimized images: They can significantly slow down load times.
  • Excessive HTTP requests: Every element on a page, from images to scripts, requires an HTTP request, and too many can bog down performance.
  • Poorly written code: Inefficient code can make your app sluggish.
  • Lack of caching: Without proper caching, your server has to generate the same content repeatedly, increasing load times.
  • Inefficient server configurations: Slow server response times can hurt performance.
  • Third-party scripts: Third-party scripts (like ads, social media widgets, and analytics tools) can add significant load time to your site.
  • Frameworks: Using the wrong tech for your platform can lead to suboptimal results. And no matter how much you optimize you can run into framework limitations. For example, if your primary goal is initial page speed, using Angular isn’t ideal.

Code reviews

Code reviews include examining your codebase to check for inefficiencies, redundant code, logic errors and that best practices were followed. You should involve your dev team and at least one senior developer - after all, two heads are better than one, and a fresh pair of eyes can often catch issues that you might miss. Not only does this practice improve code quality, but it also helps developers get familiar with the system.

Monitoring and testing

Continuously monitoring and assessing software performance is key to catching and addressing issues as they arise. Using a combination of tools like Lighthouse and automated testing can make this process more efficient.

Developers can write automated tests that run with each update to ensure new code doesn’t break existing functionality. This not only helps maintain a high-quality product but also significantly reduces the need for manual testing.

At All Front, we are fans of using Debugbear, which allows us to easily monitor pages and their performance over time.

Collaboration efforts

Performance optimization should be a team effort. You should encourage communication and input from developers, designers, and project managers to ensure everyone is aligned on performance goals. A collaborative approach can lead to more comprehensive and effective solutions.

User-centric focus

Your users are the best indicators of your platform’s performance. Make sure you talk to your users regularly, collect feedback through surveys, feedback forms and usability testing, and monitor their behaviour to identify common pains and friction points. Users can often highlight slowdowns that automated tools might miss.

Iterative approach

Performance optimization is an ongoing, iterative process. Start by identifying and optimizing the slowest elements first. Keep in mind that when you improve one area, this can reveal limitations or opportunities in other areas. For example, speeding up database queries might expose bottlenecks in server response time.

Areas of performance optimization

Performance optimization can target different aspects of the system - front-end processes like images and scripts and back-end processes like server responses and database queries.

Front end

The front-end layer of performance optimization includes everything that happens on the client side. Since this is the most ‘visible’ part of performance optimization, it can have an immediate and noticeable impact on how users perceive your platform.

Bundle size

Bundle size is the combined file size of all code, libraries, and dependencies that are served to users in their browsers. This directly affects the speed of your platform - a bigger bundle size means longer load times.

Depending on the type of web app you employ, you can use different techniques to reduce bundle size. For example, if you’re using SPAs (single-page apps):

  • Serving only content the user sees above the fold, and loading the rest asynchronously.
  • Serving an SSR version of the page and then hydrating it. Check out this guide on Angular's Partial Hydration.

If you’re using MPAs (multi-page apps), bundle size usually is a smaller concern.

Enable caching

Instead of making users download the same resources every time they visit your site, browser caching stores these resources locally. This means faster load times on repeat visits and a more seamless experience.

Caching can be done:

  • On the end-user’s browser
  • On a CDN / server that keeps a copy of your site distributed on several servers across the globe
  • Using techniques like progressive web apps

Optimize images and animations

High-quality images and animations can make your app look great, but they can be quite heavy. One way you can optimize large images is by incorporating an image component that utilises modern web features to deliver only the specific type and size of image when needed.

For example, for one client we developed an image component that uses .webp images which are smaller in size. If a browser doesn’t support .webp, a fallback .jpg or .png image is fetched instead.

This component also provides retina images to devices with higher pixel density to avoid compromising image quality. A matching image size is also loaded for each device screen to avoid unnecessarily large images, improving page load time. While the image loads, we show a thumbnail version of the image until the full one loads, to avoid content shift.

When it comes to animations, use them with caution - we have seen massive 1MB+ Lottie animations slowing down sites in the wild. A little CSS goes a long way.

Optimize font loading

Fonts, much like images and animations, can be a great way to add personality and branding to your platform. However, using different styles of fonts can hurt performance. To tackle this, you can only load the characters you need using techniques like font subsetting.

For projects that use variable fonts, one strategy is loading only a subset of the font on the server side while on the client side we load the full font features. This way you can reduce the initial request size, and content doesn’t shift around when the site finishes loading. We applied this approach with one client that had an 800 KB variable font, which was nice but was also slowing everything down.

You can push this technique quite far too - for example, you can scan the HTML pages on your site and create subsets that only include features and characters that you are using. We did this to reduce the 800 KB font to 46 KB.

Also, another way to optimize font size is by using system fonts (if your designer is okay with foregoing some artistic liberty for performance) or hosting fonts locally to reduce the number of external requests.

Asynchronous and lazy loading

Asynchronous loading allows content to load in the background without blocking the rendering of the page. Similarly, lazy loading waits to render elements only when they are about to come into view, saving bandwidth and reducing the initial load time.

When possible, instead of loading analytics on the client side, see if you can do it on the server side instead. It’s trivial to send an analytics request to your server. This way you can reduce the bundle size and optimize page speed, helping you rank higher in search results and deliver a pleasant user experience.

One example relating to third-party scripts - we had to load an intercom chat plugin for a client that was pretty heavy and slowed the site down. Instead, we made a copy of the chat icon and only loaded the plugin once the users clicked on it, reducing the bundle size significantly.

Custom native components

When it makes sense and you have the resources for it, it might be a better idea to develop a custom native component than rely on third-party libraries. Third-party sliders can often be large and have additional features that you don’t need.

With one client project, we struggled to manipulate a slider library to perform well both on desktop and mobile devices, and SSR and client versions. All this without slowing down the initial load and adhering to the designer’s specifications.

Finally, we decided to develop a custom slider with native browser features. It was lightweight, fast, had all of the features the client needed and delivered a great user experience on all platforms. It’s only a shame we even tried going for a library in the first place.

Back end

While front-end optimization enhances what users see and interact with, back-end optimization ensures that data is delivered quickly and efficiently. Slow server responses or inefficient database queries can hurt the overall performance (no matter how optimized the front end is), and result in what front-end devs refer to as “Spinner Hell”.

Frameworks

We’ve seen developers go to extreme lengths to avoid writing one line of SQL. This often means using ORMs for all situations or tools built on top of ORMs. Back-end frameworks are a double-edged sword - you speed up development time at the risk of running into potential issues down the line.

Pay very close attention to the frameworks you’re running with, and look not just at their nice shiny features and landing page, but open their GitHub page and dig through the issues. Try searching for queries along the lines of: “performance”, “slow”, “load testing”.

Database queries

Inefficient database queries can bottleneck your entire system. They also don’t manifest themselves until deployed unless your developers are doing load testing or running large databases locally.

Query optimization involves reducing the time it takes to execute queries, minimizing the resources they consume, and ensuring that they scale as your data grows. Efficient queries can handle large volumes of data quickly and with minimal impact on overall performance.

The first step for query optimization is often logging the queries themselves. If you are using an ORM, try to figure out if the problem is happening at your ORM layer or SQL layer. Then you can look into profiling tools.

For example:

The most common issues usually relate to indexing, inefficient relationships or architecture, minimizing database calls, and concurrency issues.

Server performance

Your server’s performance directly impacts your app’s speed and reliability. You need to:

  • Make sure you are on sufficiently powerful hardware to keep response times low.
  • If you don’t have a server and use Lambda, keep an eye out for cold start issues.
  • Make sure the SSL handshake is quick.
  • Make sure your server is geographically close to where your users are located. The speed of light might not be fast enough if your server is in Australia and your clients are in the US.
  • Monitor server metrics like CPU, network, and disk usage, and keep a lookout for bottlenecks.
  • And hey, if you notice your server is running toasty 🔥 clean up those fans!

While you don’t want to have more servers than you have users, one server might not always be enough. Load balancing is another technique for optimizing server performance. By distributing traffic across multiple servers, you prevent any single server from becoming overwhelmed.

You can also consider using Content Delivery Networks (CDNs) to cache and deliver content from servers closer to your users, reducing latency and speeding up load times.

Back-end caching

“There are only two hard things in Computer Science: cache invalidation and naming things.” - Phil Karlton

Back-end caching can significantly reduce the time it takes for pages to load, but how this would be implemented massively depends on your use case. Caching can be done on basically every layer. For example:

  • Caching responses when the requests are the same.
  • Caching database results through your ORM.
  • Adding application-server level caching such as Redis.

By utilising caching in a smart way, you can improve user experience and drive costs down. However, it comes at the expense of complexity, and a risk that users might not get the latest and greatest version of the content if not done correctly.

We don’t have time to delve into implementation details in this article, however, here is an in-depth video on back-end caching.

Server-side rendering

Server-side rendering (SSR) is an approach to rendering web pages on the server rather than in the browser. This eliminates issues like partial rendering or missing content due to less powerful machines or outdated technologies. SSR can also positively impact SEO as search engines can crawl and index pages more easily.

By implementing SSR, we managed to cut down initial response time threefold for an e-commerce project with Fusonic.

Metrics for measuring performance

For successful performance optimization, you need the right metrics and KPIs. Without them, you’re navigating in the dark.

Core Web Vitals

The Core Web Vitals are a set of three metrics used by Google to assess how fast, responsive and reliable your site is. Google has confirmed that they use the Core Web Vitals as one of the ranking factors for assessing overall page experience.

These are:

  • Largest Contentful Paint (LCP) measures when the largest piece of content is fully rendered.
  • Interaction to Next Paint (INP) measures the time your platform takes to respond to user interactions.
  • Cumulative Layout Shift (CLS) measures the visual stability of the page by tracking unexpected layout shifts that occur during the entire lifespan of the page.

First Contentful Paint (FCP)

First Contentful Paint (FCP) measures when the first piece of content appears on the page. This could be text, an image, or any other visual element. A fast FCP gives users a sense that something is happening, which reduces the perceived load time.

Time to Interactive (TTI)

Time to Interactive (TTI) measures how long it takes for a page to become fully interactive, both visually loaded and responsive to user input.

TTI comes after FCP and the time between the two is also measured (Total Blocking Time) to uncover gaps between when the page is visually loaded and usable. This is crucial because a page that loads quickly but isn’t interactive can lead to frustration and higher bounce rates.

We all know how annoying is to click a button repeatedly and get no response. Don’t let your users experience that - they’ll quickly leave.

Time to First Byte (TTFB)

Time to First Byte (TTFB) measures the time it takes for a client’s browser to receive the first byte of data from the server. This includes the time it takes for the request to reach the server, the time it takes for the server to process the request, and the time it takes for the first byte of data to reach the client.

These are just some of the performance metrics used across the web and some tools like PageSpeed and Lighthouse. However, every case is different and some metrics might not apply to you, or you might want to use custom metrics.

Final overview

Modern users expect nothing less than fast, responsive and reliable apps that deliver exceptional user experience - that’s where performance optimization comes in.

Performance optimization has many levels that require a strategic, comprehensive approach. Start by auditing your current system to identify performance bottlenecks and set clear performance goals. This will also guide your choice of relevant metrics.

Performance optimization also requires a strong team who understands your business and your product inside out. If you don’t have an in-house team or your developers need a hand or two, let's chat. Performance optimization is one of our fortes 😉

Tags

Agile
Development
menu_icon
David Stellini

3rd June 2024