Чтобы не “класть” систему, нужно перестать грузить все задачи и переносить тяжёлые операции (фильтр/сорт/агрегации) на сервер: добавить пагинацию, облегчённые представления данных и кэш/условные запросы. Дополнительно стоит сократить 6+ запросов карточки задачи до 1–2 за счёт “include/batch” и серверной агрегации, иначе задержки будут расти вместе с объёмом данных.​ Пагинация и лимиты Сделайте массовые эндпоинты пагинированными по умолчанию: GET /api/tasks?limit=50&cursor=... (или offset/limit как простой старт), возвращая next_cursor и принудительно ограничивая limit сверху.​ Для больших таблиц предпочтительнее cursor-based пагинация, потому что LIMIT/OFFSET деградирует по мере роста offset (БД всё равно “пролистывает” строки).​ Зафиксируйте стабильный ORDER BY (например, created_at, id) и требуйте его при пагинации, чтобы не ловить дубликаты/пропуски при конкурентных изменениях данных.​ Серверные фильтры и “лёгкие” ответы Перенесите сортировку/фильтрацию из браузера в API: status=, assignee=, form_id=, created_from/to=, search=, sort= — это уменьшит и нагрузку на клиент, и объём передаваемых данных.​ Добавьте “проекции”/выбор полей: fields=id,title,status,assigneeId,dueAt для списков и виджетов, а тяжёлые связи отдавайте только по запросу (например include=comments,fields,attachments).​ Для главной страницы замените “список всех задач” на специализированные агрегатные эндпоинты (например, GET /api/dashboard → счётчики, топ-N, последние изменения), чтобы UI не требовал полный датасет.​ Сокращение 6+ запросов карточки Уберите “N+1/размазывание” данных: вместо серии запросов сделайте 1 “task detail” эндпоинт с параметром include или один batch-эндпоинт (POST /api/tasks/batch с ids[]) — batching уменьшает число round-trip’ов и общую задержку.​ На уровне БД/ORM используйте eager loading / batch fetching связанных сущностей, чтобы не выполнять множество мелких запросов на каждую карточку.​ Если рассматривается более радикальный вариант, GraphQL + DataLoader-подобное батчирование часто применяют именно для систематического устранения N+1 на “богатых” экранах (карточки, сложные страницы).​ Кэширование и инкрементальные обновления Включите условные запросы: отдавайте ETag/Last-Modified, принимайте If-None-Match и возвращайте 304 Not Modified, чтобы при повторном открытии карточки/списка не перегонять те же данные.​ Комбинируйте Cache-Control (TTL) и валидацию через ETag, чтобы сокращать трафик и серверную работу при неизменных данных.​ На клиенте добавьте кэш по ID (нормализованный store) и “stale-while-revalidate” подход: открытие карточки берёт данные из кэша, а обновление идёт фоном с условным запросом.​ Если описать “план внедрения” в 3 этапа (быстрые изменения → средние → архитектурные), какие у вас ограничения: нельзя ломать контракт API, есть ли мобильные клиенты, и какая СУБД/ORM используется?