От 2 магазинов на Ozon к 5

Архитектура мультимагазина, изоляция магазинов и почему открытие нового магазина не должно создавать вторую копию одних и тех же запасов.

Мы начинали с двух магазинов на Ozon. Сейчас мы управляем пятью. Интересной частью этого изменения было не количество, а то, сколько допущений позволяли нам сохранять два магазина.

Когда магазинов два, всю картину можно держать в одной голове. Какой листинг к какому магазину относится, какая цена принадлежит какому каналу и что произойдёт, если оба магазина попытаются продать последнюю единицу, — на всё это можно ответить по памяти. На третьем магазине это перестаёт работать, а на пятом ломается очень заметно.

Изоляция магазина — это граница, а не копия

Первая реакция при добавлении магазина — дублировать: скопировать каталог, скопировать остатки, скопировать таблицу mapping и поменять идентификатор магазина. Это выглядит быстро и создаёт вторую версию истины, которая в течение недели разойдётся с первой.

Мы заняли противоположную позицию:

Принцип
Что это значит на практике
Магазин — это идентичность, а не контейнер остатков
Магазин владеет листингами, ценами и правилами канала, но не собственным реестром запасов
Листинг — это артефакт канала
Два магазина могут продавать один и тот же физический товар под разными листингами
Идентичность товара общая
Товар описывается один раз, остальные ссылаются на это описание
Остатки наблюдаются, а не копируются
Магазин сообщает то, что видит; система фиксирует наблюдение, а не изобретает баланс

Теперь добавление магазина добавляет идентичность канала. Оно не добавляет запасы.

Почему «наблюдаемые остатки» вместо баланса по каждому магазину

Маркетплейсы сообщают данные в своём темпе и своими словами. Один канал отдаёт доступное к продаже количество уже после своих резервов. Другой — то, что ему сообщили вчера вечером. Ни одно из чисел не является ошибочным, и ни одно не является полной правдой о физическом товаре.

Поэтому мы перестали требовать от каждого канала быть источником баланса. Канал сообщает наблюдение: вот что я вижу, из этого источника, в это время. Наблюдения фиксируются, сравниваются и сверяются — они не сливаются молча в одно число, которое невозможно проверить.

Именно это проектное решение делает пять магазинов управляемыми, а не пятикратной нагрузкой на поддержку.

Что пришлось построить, чтобы это держалось

Работа пяти магазинов в одной операционной модели потребовала трёх вещей, которые не были очевидны на двух:

  • Единая идентичность товара, на которую ссылаются листинги, чтобы один и тот же товар не описывался заново в каждом канале.
  • Слой mapping между идентичностями листингов маркетплейсов и нашими SKU, потому что артикул продавца и внутренний идентификатор — не одно и то же.
  • Резолвер, который отвечает, «какие каналы могут это продавать и по какой цене», не позволяя ни одному каналу перезаписать общую запись.

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

Стоимость мультимагазина — это не пятый магазин. Это вторая копия истины, которую вы не заметили, что создали.

Что меняется по мере добавления магазинов

Когда изоляция закреплена на границе канала, добавление магазина становится операционной задачей, а не проектом по миграции данных. Следующий магазин выходит в продажу со своим набором листингов, своими правилами цен и своей отчётностью — а товары и физические остатки, на которые он ссылается, остаются там, где были.

Именно это свойство мы и покупали, когда строили модель. Не больше магазинов. Меньше неожиданностей на каждый магазин.

WEOUR / BUILD

Примите участие в сборке

Если вы решаете реальные задачи в трансграничной торговле, запасах, складе, фулфилменте или автоматизации — расскажите нам о своей задаче.

Оставить запрос Следите за WEOUR / сообщество — позже