How We Made Catalog Listing Page 7x Faster Without Upgrading ElasticSearch Version

Hakan Taşan
hepsiburadatech
Published in
4 min readSep 12, 2023

Millions of items available on Hepsiburada undergo a meticulous series of steps before becoming visible on the website or app. Among these steps, there is the crucial task of cataloging the products within their respective category hierarchy and conducting thorough reviews. While our system employs robust AI validations, the ultimate responsibility for listing, filtering, and making any required adjustments to these products falls upon the Category Team or Catalog Operation Team. This process is facilitated through the user-friendly Vidar interface, complete with left-hand filters that help users explore various product variants.

Vidar was experiencing a significant slowdown, with total product variant count exceeding 200 million. The conventional solution would have been to upgrade ElasticSearch from version 7.6 to 8.*, but that would entail substantial code changes, data migration, and extensive testing. Moreover, there was no guarantee that this upgrade would significantly improve performance. We decided to take a closer look at whether we were fully utilizing the capabilities of Elastic 7.6 before making such a drastic move.

Identifying and Addressing the Issues:

Previous state of catalog listing page:

1. Deep-Pagination:

Our initial examination revealed that the listing part of the Vidar page was utilizing deep-pagination, which performed poorly with such a vast dataset. Even occasional unresponsiveness could occur if the queried data was too costly such as if you tried to get the last page for millions of data. To address this, we transitioned to the more efficient search-after method. This change yielded significant performance improvements. This transition introduced numberless “previous-next” buttons as a natural outcome of the search-after method, resulting in a more responsive user experience.

Resources:

2. Single Call for Listing and Filtering:

Another issue stemmed from the frontend module making a single call to retrieve both listing and filter components. Although ElasticSearch calls for these separate components were fetched in parallel, the faster component still had to wait for the slower one before constructing the full response. Furthermore, processes like sorting or changing pages also triggered ElasticSearch to fetch the costly filter component, even when unnecessary. To resolve this, we separated listing and filter endpoints, allowing for more efficient data retrieval.

3. Redundant Total Count Calculation:

Total variant count for selected filters, a critical piece of information for our users, was being calculated redundantly. While the aggregation endpoint naturally provided this count, the listing endpoint was also calculating and returning it with every call. Our frontend then retrieved this value from the listing endpoint. To improve performance, we eliminated the redundant calculation in search-after endpoint and used total count data from aggregation endpoint in the frontend.

4. Aggregation Fetch:

Additionally, we optimized the aggregation part of our system through parallel aggregation fetching. We divided our aggregation fields (which were many) into multiple smaller queries and ran them in parallel. This approach helped distribute the workload and take advantage of the parallel processing capabilities of ElasticSearch. While not as pivotal as the first three improvements, this enhancement notably impacted the average and worst-case scenarios, improving overall performance.

Resources:

Architectural Changes:

To illustrate the changes we made, let’s take a look at the old and new architecture of our Catalog Listing page:

Additional to the changes visible in the diagram, the old listing call calculated and returned total count, new one does not. New aggregation call returns the already calculated total count.

New aggregation call does not need to be made every time listing is called, and cronus is free to render one independent from the other.

Performance Improvements:

These changes resulted in significant performance enhancements:

  • For the listing part, we achieved a 7x improvement on average, with a staggering 35x improvement at its fastest and a solid 4x improvement at its slowest.
  • In the aggregation part, we realized a 3x improvement on average, a 1.5x improvement at its fastest, and a 2x improvement at its slowest.

When it comes to user interactions such as page navigation and filtering, our modifications have streamlined the process. Users can now effortlessly move between pages without the need to fetch aggregation data. Additionally, as users apply more filters, both calls become significantly faster. This ensures swift and efficient interaction, ultimately enhancing the overall user experience and contributing to company productivity.

Conclusion:

Through the resolution of deep-pagination issues, endpoint optimization, and the elimination of redundant total count calculations, we achieved a notable performance boost for our Vidar Catalog Listing page, all without the need for an ElasticSearch version upgrade. While our upgrade plans remain on the horizon, our present resource constraints have posed challenges to prioritize this extensive undertaking. Nevertheless, it’s worth highlighting that when we eventually proceed with the upgrade to ElasticSearch 8.*, it will synergize seamlessly with the improvements we’ve already implemented using the search-after approach. This synergy promises a further substantial performance enhancement. The relatively straightforward nature of these optimizations has already delivered significant results, paving the way for a more streamlined and efficient upgrade in the future. The performance improvements in the catalog listing page decreased the time that our operation team spent per product check and edit, and contributed to the efficiency of the company significantly.

--

--