Это статья о том, почему написать SaaS оказалось проще, чем превратить его в продукт.
После университета я начала искать первую работу разработчиком. Вакансии для начинающих почему‑то не выглядели вакансиями для начинающих. Я читала требования, понимала, что многого не умею, нервничала всё сильнее, а потом решила сделать собственный проект — конструктор магазинов.
Уже звучит как начало чего‑то плохого.
Идея была такой: владелец отправляет токен своего Telegram‑бота, мой сервис подключает к нему команды и витрину. Покупатели открывают его бот‑магазин внутри Telegram, собирают корзину, оформляют заказ. Владелец управляет всем через отдельный Mini App.
Архитектура первого MVP
Сервис состоит из двух частей. Владелец управляет магазином через админ‑бот и Mini App, покупатели открывают витрину через бота магазина.
Admin bot -----\ Store bots -----+--> FastAPI --> PostgreSQL Mini App -------/ | +--> Outbox --> Workers --> Telegram API
У каждого магазина свой tenant_id — через него бэкенд понимает, какие товары, настройки и заказы принадлежат конкретному владельцу.
За полгода я собрала работающий MVP. Ещё через полгода у меня появились реальные пользователи — незнакомые люди, которые запускали своих ботов, наполняли магазины и находили сценарии, о которых я даже не думала. Выручка при этом была нулевой.

Один из первых написал мне с вопросом: как добавлять товары?
Технически всё работало. Пользователь был в нужном магазине, разделы открывались, данные сохранялись. Просто после подключения он оказывался в пустой панели управления — без подсказок и объяснений, что делать дальше.
Я смотрела на этот экран и не сразу понимала в чём проблема. Мне последовательность казалась очевидной: название магазина, доставка, категория, первый товар, открыть витрину. А новый человек видел несколько пустых разделов и должен был сам догадаться, в каком порядке их заполнять.
До этого момента я почти не думала об онбординге. Казалось, это украшение, которым можно заняться после основных функций. После первого пользователя стало понятно: если человек не может начать работу, основной сценарий тоже нельзя считать готовым.
Так появился пошаговый онбординг. Вместо пустого дашборда сервис начал проводить владельца через настройку: название, тип бизнеса, оформление, доставка, первая категория, первый товар, проверка витрины.
Онбординг оказался не одним экраном с инструкцией, а ещё одним состоянием всего продукта.
После этого пользователи нашли мелочи: отсутствие ограничений длины, непонятные допустимые значения, ошибочное определение валюты. По отдельности ерунда, но вместе они решали — сможет ли человек закончить настройку без моей помощи.
Десять попыток сменить бота
Однажды мне написала девушка: хотела отвязать текущий магазин и подключить новый бот, но после подключения система всё равно открывала старый.
По логам она пробовала это около десяти раз.
Кнопка отвязки у меня была. Повторное подключение токена тоже работало. Просто между двумя этими действиями существовала огромная дыра, о которой я не думала. Что должно происходить с магазином после отключения бота?
Если человек через минуту подключил того же бота — он ожидает увидеть свои товары. Если бот другой — что тогда? Переносить старый каталог? Создавать пустой? Что делать с заказами которые уже забрал фоновый воркер?
Оказалось, сначала нужно было решить не техническую, а продуктовую задачу: магазин принадлежит аккаунту владельца или конкретному Telegram‑боту?
В итоге я разделила несколько сценариев:
Событие |
Что происходит |
|---|---|
Повторно подключён тот же |
Витрина, товары и настройки сохраняются |
Токен перевыпущен, но |
Считается тем же ботом |
Подключён другой |
Аккаунт владельца и настройки сохраняются, но каталог и заказы начинаются заново |
Старый бот отключён |
Webhook старого бота удаляется, фоновые задачи больше не отправляют через него сообщения |
Определять «того же бота» только по токену нельзя — токен можно перевыпустить через BotFather, хотя сам бот останется прежним. Поэтому я сравниваю bot_id полученный через Telegram API.
Если bot_id совпадает, я просто обновляю токен и возвращаю владельцу тот же магазин. Если bot_id другой, я оставляю tenant владельца и настройки аккаунта, но очищаю витрину: товары, категории, заказы и отложенные уведомления, которые относились к старому магазину.
На исправление кода ушло минут двадцать. Девушка не дождалась — каким‑то образом добилась нужного результата сама и больше не написала.
Магазин одежды сломал мою модель товара
Однажды в логах я увидела, что кто‑то начал заполнять магазин одеждой. Появилась категория, фотографии, первые товары. Я просто наблюдала, а потом до меня дошло: этот человек скоро дойдёт до размеров или цветов. А добавить их у меня невозможно.
Просто добавить поле «размер» было недостаточно. Каждая комбинация значений фактически становилась отдельным вариантом товара.
Например:
Цвета: чёрный, белый
Размеры: S, M, L, XL
Товар ├── Цвет │ ├── Чёрный │ └── Белый └── Размер ├── S ├── M ├── L └── XL
Результат: 8 вариантов

Я разделила товар, его опции, значения опций и товарные варианты. При изменении опций система строит новый набор комбинаций и сравнивает его с уже сохранёнными вариантами. Совпавшие сохраняют цену, остаток и фотографию, недостающие создаются, а устаревшие удаляются. Бэкенд дополнительно проверяет целостность полученного набора.
Просто пересоздать все комбинации было нельзя — пользователь потерял бы данные, которые вносил вручную.
Работала над задачей несколько дней, много времени ушло на моё понимание задачи.
До реального магазина одежды эта функция не казалась мне обязательной. После стало ясно, что исходная модель товара подходила только для сценариев, которые я сама представляла при разработке.
Почему за год я не заработала ничего
Часто моей целью было не заработать деньги, а закрыть очередную задачу в блокноте.
Добавить поле, поправить отступы, переделать экран, продумать ещё один сценарий — это давало понятное ощущение прогресса. Задачу можно выполнить, отметить галочкой и перейти к следующей.
При этом я почти не знала как продвигать продукт. Я понимала, что мне нужны не просто пользователи Telegram, а люди, у которых уже есть бизнес, и которые продают онлайн. Случайным массовым трафиком такую аудиторию не приведёшь.
Суммарные результаты нескольких небольших рекламных запусков за всё время:
около 500 переходов в бот
30 созданных магазинов
12 добавили хотя бы один товар
4 добавили больше 10 товаров
3 получили заказы
0 оплаченных подписок
Проблема была не только в объявлении. Площадка показывала его людям, которые интересовались Telegram‑ботами — но не обязательно продавали товары. Я искала технически релевантный трафик, хотя мне нужен был продуктово релевантный.
Только сейчас я начинаю понимать, что анализ рынка нужен не после разработки, а до неё. Недостаточно знать, что похожие сервисы существуют. Нужно понимать, кто ими пользуется, где они находят клиентов, и за что люди готовы платить.
Я долго относилась к маркетингу как к последнему этапу: сначала закончить продукт, потом продавать. Но продукт невозможно закончить без рынка — именно рынок показывает, что нужно делать. Это, наверное, и есть основная причина нулевой выручки.
Был ли этот год потрачен зря
Нет. Создавать что‑то своими руками оказалось очень интересно.
В начале почти всё казалось тёмным лесом. Сейчас у меня есть работающий проект, реальные пользователи и опыт которого не было после университета. Я умею не только написать отдельную функцию, но и проследить весь путь: от действия пользователя до записи в базе и фоновой задачи.
Главное, что я поняла за этот год: сложный продукт состоит из множества отдельных, вполне решаемых проблем. Когда смотришь на всю систему целиком, она кажется огромной. Когда находишь конкретную следующую проблему, её уже можно разобрать и решить.
Следующая задача в моём блокноте — это не новая функция.