ArchitecturePro
Услуги ▼
Premium eCommerce B2B Порталы Промо & WebGL
Кастомная веб-разработка (SPA, PWA) Мобильные приложения (iOS/Android) Корпоративные сайты на WordPress Лендинги и спецпроекты UI/UX Дизайн и аналитика Техподдержка и развитие
Кейсы О компании Процесс Блог
Связаться
Меню
Услуги
Premium eCommerce B2B Порталы Промо & WebGL Кастомная веб-разработка Мобильные приложения Корпоративные сайты Лендинги и спецпроекты UI/UX Дизайн и аналитика Техподдержка и развитие
Кейсы О компании Процесс Блог Оставить заявку

[ Tech Hub ]

Заметки Senior-архитектора. Делюсь опытом проектирования сложных систем, оптимизации баз данных и вывода сайтов в зеленую зону Lighthouse.

REST API vs GraphQL
12 Окт 2023[ 6 min read ]

Почему мы отказались от REST в пользу GraphQL в Highload-проекте

Проблема Overfetching'а в REST API. Как переход на GraphQL сократил нагрузку на базу данных в 3 раза и ускорил рендеринг клиента.

./read_article
Next.js Lighthouse 100
28 Ноя 2023[ 8 min read ]

Как оптимизировать Next.js для Google Lighthouse на 100 баллов

Побеждаем Core Web Vitals. Разбор SSR против SSG, правильная работа с next/image и динамические импорты тяжелых компонентов.

./read_article
Ошибки проектирования БД
15 Фев 2024[ 5 min read ]

Ошибки проектирования базы данных, которые убьют ваш стартап

N+1 problem в ORM, отсутствие индексов и избыточная нормализация. Чего нельзя делать при проектировании PostgreSQL.

./read_article
×

Почему мы отказались от REST в пользу GraphQL в Highload-проекте

Схема работы GraphQL

Когда мы начинали разработку крупного маркетплейса, выбор архитектуры API казался очевидным — классический REST. Однако по мере роста проекта и появления новых ролей (мобильное приложение, админка, B2B-портал) мы столкнулись с классическими проблемами REST API.

Проблема: Overfetching и Underfetching

На главной странице нам нужно было показать список товаров. Мобильному клиенту требовалось только 3 поля: `id`, `title` и `price`. Но REST API `/api/products` возвращал огромный JSON на 50 полей, включая описания, характеристики и массив отзывов. Это называется Overfetching — передача избыточных данных, что забивает канал на мобильных устройствах.

В то же время, чтобы отобразить карточку товара с автором и отзывами, клиенту приходилось делать 3 разных запроса к серверу (`/products/1`, `/users/5`, `/reviews?productId=1`). Это Underfetching.

Решение: Переход на GraphQL

Мы внедрили Apollo Server (Node.js) в качестве шлюза. Теперь клиент сам решает, какие данные ему нужны.


// Запрос от мобильного клиента
query GetMobileProducts {
  products {
    id
    title
    price
  }
}
            

Результаты перехода:

  • Объем передаваемого трафика на мобильных устройствах снизился на 75%.
  • Количество запросов к базе данных сократилось благодаря использованию DataLoader (решение проблемы N+1 на уровне GraphQL).
  • Frontend-разработчики перестали просить backend добавить "еще одно поле в этот эндпоинт", разработка ускорилась в 2 раза.

Как оптимизировать Next.js для Google Lighthouse на 100 баллов

Показатели Lighthouse 100 баллов

В премиальном eCommerce скорость загрузки сайта напрямую влияет на конверсию. Мы поставили задачу: вывести сложный интернет-магазин с 3D-моделями и сложной фильтрацией в зеленую зону (90+ баллов) по всем показателям Core Web Vitals.

1. SSG вместо SSR где это возможно

Многие разработчики злоупотребляют getServerSideProps в Next.js. Это заставляет сервер рендерить страницу заново при каждом запросе, увеличивая показатель TTFB (Time to First Byte).

Мы перевели каталог на Static Site Generation (SSG) с использованием getStaticProps и Incremental Static Regeneration (ISR). Страницы товаров теперь лежат в кэше CDN и отдаются за 30 миллисекунд.

2. Оптимизация Largest Contentful Paint (LCP)

Главная баннерная картинка — это обычно самый большой элемент (LCP). Если загружать ее стандартным тегом <img>, Lighthouse снимет баллы.


import Image from 'next/image';

// Правильное использование next/image для LCP:
<Image 
  src="/hero-banner.webp" 
  alt="Main Banner" 
  priority={true} // Критично для LCP!
  width={1920} 
  height={1080} 
/>
            

3. Динамические импорты (Code Splitting)

Тяжелые библиотеки (например, чат поддержки или 3D-вьювер) не должны грузиться при начальной загрузке страницы. Мы использовали next/dynamic:

В итоге, показатель Total Blocking Time (TBT) снизился с 400ms до 20ms, а общий балл Performance в мобильной версии вырос с 62 до 98.

Ошибки проектирования базы данных, которые убьют ваш стартап

Архитектура базы данных

За годы проведения аудитов IT-инфраструктуры мы видели сотни проектов, которые начинали тормозить сразу после запуска маркетинговой кампании. И в 90% случаев проблема скрывалась не в языке программирования, а в архитектуре PostgreSQL.

Ошибка 1: Проблема N+1 в ORM

Использование ORM (Prisma, TypeORM, Sequelize) сильно упрощает жизнь разработчикам, но скрывает реальные SQL-запросы. Самая частая ошибка — запрос связанных таблиц в цикле.

Вместо того чтобы достать пользователей и их заказы одним запросом (JOIN), ORM делает 1 запрос на пользователей, а затем 100 отдельных запросов на заказы каждого пользователя. Решение: всегда использовать .include() в Prisma или JOIN FETCH, а также настраивать логирование долгих запросов на сервере.

Ошибка 2: Игнорирование индексов (и их избыток)

Отсутствие индекса на колонке, по которой часто происходит поиск (например, `user_email` или `status`), приводит к Seq Scan — полному перебору таблицы.


-- Создание правильного индекса
CREATE INDEX idx_orders_status ON orders (status) WHERE status = 'pending';
            

Однако есть и обратная ошибка — вешать индексы на каждую колонку. Индексы ускоряют SELECT, но замедляют INSERT и UPDATE, так как при каждой записи базе нужно перестраивать индексное дерево.

Ошибка 3: Хранение JSON там, где нужна реляция

PostgreSQL отлично работает с JSONB. Это соблазняет разработчиков складывать сложные данные (например, характеристики товара) в одну JSON-колонку. Но когда заказчику требуется отсортировать товары по значению внутри этого JSON, база начинает сильно тормозить. Если по полю нужен поиск или сортировка — это должна быть отдельная колонка в таблице.

Telegram Позвонить