Фасетный поиск для магазина на 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


