Medusa, Saleor и Vendure решают одну базовую задачу: предоставляют готовое commerce-ядро, к которому разработчики подключают собственный интернет-магазин, мобильное приложение, кабинет менеджера или несколько клиентских интерфейсов. В отличие от монолитных платформ, backend здесь не определяет внешний вид витрины и не требует использовать встроенную тему.
Однако сходство заканчивается на общей headless-модели. Medusa и Vendure ориентированы прежде всего на TypeScript-экосистему, но предлагают разные API и способы расширения. Saleor построен на Python и Django, использует GraphQL как основной контракт и заметно отличается по эксплуатационной модели. Поэтому выбирать следует не по числу функций в рекламном списке, а по соответствию архитектуре проекта, компетенциям команды и планируемым доработкам.
Что именно сравнивается
Все три решения подходят для self-hosted-развёртывания и отделяют commerce-backend от клиентского приложения. Фронтенд можно написать на Next.js, Nuxt, SvelteKit, Angular, мобильном фреймворке или собственном серверном стеке. Для backend не имеет принципиального значения, как именно страницы будут отрисовываться пользователю, пока клиент корректно работает с API.
При выборе важны следующие характеристики:
- язык backend и основной технологический стек;
- тип API и удобство его использования из собственного фронтенда;
- модель каталога, цен, каналов продаж и остатков;
- устройство корзины, checkout и жизненного цикла заказа;
- возможности встроенного расширения без форка ядра;
- поддерживаемая база данных и роль дополнительных сервисов;
- состав production-инфраструктуры и требования к VPS;
- сложность обновлений, фоновых задач и горизонтального масштабирования.
Headless-платформа не является готовой витриной. Даже если проект предоставляет starter storefront, его следует воспринимать как пример интеграции и основу для разработки, а не как обязательную часть системы. Команда всё равно отвечает за интерфейс, SEO, серверный рендеринг, аналитику, обработку ошибок API и согласование процесса оформления заказа с backend.
Краткое сравнение архитектуры
| Критерий | Medusa | Saleor | Vendure |
|---|---|---|---|
| Основной язык | TypeScript | Python | TypeScript |
| Backend-основа | Node.js, модульное commerce-приложение | Django и связанная Python-инфраструктура | Node.js и NestJS |
| Основной API | REST | GraphQL | GraphQL |
| Разделение API | Store и Admin endpoints | Единая GraphQL-схема с разграничением доступа | Shop API и Admin API |
| Основная БД | PostgreSQL | PostgreSQL | PostgreSQL, MySQL/MariaDB; SQLite уместна для разработки и простых стендов |
| Модель расширения | Модули, workflows, плагины, маршруты и подписчики | Apps, webhooks и расширения dashboard; глубокие изменения ядра сложнее изолировать | Плагины, custom fields, расширение GraphQL и настраиваемые процессы |
| Фоновые операции | Worker и инфраструктурные модули | Очереди и отдельные фоновые workers | Worker и очередь заданий |
Таблица показывает общее направление, но не отвечает на главный вопрос: где будет находиться нестандартная бизнес-логика проекта. Если она должна выполняться внутри commerce-backend, особенно важна модель плагинов и доменных расширений. Если же интеграции планируется выносить в независимые приложения, более значимыми становятся стабильность API, webhooks и изоляция внешних сервисов.

Medusa: модульное commerce-ядро на TypeScript
Medusa построена вокруг Node.js и TypeScript. Запрос поступает в HTTP-маршрут, затем бизнес-операция выполняется через workflow, а работа с конкретной предметной областью передаётся модулю. Такой подход отделяет транспортный слой от последовательности бизнес-действий и хранения данных.
Commerce-функции разделены на домены: товары, цены, корзины, заказы, платежи, остатки, склады, выполнение заказов и другие части системы. Разработчик может добавлять собственные модули, связывать их с существующими сущностями и включать новые шаги в workflows. Для повторно используемого набора доработок предусмотрена модель плагинов.
API и разработка фронтенда
Основной интерфейс Medusa — REST API. Store API предназначен для витрины, корзины и действий покупателя, Admin API — для управления магазином и внутренних инструментов. Для JavaScript-клиентов доступен SDK, но фронтенд не обязан быть написан на JavaScript: REST можно вызывать из любого окружения.
REST упрощает интеграцию для команд, которым удобны явные ресурсы и HTTP-маршруты. Цена этой простоты проявляется на сложных страницах: витрине иногда требуется несколько запросов или специально подготовленный endpoint. Если проект привык строить интерфейсы вокруг GraphQL-фрагментов и выборки строго заданного набора полей, Medusa потребует иного подхода либо создания агрегирующего API-слоя.
Каталог и продажи
Каталог поддерживает товары, варианты, опции, категории и коллекции. Цены, остатки и доступность связаны с отдельными commerce-доменами, поэтому модель подходит для магазинов, где один товар продаётся в разных вариантах, каналах или регионах. Склады и уровни запасов можно учитывать отдельно от карточки товара.
Сильная сторона такого разделения — возможность менять отдельные части системы. Например, подключить внешний сервис платежей, файловое хранилище, систему уведомлений или собственную складскую логику. Обратная сторона — разработчику необходимо понимать связи между модулями. Нестандартная операция редко сводится к изменению одной таблицы: она должна быть корректно встроена в workflow и не нарушать компенсацию уже выполненных шагов.
Заказы и расширяемость
Medusa предоставляет сущности и операции для корзины, оформления покупки, оплаты, заказа, доставки, возвратов и выполнения заказа. Специфические сценарии можно собирать в workflows. Это удобно, когда магазин должен резервировать товар во внешней системе, рассчитывать особую скидку, создавать запись в ERP или запускать несколько связанных действий после заказа.
Расширение возможно через собственные API routes, модули, workflows, подписчиков на события, фоновые задания и плагины. Поэтому Medusa особенно привлекательна для TypeScript-команд, которые хотят хранить кастомную commerce-логику рядом с платформой, но не изменять файлы ядра напрямую.
Основной базой данных является PostgreSQL. Для production-развёртывания также используется Redis в инфраструктурных задачах: событиях, кэшировании, блокировках и выполнении workflows. Конкретный состав зависит от выбранных провайдеров модулей, но production-схему не стоит проектировать как единственный процесс Node.js с локальным состоянием.
Saleor: GraphQL-платформа на Python и Django
Saleor заметно отличается от двух других участников сравнения не только языком, но и общим стилем архитектуры. Commerce-ядро написано на Python и основано на Django, а главным публичным контрактом выступает GraphQL API. Административный dashboard развёртывается как отдельный компонент и также взаимодействует с API.
Saleor хорошо соответствует проектам, где GraphQL является стандартом взаимодействия между frontend и backend. Клиент может запросить только нужные поля, использовать фрагменты и строить типизированный слой на основе схемы. Это особенно удобно для больших витрин, мобильных приложений и нескольких клиентов, которым нужны разные представления одних commerce-данных.
Каталог, типы товаров и каналы
В модели каталога важную роль играют типы товаров и атрибуты. Они позволяют описывать разные классы продукции без добавления отдельного поля в базовую модель для каждой характеристики. Товары могут иметь варианты, категории, коллекции, медиа и атрибуты. Для данных, которые не должны становиться частью стандартного каталожного интерфейса, предусмотрены metadata.
Каналы определяют контекст продажи: валюту, цены, доступность ассортимента и связанные настройки. Это делает Saleor сильным кандидатом для нескольких регионов, брендов или витрин, использующих одно commerce-ядро. Но канал не следует воспринимать как универсальную замену любой модели арендаторов. Если требуется строгая изоляция продавцов, отдельных администраторов и данных, архитектуру marketplace необходимо проектировать отдельно.
Checkout и заказы
Saleor разделяет checkout и созданный заказ. Пока покупатель выбирает адрес, доставку и способ оплаты, фронтенд работает с checkout через GraphQL mutations. После завершения процесса появляется заказ, который проходит собственный жизненный цикл. Такая модель хорошо видна в API и помогает клиентскому приложению явно управлять каждым этапом оформления.
Разработчикам важно учитывать, что headless checkout — это не одна кнопка и не единственная мутация. Фронтенд должен обрабатывать изменение цены, недоступный остаток, ошибки адреса, смену доставки, неуспешную оплату и повторное подтверждение данных. GraphQL делает контракт прозрачным, но не отменяет необходимость спроектировать конечный автомат пользовательского интерфейса.
Apps, webhooks и глубокая кастомизация
Основной путь интеграции Saleor — приложения и webhooks. Внешнее приложение может реагировать на события, участвовать в отдельных синхронных процессах, вызывать GraphQL API и добавлять элементы в dashboard. Так удобно подключать платежи, налоги, поиск, уведомления, аналитику и корпоративные системы, не помещая весь код внутрь commerce-процесса.
Преимущество подхода — изоляция интеграций. Приложения можно разрабатывать, развёртывать и масштабировать независимо от Saleor. Недостаток обнаруживается при глубоком изменении внутреннего поведения ядра. Не каждую операцию удобно выразить webhook-вызовом, особенно если она должна участвовать в транзакции или менять базовые инварианты commerce-модели. В подобных случаях может потребоваться доработка самого core, а значит, усложнится сопровождение собственного форка и установка обновлений.
Saleor использует PostgreSQL. Полная production-конфигурация также включает фоновые процессы и инфраструктуру очередей или кэша, обычно с Redis. Следовательно, это не только веб-приложение Django: при расчёте ресурсов нужно учитывать API, worker, базу данных, вспомогательные сервисы и dashboard.
Vendure: NestJS, GraphQL и плагины внутри приложения
Vendure написана на TypeScript и построена на NestJS. Для разработчиков, уже использующих dependency injection, модули, декораторы и общие шаблоны NestJS, устройство проекта выглядит предсказуемо. Commerce-приложение конфигурируется кодом, а новые функции обычно оформляются как плагины.
Платформа предоставляет два GraphQL-интерфейса. Shop API используется витриной и покупателем, Admin API — административными инструментами и интеграциями. Разделение уменьшает риск случайно открыть служебные операции публичному клиенту и позволяет проектировать разные правила доступа.
Каталог и custom fields
Каталог Vendure включает товары, варианты, опции, коллекции, фасеты, цены и остатки. Фасеты используются для классификации и фильтрации, а коллекции могут формировать структуру каталога. Каналы позволяют связывать сущности с отдельными контекстами продаж, что полезно для нескольких витрин, валют, регионов или продавцов.
Практичная особенность Vendure — custom fields. Разработчик может декларативно добавить поля к поддерживаемым сущностям и затем использовать их в GraphQL и административном интерфейсе. Для многих проектов это снижает количество шаблонного кода: дополнительные свойства заказа, товара или клиента не требуют создавать параллельную доменную модель.
Custom fields не заменяют полноценный модуль. Если новые данные имеют собственный жизненный цикл, связи, права доступа и бизнес-операции, их лучше реализовать отдельными сущностями и сервисами внутри плагина. Иначе конфигурация постепенно превращается в набор полей, смысл и ограничения которых трудно контролировать.
Заказы и настраиваемые процессы
Vendure использует конечные автоматы для управления состояниями заказов, платежей и выполнения заказов. Проект может добавлять переходы и проверки, адаптируя процесс под резервирование, ручное подтверждение, производство, получение в пункте выдачи или корпоративное согласование.
Такой механизм полезен, когда жизненный цикл заказа отличается от стандартной последовательности «корзина — оплата — отправка». При этом расширять процесс следует осторожно: frontend, административный интерфейс, платёжный обработчик и внешняя ERP должны одинаково понимать новые состояния. Само наличие настраиваемого state machine не решает проблему согласованности интеграций.
Плагины и расширение GraphQL
Плагин Vendure может регистрировать сервисы, сущности базы данных, GraphQL-схему, resolvers, фоновые задачи, обработчики событий и расширения административного интерфейса. В результате нестандартная функция оформляется как изолированный модуль NestJS, а не как набор изменений в core.
Это одна из самых сильных сторон Vendure. Команда может добавить аренду товаров, B2B-согласование, интеграцию с поставщиками или собственный расчёт доставки в рамках единой модели расширения. Платой становится более тесная связь кастомного кода с внутренними API платформы: перед обновлением необходимо проверять совместимость плагинов, миграций и расширенной GraphQL-схемы.
Для хранения данных Vendure использует слой ORM и поддерживает несколько SQL-баз. Для production чаще выбирают PostgreSQL или MySQL-совместимую систему, тогда как SQLite удобнее для локальной разработки, демонстраций и тестов с небольшой нагрузкой. Фоновые задания выполняет отдельный worker. Redis может потребоваться при выборе соответствующей стратегии очередей и масштабировании, но базовая установка не всегда делает его обязательным.
REST Medusa или GraphQL Saleor и Vendure
Тип API влияет не только на синтаксис запросов, но и на устройство frontend-проекта.
Medusa подходит командам, которым удобен REST: понятные endpoints, обычное HTTP-кэширование и сравнительно простой вызов из любого клиента. Для типовых страниц магазина этого достаточно. Если экран собирает большую связанную структуру данных, потребуется контролировать число запросов, использовать параметры выборки или подготовить собственный endpoint.
Saleor и Vendure дают GraphQL-схему. Фронтенд может генерировать типы и клиентский код, а затем получать именно те поля, которые нужны компоненту. Это уменьшает ручное описание DTO, но добавляет инструменты сборки схемы, генерацию типов, правила хранения запросов и контроль сложности операций.
У Saleor GraphQL является центральным контрактом всей платформы. У Vendure дополнительное преимущество состоит в том, что плагины могут расширять Shop API и Admin API собственными типами и resolvers. Поэтому Vendure особенно удобна, если GraphQL должен охватывать не только стандартную торговлю, но и доменные функции проекта.
Выбирать платформу только по предпочтению REST или GraphQL не стоит. Важнее проверить конкретные пользовательские сценарии: листинг с фильтрами, карточку товара, пересчёт корзины, авторизацию, checkout, личный кабинет и историю заказов. Прототип этих экранов покажет реальную сложность интеграции лучше, чем сравнение абстрактных возможностей API.
Базы данных и инфраструктурные зависимости
Medusa и Saleor ориентированы на PostgreSQL. Это упрощает выбор основной СУБД, но исключает сценарий, в котором проект хочет сохранить существующую MySQL-базу как непосредственное хранилище commerce-ядра. Vendure предлагает больше вариантов SQL-базы, хотя перенос действующего каталога всё равно потребует отдельной миграции и адаптации структуры.
Ни в одном из решений не следует предоставлять фронтенду прямой доступ к базе. Контрактом остаётся API, а изменения схемы выполняются миграциями конкретной платформы и собственных модулей. Ручное добавление таблиц допустимо только в рамках документированного механизма расширений: иначе обновление может привести к конфликтам и несогласованности моделей.
Кроме SQL-базы, production-магазину обычно нужны:
- объектное или файловое хранилище для изображений и документов;
- почтовый или иной сервис уведомлений;
- платёжный провайдер и безопасная обработка его webhooks;
- очередь фоновых задач либо worker-процессы;
- резервное копирование базы и пользовательских файлов;
- централизованные журналы, метрики и контроль ошибок;
- reverse proxy или ingress с TLS;
- поиск, если возможностей штатной выборки недостаточно для каталога.
Redis играет разную роль. В Medusa он используется production-провайдерами инфраструктурных модулей. В Saleor связан с кэшированием и выполнением фоновых задач. В Vendure необходимость Redis зависит от выбранной стратегии очередей и архитектуры масштабирования. Поэтому формулировка «платформа запускается без Redis» ещё не означает, что такая конфигурация подходит для отказоустойчивого магазина.
Резервные копии должны охватывать не только SQL-базу, но и загруженные медиафайлы, конфигурацию и данные, необходимые для восстановления интеграций. После настройки полезно проверить восстановление на изолированном стенде; практические принципы такого процесса разобраны в материале о стратегии резервного копирования 3-2-1 для баз данных.
Docker и требования к VPS
Docker не является обязательной частью commerce-логики, но значительно упрощает воспроизводимое развёртывание. В контейнеры можно разделить API, worker, dashboard, storefront, PostgreSQL, Redis и reverse proxy. Для production базу данных необязательно запускать на том же сервере: управляемая СУБД или отдельный узел обычно упрощают резервное копирование и масштабирование. Для контейнерных сервисов важно отдельно настроить healthcheck и политику перезапуска, чтобы сбой одного процесса не оставался незамеченным.
На обычном виртуальном хостинге эти платформы, как правило, развернуть нельзя. Им нужны долгоживущие процессы Node.js или Python, управление переменными окружения, миграциями, workers и сетевым доступом к базе. Практическим минимумом является VPS-сервер, контейнерная платформа или сервис, поддерживающий соответствующий runtime. Для самостоятельного VPS потребуются административный доступ и навыки сопровождения Linux или выбранной серверной ОС.
Medusa на VPS
Нужно разместить приложение Medusa, PostgreSQL и production-инфраструктуру Redis, а также определить, где будет работать storefront. Серверная и worker-роли можно запускать отдельно. Такая схема позволяет масштабировать HTTP-запросы независимо от фоновых операций. Если административный интерфейс собирается вместе с backend, необходимо учитывать память не только во время работы, но и во время установки зависимостей и сборки.
Saleor на VPS
У Saleor больше отдельных компонентов: Django API, фоновые workers, PostgreSQL, Redis и dashboard. Даже если всё запускается одним Docker Compose, в production это несколько процессов с разными профилями нагрузки. Для небольшого тестового стенда их можно собрать на одном VPS, но рабочий магазин требует особенно внимательно контролировать память, очередь задач, соединения с PostgreSQL и перезапуск workers.
Vendure на VPS
Типовая схема включает server, worker и SQL-базу. Дополнительные контейнеры появляются при подключении Redis, внешнего поиска, объектного хранилища и сервисов наблюдаемости. Начальная конфигурация может быть компактнее Saleor, однако плагины способны добавить собственные workers и зависимости. Поэтому итоговый размер инфраструктуры определяется не только ядром, но и составом проекта.
Универсального объёма CPU и RAM для всех магазинов нет. Нагрузка зависит от размера каталога, трафика, фоновых импортов, количества каналов, сложности GraphQL-запросов, кэширования и числа интеграций. Размер VPS следует определять нагрузочным тестом. Проверять нужно не только открытие карточки товара, но и массовый импорт, пересчёт цен, параллельные checkout, обработку webhook и восстановление очереди после перезапуска.

Что проще расширять
Medusa предоставляет наиболее явно разделённую модель доменных модулей и workflows. Она подходит, если новая функция должна координировать несколько commerce-доменов и выполнять последовательность шагов с контролируемым откатом. Для команды TypeScript это гибкий вариант, но архитектуру workflows придётся изучить.
Vendure предлагает привычную для NestJS разработку плагинов и удобные custom fields. Если команда хочет добавлять сущности, GraphQL-операции и административные элементы в одном пакете, Vendure даёт цельный механизм. Особенно хорошо он работает для функциональности, которую можно оформить самостоятельным модулем.
Saleor делает ставку на внешние apps и webhooks. Это полезно для распределённой системы, где платежи, налоги, поиск и корпоративные интеграции развёртываются отдельно. Но изменение фундаментального поведения core может оказаться сложнее, чем написание встроенного плагина для Medusa или Vendure.
При оценке расширяемости нужно ответить на три вопроса:
- Должно ли расширение выполняться в одной транзакции с commerce-операцией?
- Нужны ли новые сущности и поля в основном API?
- Можно ли вынести функцию во внешний сервис и согласовать данные через события?
Если важна транзакционная близость к ядру, удобнее встроенные модули и плагины. Если важнее независимое масштабирование и технологическая изоляция, внешнее приложение может быть безопаснее.
Как выбрать платформу для проекта
Когда рациональна Medusa
- backend-команда работает на TypeScript и предпочитает REST;
- commerce-логику требуется собирать из модулей и workflows;
- проекту нужны собственные API routes и тесно встроенные интеграции;
- PostgreSQL соответствует принятой инфраструктуре;
- команда готова отдельно развернуть storefront, backend, worker и инфраструктурные сервисы.
Когда рационален Saleor
- GraphQL должен быть основным контрактом для всех клиентов;
- в команде есть опыт Python, Django и эксплуатации фоновых workers;
- магазину важны каналы, структурированные атрибуты и несколько клиентских приложений;
- интеграции можно реализовать как независимые apps и webhooks;
- команда принимает более сложный набор production-компонентов.
Когда рационален Vendure
- команда использует TypeScript, NestJS и GraphQL;
- нестандартные функции удобно оформлять как плагины;
- нужно расширять сущности через custom fields без создания отдельного модуля для каждого свойства;
- требуются изменяемые процессы заказов, оплат или выполнения;
- важна возможность выбрать PostgreSQL либо MySQL-совместимую базу.
Что проверить на прототипе до окончательного решения
Сравнение документации не заменяет короткий proof of concept. Для каждой платформы стоит реализовать одинаковый вертикальный сценарий:
- Импортировать несколько товаров с вариантами, атрибутами, изображениями и остатками.
- Создать два контекста продаж с разными ценами или доступностью.
- Вывести каталог с пагинацией, фильтрами и сортировкой на выбранном frontend-стеке.
- Реализовать корзину, адрес, доставку, тестовую оплату и создание заказа.
- Добавить одно нестандартное поле и одну собственную бизнес-операцию.
- Подключить webhook или событие для передачи заказа во внешний тестовый сервис.
- Запустить API и workers в отдельных процессах, затем проверить повторную обработку после сбоя.
- Выполнить резервное копирование, миграцию и восстановление базы на чистом стенде.
Во время прототипа полезно фиксировать не только время написания кода. Следует оценить понятность ошибок API, качество типов, число запросов для основных страниц, сложность отладки фоновых задач, поведение повторных webhook и объём платформенного кода, который пришлось изучить.
Отдельно нужно проверить обновляемость. Собственное расширение должно устанавливаться поверх чистого проекта без ручного редактирования зависимостей и файлов ядра. Чем больше прямых изменений внесено в core, тем дороже будут исправления безопасности и переходы на новые релизы.
Итоговое сравнение
Medusa лучше всего соответствует TypeScript-командам, которым нужны REST API, доменные модули и управляемые workflows. Она даёт много точек расширения внутри backend и подходит для проектов с существенной собственной commerce-логикой.
Saleor выделяется GraphQL-first-подходом, Python-стеком и ориентацией на приложения и webhooks. Это сильный вариант для нескольких витрин и клиентов с единым типизированным API, если команда готова к более составной инфраструктуре и может выносить интеграции за пределы core.
Vendure сочетает TypeScript, NestJS, GraphQL и развитую плагинную модель. Она удобна, когда разработчики хотят расширять схему, сущности, административный интерфейс и процессы заказов в рамках одного приложения.
Универсального победителя нет. Для REST и модульных workflows логичным первым кандидатом будет Medusa. Для GraphQL и Python-экосистемы — Saleor. Для GraphQL, NestJS и глубокой плагинной доработки — Vendure. Окончательное решение следует принимать после реализации одного и того же checkout-сценария и production-подобного развёртывания: именно они показывают реальную стоимость разработки и сопровождения self-hosted headless commerce.


