Cover Image for Фасетный поиск для магазина на 40 млн товаров: переход с InstantSearch на TanStack Query

Фасетный поиск для магазина на 40 млн товаров: переход с InstantSearch на TanStack Query

27 апреля 2026

Фасетный поиск в eCommerce — непростая задача, особенно когда каталог насчитывает миллионы позиций. В этом кейсе описываю путь от самописного решения через InstantSearch.js к связке TanStack Query и nuqs на Next.js.

Контекст проекта

  • B2C eCommerce-платформа с каталогом из 40+ миллионов SKU
  • Гибридная архитектура SSR/CSR с важным SEO-требованием
  • Поисковый движок Manticore Search
  • 15–20+ фасетов на категорию с динамическими атрибутами
  • Требование SSR без мерцаний при гидратации

Этап 1: Самописная реализация

На старте использовали простое решение: фильтры, прямые запросы в Manticore и состояние в useContext.

Проблемы:

  • Каждый новый фильтр приходилось править в нескольких местах кода
  • Сложная реализация disjunctive faceting («ИЛИ» внутри фасета, «И» между фасетами)
  • Дублирование логики между SSR и CSR, мерцания при гидратации
  • Статические фильтры не масштабировались при добавлении динамических атрибутов из PIM

Этап 2: InstantSearch.js с кастомным клиентом

Попробовали библиотеку InstantSearch.js для упрощения работы с фасетами и синхронизации состояния с URL.

Столкнулись с проблемами:

  • Двойной запрос при SSR (server action + API handler)
  • Отдельный запрос на каждый фильтр
  • Отсутствие документации по кастомному searchClient
  • Сложная отладка, гонки состояний при быстрых переключениях фильтров
  • Необходимость блокировать интерфейс во время загрузки данных
  • Время реализации — около 3 месяцев без стабильного результата

Вывод: InstantSearch хорошо работает в экосистеме Algolia, но для кастомного поискового движка требует значительных доработок.

Этап 3: TanStack Query + nuqs

Отказались от InstantSearch в пользу связки TanStack Query для управления серверным состоянием и nuqs для синхронизации с URL.

Что изменилось:

  • Все запросы через server actions, без промежуточных API handler
  • Состояние фильтров хранится в URL и queryKey
  • Единый запрос при изменении группы фильтров вместо множественных вызовов
  • Встроенное кэширование и дедупликация запросов из коробки
  • Возможность оптимистичных обновлений интерфейса без ожидания ответа сервера
  • Время перехода — около 2 недель до стабильной работы

Минусы TanStack Query:

  • Порог входа выше, чем у InstantSearch + Algolia. Но он понятный и предсказуемый. Всё ок с документацией.
  • Больше ручной работы. Нет готовых UI компонентов. В нашем случае UI уже был кастомным, так что не заметили.
  • Риск раздуть кэш при неаккуратных ключах.
  • SSR-гидратация всё равно требует внимания к архитектуре. TanStack Query решает проблемы данных, но не роутинг и не синхронизацию с URL.

Результаты:

Полный контроль над поведением запросов и состоянием приложения и предсказуемость работы всех компонентов системы на разных этапах рендеринга в клиентской и серверной части веб-приложения и меньше сетевых вызовов благодаря умному кэшированию и стабильный SSR без визуальных артефактов при гидратации на клиенте и отсутствие блокировки пользовательского интерфейса даже при очень быстрых последовательных переключениях фильтров пользователем и проще добавлять новые фильтры без переписывания существующей архитектуры системы и оптимистичные обновления интерфейса работают без задержек для пользователя.

Что выбрать?

  • InstantSearch.js — отличное решение, если вы работаете в экосистеме Algolia. Быстро, просто, с хорошим (возможно) SSR из коробки.
  • TanStack Query + nuqs — когда у вас кастомный поисковый движок, нестандартная логика фасетов или вы не хотите привязываться к Algolia. Даёт контроль и прозрачность, но требует больше ручной работы.

Выводы

Если у вас кастомный поисковый движок и нестандартная бизнес-логика фильтров, связка TanStack Query + nuqs даст больше контроля и предсказуемости чем попытки адаптировать InstantSearch. Да придётся написать больше кода руками но зато в поддержке такое решение проще а поведение системы понятнее. «, «Замечания: текст почти готов к публикации, исправил структуру и стиль, убрал шаблонные формулировки, сделал заголовки консистентными по уровню вложенности, разбил некоторые абзацы для удобного чтения с мобильных устройств.


Источник https://habr.com/ru/articles/1025854