Expedia Group — Engineering

Search Speed: Making Expedia Flights Faster

How we dramatically improved the performance of customer flight searches on Expedia

Heena Gupta
Expedia Group Technology
6 min readJan 3, 2024

--

People walk around a city in Norway
Photo by Oliver Cole on Unsplash
A line graph showing a sharp downward trend, plateauing at about half the height of the original line.
Trend showing improving in performance metric

Performance plays a crucial role in ensuring the responsiveness and functionalities of an application which leads to better end user experience and user engagements. It is vital for making the application scalable and maintainable in an efficient manner. Studies have shown the negative impact mediocre performance can have on business goals. High performing applications engage and retain users better than low performing ones. When we migrated Expedia Flights to Progressive web application, it enhanced the user experience and resulted in an increase in the demands at Expedia. However, the latency of Expedia Flights was too high, a standard monitoring of performance metrics was missing and there was a strong need to automate performance monitoring especially during releases which affected user retention and a seamless user experience.

Motivation

Expedia Group™ is a leading global travel platform. Flight searches are a large chunk of user traffic on our platform. Flights search is traditionally a heavy system with peak search traffic going regularly in the large range of transactions per second. There is a latency overhead associated with each request which goes all the way down to the supplier. It was noticed that the airline information obtained from third parties further added to the latency. While optimising the third-party APIs was not controllable, the goal was to optimise the network call and progressive web application for a seamless user experience. From the product analysis we found that a bad user experience leads to a drop in conversion and a higher page load time leads to a higher bounce rate as well. Better performance leads to higher user engagement and a reduction in overhead on both client & server side.

Performance metrics

To measure the performance in top 90th percentile, we produced the following derived performance metrics:

  • Page Usable Time: Page usable time measures the loading of a React component and is useful especially for Query components. This metric helped to determine the latency happening due to huge payload, multiple re-rendering and synchronous GraphQL calls.
  • Non-Supply Overhead: Non-supply overhead measures the journey of the GraphQL call from the beginning till the browser receives it, excluding the time spent getting the data which includes a lot of dependencies which is external to Expedia Group.

Other than the derived metrics, we also monitored the first contentful paint, first input delay, cumulative layout shift, and time to interactive.

Size limit: With the micro frontend architecture, we wanted to ensure the bundles for each of the packages are not exceeding the upper limit as this would affect performance especially on a slow network. To ensure this, we integrated Git commit hooks along with GitHub actions integrated for size limit when a pull request is raised.

How did we improve the performance?

We carried out some experimental performance initiatives among which the following are worth mentioning:

  • Prefetching of JS and CSS static resources: Fetching static resources could be made faster by prefetching a common set of resources needed for the next page that a user is likely to visit ahead of time. For the Flights Search Page, we prefetched the static JS and CSS bundles on the homepage for loading the bundles faster, which meant it did not need to wait for the respective resources. The prefetching of bundles improved page usable time marginally on the Flights Search page.
  • Faster caching: For any route, there can be lots of flight combinations. For instance, it is common to see a huge number of unique flight combinations for return travel between source and destination on any given date. To create a unique yet coherent experience for the users, we slice and dice these combinations and show a best-differentiated subset to the users based on the user’s current position in the shopping funnel. The combinations are also affected by individual preferences and interactions in their current session. Our caching solution was powered by Apache Cassandra and it has been serving our requirements for many years. Even though the Cassandra fetch times are swift, the 90th percentile of the overall response time of the flight search service was more than 3 seconds to display results from the cache to the user. The goal of this project is to build a search offer cache for Flights to add the capability to assess if the search for identical parameters is still in progress and accordingly make the subsequent identical searches “wait” for the results from down level or serve from cache if already available. It improved in non-supply overhead by ~10%.
  • Preemptive Search: The payload size is huge for Flights at Expedia, so to save the computation and fetch time from third party APIs the search criteria was predicted even before the user lands on Flights Search page. This is done by passing the search criteria beforehand from homepage which is then passed downstream to process further. When the user lands on Flights search page, the cached search response is shown to the user and thereby reduces the latency significantly. To reduce the number of networks calls on Homepage for preemptive search, the network call is triggered on the last field updated by majority of the end users. With the preemptive search experiment, a visible improvement of ~50% was observed on page usable time on Web and Native apps (iOS/Android).
  • Horizontal and Vertical Slicing: The GraphQL query on Flights Search page was very expensive as the payload size was huge for search result combinations obtained from the third party. To optimise the payload size, it was broken down into smaller GraphQL queries to obtain the list of search offers in chunks rather than all at once within Expedia. This helped improve the user experience as the users no longer need to wait to have a quick glance on the results and could check the loaded search offers while the remaining search offers are getting resolved on client side. In addition to horizontal slicing, when a user clicks on search offers, the detailed information for the search offers is shown which usually takes some time to resolve due to downstream call. To let the user be able to view the search offers summary faster, the detailed information was separated out to another GraphQL query which only resolves upsell information. This helped speed up the user experience as now the user can view the summary information faster and the downstream call will be made only for the offer which is clicked. Horizontal Slicing experiment improved the non-supply overhead by 20% on Web and Native apps (iOS/Android)
  • Async GraphQL loading and loaded states: Based on the code inspection, it was noticed that the loading and loaded GraphQL queries were not async. The loading call being a server-side call, is quicker to resolve and happens first followed by the client-side loaded call. This implies that the loaded call will wait for the loading call to resolve first and then will get resolved which will increase the page load time further. To optimise the network calls here, we did an experiment in which we prepared the request params for the loaded GraphQL call at an initial stage by injecting the fetch (XHR) into the HTML beforehand and resolved the promise of fetch at a later stage. As a result of this we noticed an improvement of ~8% on non-supply overhead and slight improvement in page usable time.
  • Micro frontend architecture: We have broken down the Expedia Flights PWA codebase into shareable packages which are reused across other lines of business as well. These shareable independent packages are then owned by their respective service owners, allowing flexibility, reusability, and better optimizations at the package level. With micro-frontend architecture in place, the build size has improved significantly as only the packages that are needed by the Flights progressive web application are being utilised.

Conclusion and impact

As a result of these performance initiatives, we observed a visible impact on the top 90th percentile on Page usable time by 52% overall and top 90th percentile on non-supply overhead by 40%. This is a great result and has improved search speed for all of our customers looking for flights on Expedia.

Learn about life at Expedia Group

--

--