15708
Присоединяйтесь к нашему каналу и погрузитесь в мир Backend-разработки Связь: @devmangx РКН: https://clck.ru/3FobxK
Нашел эту статью о транзакциях в базах данных и реализации ACID в реляционных базах данных действительно интересной, рекомендую прочитать.
https://www.datacamp.com/blog/acid-transactions
👉 @BackendPortal
Ваша база PostgreSQL уперлась в потолок.
Текущие метрики:
- База 2 ТБ на db.r5.4xlarge
- 85% read, 15% write
- Лаг read-replica: в среднем 200 мс, пики до 2 секунд
- Количество подключений в пик упирается в максимум (500)
- Самые медленные запросы: сложные JOIN’ы по 4 таблицам с 100M+ строк
- VACUUM не успевает, растет число мертвых кортежей (dead tuples)
- Хранилище растет на 50 ГБ/месяц
Команда спорит, что делать:
- Добавить PgBouncer для пуллинга соединений
- Внедрить read-replica + роутинг запросов
- Шардировать базу
- Вынести горячие таблицы в DynamoDB
- Залить деньгами (апгрейд до db.r5.12xlarge)
В этом квартале можно выбрать только 2.
Какие 2 и в каком порядке?
👉 @BackendPortal
Что такое LGTM?
L – Loki
структурированные, поисковые, коррелируемые логи.
G – Grafana
визуализация всего, что происходит в системе.
T – Tempo
распределенный трейсинг между сервисами.
M – Mimir
истина про поведение системы в виде таймсерий.
Вместе они отвечают на три ключевых вопроса:
что произошло? → логи
насколько все плохо? → метрики
где конкретно тормозит? → трейсы
Без LGTM дебаг распределенных систем это гадание на кофейной гуще. ❤️
Плейлист-курс по LGTM (Loki + Grafana + Tempo + Mimir)
👉 @BackendPortal
Идём играть в Go-лото 10 марта ☄️
Коллеги из Авито придумали уникальный формат нетворкинга с элементами азарта и, конечно, Go! Вас ждут живая игра в русское лото, адаптированная для Go- и бэкенд-разработчиков, обсуждение реальных кейсов с коллегами и розыгрыш лимитированных призов от AvitoTech.
Приходите 10 марта поиграть и поделиться болями — регистрация по ссылке. Количество мест ограничено!
Сколько бы блогов, книг или статей ты ни прочитал, прототипирование все равно остается самым быстрым способом что-то понять. Вот мой воркфлоу:
- держу GitHub-репозиторий с названием prototypes
- каждая папка это один эксперимент
- если что-то кажется интересным, иду и реализую
- четко формулирую, что именно хочу понять
- нахожу абсолютный минимум того, что нужно
- пишу код, запускаю, итерируюсь
Ключевой момент тут это найти минимально необходимое, самый-самый минимум кода, который поможет тебе собрать нужное понимание. Сначала ты почти всегда будешь писать больше, чем нужно, но со временем начнешь подставлять данные, добавлять sleep, мокать и делать правильные допущения.
И да, я понимаю, есть соблазн заопенсорсить прототип или превратить его в проект или стартап. Не надо. Помни, цель тут понять. Как только понял, все, закончил, двигаешься дальше.
Вчера, например, я собрал и реализовал разные типы join-ов и прогнал бенчмарки, чтобы посмотреть, как они реально себя ведут по производительности. Теорию я и так знал, но прототип дал мне реальные, пусть и грубые, цифры.
👉 @BackendPortal
Ускорь JSON-ответы FastAPI в 2 раза, а то и больше
1. Обновись до вышедшего FastAPI 0.131.0
2. Объявляй response model (тип возврата)
После этого @pydantic будет заниматься JSON-сериализацией на стороне Rust 🦀
https://fastapi.tiangolo.com/advanced/custom-response/#json-performance
👉 @BackendPortal
У тебя SaaS, где есть фича: загрузить и обработать большой файл.
Без брокера:
1. Юзер жмёт Upload → POST /upload
2. Сервер принимает файл и тут же начинает обработку (2 минуты)
3. И только потом отвечает
Если так делают многие, сервер забивается обработкой и перестаёт нормально обслуживать остальные запросы. Логин тормозит. Дашборд грузится долго. Всё начинает ехать.
С брокером (например RabbitMQ):
1. Юзер жмёт Upload
2. Сервер принимает файл и кладёт его в storage
3. Отправляет в RabbitMQ сообщение: “обработать файл ID 1”
(этот сервер здесь Producer)
4. RabbitMQ кладёт сообщение в queue (очередь задач)
5. Сервер отвечает почти сразу
6. RabbitMQ отдаёт это сообщение другому процессу, который забирает файл из storage и обрабатывает (Consumer)
Пайплайн:
Users → Producer → Broker → Consumer
RabbitMQ сам файл не обрабатывает. Он просто хранит задачу и выдаёт её воркеру, когда приходит очередь.
Что ты выигрываешь?
Быстрый ответ на запрос, сервер свободен для других действий (логин, загрузка дашборда), обработку можно масштабировать отдельно, и если что-то упало, задачу можно ретраить.
Но: теперь поток асинхронный, значит нужно делать обработку идемпотентной и нормально продумать ретраи.
Брокер не упрощает систему. Он делает её устойчивее, когда проект начинает расти.
👉 @BackendPortal
На Stepik добавили курс «Linux с нуля»
Этот курс закрывает всю обязательную Linux-базу для работы в IT. Подойдёт для:
- разработчиков
- девопсов и админов
- специалистов по данным и ML
- специалистов поддержки и сопровождения
- тестировщиков и безопасников
23LINUX30»: открыть курс на Stepik
Читать полностью…
Проектируем полезные логи для бэкендеров
Большинство девов логируют реактивно: добавили console.log, когда что-то сломалось, починили и пошли дальше. В итоге получаются в основном шумные логи, которые вообще ничего не говорят, когда прод полыхает.
1. Начинай со структурированного логирования: вместо обычного текста пиши JSON с едиными, предсказуемыми полями, по которым можно нормально искать.
Тогда твой мониторинг сможет алертить, фильтровать и строить графики, а логи можно будет “запрашивать” почти как базу данных.
2. Используй уровни логов по делу.
• INFO = ожидаемые бизнес-события (например, пользователь залогинился)
• WARN = обработанные аномалии (например, ретраим упавший вызов)
• ERROR = реальные фейлы, которые требуют внимания
• DEBUG = детали для разработки, в проде выключать
Большинство команд ставят ERROR вообще на все. Не надо так.
3. Всегда держи “чеклист контекста”:
Само сообщение лога почти бесполезно. Ценность дают контекстные поля, которые к нему приклеены, и именно они делают лог пригодным для действий.
• Идентификаторы: user_id, order_id, request_id
• Значения: amount, count, size
• Состояние: status, current_step
• Детали ошибки: error_code, exception
• Время: duration_ms
Идентификаторы отвечают на “кто и что”, значения на “сколько”, состояние на “где мы в процессе”, детали ошибки на “что пошло не так”, а время на “как долго это длилось”.
4. Используй correlation ID:
Генерируй уникальный request_id на каждом входе в систему. Протаскивай его через каждую функцию, сервис и лог.
Без этого дебажить параллельные запросы становится проблемнее.
5. Никогда не логируй чувствительные данные:
Не логируй пароли, токены, номера карт, сырой SQL с пользовательскими значениями, данные, возвращаемые запросами, и т.п.
Цель такая: любой инженер во время инцидента должен открыть логи и сразу понять, что произошло, даже не лазя в исходники.
👉 @BackendPortal
Ты знал, что у Postgres есть ДВА in-memory кэша?
Каждый раз, когда Postgres читает строку, по факту данные приходят из одного из трех мест:
1. shared_buffers (кэш, которым управляет сам Postgres). Это самый “ближний” к Postgres слой с страницами данных, обычно самый быстрый.
2. OS page cache (кэш страниц ОС). Операционка использует свободную память как кэш недавно прочитанных страниц файловой системы. Чтение в Pg может промахнуться мимо shared_buffers, но нужная страница при этом уже лежит в кэше ОС. Это тоже очень быстро: остается только скопировать страницу в shared_buffers.
3. Файловая система / железо. Если данных нет ни в одном из кэшей, файловая система идет за ними на диск (это заметно медленнее).
Данные могут дублироваться в обоих кэшах одновременно! На мой взгляд, единый “общий” кэш мог бы быть приятным улучшением для Pg в будущем, хотя это огромная работа по реализации.
👉 @BackendPortal
Топ-5 юзкейсов Redis:
Два разработчика, Сара и Майк, решили собрать приложение доставки еды. Началось как проект на выходных, а к третьему месяцу у них уже реальные пользователи, реальный трафик и реальные проблемы. Вот как Redis спасает их на каждом этапе.
1. Redis как кэш
База начинает тормозить. Сара замечает: меню почти не меняются, но их дергают тысячи раз в день. Она ставит Redis перед базой: один раз достали меню, закэшировали на 10 минут.
2. Redis как хранилище сессий
Майк поднимает еще один сервер под пики вроде обеденного наплыва, и пользователи начинают жаловаться, что их рандомно выкидывает из аккаунта.
Причина простая: сессия сохранилась на Сервере 1, а следующий запрос улетел на Сервер 2.
Майк просто переносит все пользовательские сессии в Redis. Теперь не важно, какой сервер поймал запрос: юзеры остаются залогиненными.
3. Redis как rate limiter
Сара и Майк запускают акцию "50% на первый заказ"… И уже через час один тип оформил 47 заказов с 47 фейковых аккаунтов с одного IP.
Майк добавляет rate limiter на Redis: простой счетчик на IP, который сбрасывается каждый час. Абуз прекращается, а тип идет жить дальше.
4. Redis как Pub/Sub и очереди
Пользователи постоянно пишут: "мой заказ точно подтвержден?" Сара хочет отправлять письмо-подтверждение сразу после оформления заказа, но если делать это внутри запроса, чек-аут становится медленным.
Она пушит события о заказах в Redis-очередь, а фоновый воркер забирает их и шлет письма асинхронно. Теперь оформление выглядит мгновенным, и никто больше не дергает саппорт.
5. Redis как распределенные локи
У пользователя плохая сеть, он нажимает "Оформить заказ" два раза подряд. Оба запроса одновременно прилетают на сервер. Карта списывает два раза, оформляется два заказа, и в итоге прилетает злой отзыв.
Майк делает distributed lock на Redis: первый запрос забирает лок, второй видит, что лок занят, и получает отказ. Теперь списание одно, заказ один, и возможно даже будет отзыв на пять звезд.
Redis умеет гораздо больше. Но даже этих примеров хватает, чтобы понять: это инструмент, к которому можно тянуться каждый раз, когда что-то начинает ломаться под нагрузкой.
👉 @BackendPortal
О чем на самом деле Agent Skills?
Как они работают?
👉 @BackendPortal
🔥 Пожизненная PRO-подписка на easyoffer по цене одного года.
Беспрецедентная акция на PRO-тариф сайта для подготовки к собеседованию на программиста, тестировщика, проектного менеджера и другие IT-профессии.
⚙️ Доступные функции сейчас:
1. База вопросов из реальных технических собеседований с вероятностью встречи и примерами ответов.
2. База задач с этапа live-coding.
3. База 1100+ реальных собеседований, в том числе в топовые компании (Сбер, Авито, Яндекс, WB, OZON, МТС и др.) на позиции Junior/Middle/Senior.
4. База 400+ тестовых заданий от компаний.
5. Аналитика ТОП-требований из вакансий для лучшего написания резюме по ключевым словам.
6. Тренажеры для подготовки к собеседованию. В том числе тренажер «Реальное собеседование» со сценарием вопросов под конкретную компанию.
⌛️ Функции, которые появятся в ближайшие полгода:
1. Агрегатор вакансий из Telegram, сайтов компаний и джоббордов.
2. Улучшение и оптимизация резюме, чтобы проходить ATS-системы.
3. Генерация уникального резюме и сопроводительного письма под вакансию.
Акция до 20 февраля (включительно) на PRO-тариф. Покупаешь сейчас один раз — пользуешься всю жизнь без лимита, включая все будущие функции.
👉 Смотри подробности тарифа и покупай на easyoffer
Умоляю: не юзайте CTE
CTE это не медалька и не повод гордиться.
Не пишите их просто потому, что это выглядит “продвинуто”.
Иногда чистый прямой запрос лучше, чем “навороченный”.
Если ваш CTE не:
❌улучшает читаемость
❌помогает разложить сложность
❌отделяет логические шаги
то это просто вертикальный скролл без смысла. Пишите обычный запрос. Прятать логику за лишней сложностью это не гениальность, это балласт.
CTE это просто инструмент. И как любой инструмент, не надо им злоупотреблять💚
👉 @BackendPortal
В этом видео разбирают асинхронное чтение (read IO) в Postgres 18.
0:00 Вступление
1:30 Синхронные и асинхронные вызовы
3:00 Синхронный IO
6:30 Асинхронный IO
10:00 Синхронный IO в Postgres 17
17:20 Почему Async IO в Postgres 18 это непросто
20:00 io_method: worker
23:00 io_method: io_uring
29:30 io_method: sync
31:08 Async IO еще не готов!
31:30 Поддержка backend writers
32:36 Улучшения worker io_method
33:00 Поддержка direct IO
👉 @BackendPortal
Weekend Offer Multitrack: быстрый найм для опытных специалистов
Приглашаем бэкенд-разработчиков с опытом от 5 лет на C++, Python, Go или Java/Kotlin получить офер за 2 дня и поработать в трёх командах Яндекса на выбор.
Приходите, если вам важно видеть результат своей работы в живых системах и метриках, а не только в merged PR.
Как всё проходит:
🟢 До 6 марта — регистрация на сайте.
🟢 14 марта — технические секции.
🟢 15 марта — финальная секция и офер.
После получения офера у вас будет возможность выбрать три команды и в течение нескольких недель поочерёдно поработать в каждой. Такой формат позволит не только познакомиться с коллегами и технологическим стеком, но и оценить задачи и рабочие процессы в каждой команде.
Подробности и форма регистрации — по ссылке.
🏙️ Бэкэнд масштаба города — на Day&Night 2026*
Городские сервисы Яндекса — это миллионные нагрузки, сложная архитектура и код, который ежесекундно работает в реальном мире.
Day&Night* — флагманская конференция Городских сервисов. Программу формируют Илья Царев из Яндекс Go, Стёпа Мороз из Яндекс Доставки , Женя Косенко из Техплатформы и другие лидеры индустрии.
Доклады про:
🔶 Архитектуру и высокие нагрузки
🔶 Единую платформу
🔶 ИИ и будущее индустрии
После докладов будут тематические клубы по интересам, где можно будет обсудить всё и пообщаться с докладчиками на самые разные темы.
🍸 Финал вечера — масштабный нетворкинг и активности до 2 ночи. В программе: диджеи, коктейли и та самая атмосфера, ради которой хочется остаться до конца.
🚀 Регистрация открыта — успейте подать заявку!
Все заявки проходят модерацию, обязательно дождитесь обратной связи.
*День и Ночь 2026
Если ты учишь backend в 2026, прокачай вот эти 8 тем:
1️⃣Дизайн REST API
↓
2️⃣Аутентификация (JWT / OAuth)
↓
3️⃣Индексы в базе данных
↓
4️⃣Кэширование (Redis)
↓
5️⃣Rate limiting
↓
6️⃣Логирование и мониторинг
↓
7️⃣База по Docker
↓
8️⃣Основы system design
👉 @BackendPortal
Большинство думают, что каждый .sort() работает одинаково во всех языках.
Это не так.
Разные языки, разные алгоритмы:
> C++ → Introsort
> std::sort() = Quicksort + Heapsort + Insertion
> Python → Timsort
> list.sort() = Stable (стабильная сортировка)
> Java → Зависит от типа
> Arrays.sort(Object[]) = Timsort (стабильная)
> Arrays.sort(int[]) = Dual-Pivot Quicksort
> JavaScript → Зависит от движка
> Chrome V8 = гибрид в стиле Timsort
> Firefox = гибрид Merge Sort
> C → Нет фиксированной гарантии
> qsort() обычно Quicksort
> Go → PDQSort + Insertion
> Rust → Выбираешь сам
> .sort() = стабильная Merge Sort
> .sort_unstable() = PDQSort
> Swift → Интроспективный гибрид
> Ближе к PDQSort + Insertion
Один и тот же .sort(), но в каждом языке за ним могут стоять разные алгоритмы.
👉 @BackendPortal
Нужно быстро поднять PostgreSQL для MVP или pet-проекта?
В MWS Cloud Platform база данных PostgreSQL разворачивается за минуты и сразу готова к работе:
⏺️готовые конфигурации CPU и RAM под разные типы нагрузок
⏺️high availability или standalone конфигурации, автоматические бэкапы
⏺️гарантированные мощности CPU, консистентный API и удобный cloud-native IAM
⏺️сетевые или сверхбыстрые NVMe-диски под разные сценарии
⏺️постоянный primary endpoint: адрес не меняется при failover или switchover
⏺️до 3 read-only точек подключения — удобно для подключения аналитики
⏺️поддержка популярных расширений PostgreSQL "из коробки"
Представь, что ты делаешь новостной агрегатор (типа Google News). Одна из самых больших проблем, с которой ты столкнешься, это дедупликация статей среди миллионов документов. Наивные сравнения O(n^2) тебя просто раздавят на масштабе. А реальное решение это MinHash + LSH.
MinHash превращает большое множество в маленькую, фиксированного размера сигнатуру так, что похожесть двух сигнатур приближенно соответствует жаккаровскому сходству (Jaccard similarity) исходных множеств. Jaccard similarity это просто пересечение множеств, деленное на их объединение; мера того, насколько сильно множества перекрываются.
Это быстрый вероятностный способ оценить “насколько эти два документа похожи”, не сравнивая их слово в слово.
Первый шаг это шинглинг: ты разбиваешь каждый документ на перекрывающиеся n-граммы (например, последовательности из 3 слов), а потом запускаешь MinHash на множестве этих шинглов. На выходе MinHash дает компактную сигнатуру, обычно 100-200 хеш-значений.
Ключевое свойство такое: вероятность того, что две сигнатуры разделят одно и то же минимальное хеш-значение, равна Jaccard similarity их исходных множеств шинглов. Так ты оцениваешь сходство, вообще не трогая сырой текст.
Но проблема сравнения все равно остается. Даже с компактными сигнатурами сравнивать каждую пару дорого. Тут и появляется LSH
Ты делишь каждую сигнатуру на b полос по r строк в каждой, и хешируешь каждую полосу в бакет. Два документа, которые достаточно похожи, с высокой вероятностью попадут в один и тот же бакет хотя бы в одной полосе, и уже только эти кандидатные пары ты реально сравниваешь.
Такой подход схлопывает миллиарды сравнений до миллионов, и именно так системы вроде Google News и ранние веб-краулеры дедупили контент на больших объемах. В нескольких гугловых статьях и инженерных блогах начала 2000-х прямо упоминается этот подход. Довольно просто и аккуратно.
И как почти всегда на масштабе: тебе не нужна идеальная система детекта похожести. Нужна быстрая и достаточно хорошая, потому что стоимость в итоге и диктует правила игры.
👉 @BackendPortal
JWT за 60 секунд
Что такое JWT?
JWT = JSON Web Token
Компактный, URL-safe токен, который используют для:
- аутентификации
- авторизации
- безопасного общения между API
- шаринга идентичности между сервисами
Он цифрово подписан, поэтому его можно проверять и ему можно доверять.
🟢Зачем вообще нужен JWT
Типичный флоу без JWT:
Пользователь → Приложение → База данных (хранилище сессий)
-сервер хранит сессии
-нужна память/хранилище
-сложно масштабировать в микросервисах
-больше инфраструктурной сложности
-за балансировщиком нужны sticky sessions
-в распределенных системах это плохо масштабируется
🟢Тут и появляется JWT
- JWT это stateless-аутентификация.
Новый флоу:
Пользователь → Приложение → JWT → Клиент → API
-на сервере не хранится сессия
-токен несет идентичность пользователя и claims
-сервер только проверяет подпись
-отлично подходит для масштабируемых систем
🟢Полный флоу JWT-запроса
1️⃣пользователь логинится с кредами
2️⃣сервер валидирует пользователя
3️⃣сервер генерирует JWT (Header + Payload + Signature)
4️⃣клиент сохраняет JWT (обычно в браузере/приложении)
5️⃣клиент шлет JWT в заголовке Authorization
6️⃣сервер проверяет подпись
7️⃣если валидно → доступ выдан
Никакой поход в базу за сессией не нужен.
🟢Где JWT используют в реальных системах?
-REST API
-аутентификация микросервисов
-OAuth2 / SSO
-API Gateway
-Kubernetes dashboards
-CI/CD инструменты
-мобильные приложения и SPA
-почти каждый современный cloud-native апп использует JWT
🟢JWT в DevOps и System Design
DevOps-инженеру JWT нужен для:
-проектирования stateless-приложений
-масштабирования за Load Balancer’ами
-внедрения API security
-работы с IAM и OAuth-провайдерами
-защиты коммуникации микросервисов
-уменьшения зависимости от session storage
Stateless auth = лучше масштабируемость + проще инфраструктура
Спасибо, что дочитал.
👉 @BackendPortal
Зачем нужен CORS на localhost?
👉 @BackendPortal
Vercel выкатили реально полезную штуку для локальной разработки
Называется Portless. Вместо того чтобы жить на захламленных портах типа localhost:3000, можно использовать нормальные именованные адреса вроде app.localhost или api.localhost.
Под капотом это локальный прокси, который мапит эти понятные домены на нужные порты на твоей машине.
Почему это удобно:
▪️не надо помнить случайные номера портов
▪️локальные URL читаемые, по-человечески
▪️имена стабильные, даже если порты поменялись
▪️больше похоже на прод, где все часто разнесено по сабдоменам
▪️удобнее для автоматизации и AI-агентов, меньше сюрпризов
Важно упомянуть, оно не выставляет твое приложение в интернет. Просто делает локальную разработку аккуратнее и организованнее :))
Ссылка на репо: http://github.com/vercel-labs/portless
👉 @BackendPortal
"Два struct-а с одинаковыми полями могут иметь разный размер, поэтому переставляй поля в struct-е, чтобы оптимизировать память".
Как разобраться в новой версии Go 1.26 за 20 минут?
Шарящие уже поняли: посмотреть новый обзор от Паши Агалецкого, техлида и бэкенд-разработчика Авито.
📌 Слушаем или смотрим по ссылке, чтобы сразу с порога узнать про самые интересные функции: от нового метода для работы с ошибками до возможности отправлять логи сразу в несколько обработчиков.
📺 YouTube
💻 Rutube
🔵 VK Видео
Топовый ресурс, чтобы учить алгоритмы программирования. Пошаговые визуальные объяснения и примеры кода.
На испанском и с графиками сложности.
40 алгоритмов, концептов и структур данных:
→ http://alg0.dev
👉 @BackendPortal
React Doctor уже тут
Сканируй свой React-код на анти-паттерны:
▪️лишние useEffect-ы
▪️исправляет проблемы с доступностью (a11y)
▪️prop drilling вместо context / композиции
Запускается как CLI или как агент skill. Гоняешь снова и снова, пока всё не проходит. Полностью open source.
Запусти это в терминале, чтобы попробовать:
npx -y react-doctor@latest
Никогда не запускай запросы без таймаута.
Без него один “вредный” запрос или всплеск нагрузки легко приводит к затыкам и даже к даунтайму приложения. Давай разберем, почему.
Представь ситуацию: в приложение случайно попадает долгий запрос. Обычно база обрабатывает только короткоживущие запросы (10 мс или меньше), а тут внезапно появляется новый, который выполняется по 1000 мс каждый раз.
Он не только будет жрать ресурсы, но и резко увеличит число одновременных транзакций. В итоге мы упремся либо в лимит соединений, либо в лимиты по транзакциям, либо просто выжмем 100% CPU / IOPS у базы.
Теперь та же ситуация, но мы ставим таймаут 250 мс на каждую транзакцию (на стороне базы), а на стороне приложения делаем ретраи с экспоненциальным backoff + jitter. Так мы ограничиваем радиус поражения от одного запроса. Долгие запросы будут прибиваться, а backoff-логика снижает риск эффекта “стада” (thundering herd).
И если мониторить эти таймауты, можно быстро найти проблемный запрос и откатить изменение.
👉 @BackendPortal
Как разработчик решил параллельно найму пилить свои бизнес-проекты с нулевым опытом: дневник с передовой
Меня зовут Александр Торбек, И я попал в день сурка: код писать умею, зарплата стабильная. Но в заднице зудит ощущение катастрофического застоя.
Поэтому я сделал глупейшую вещь — начал разрабатывать продукты. Без связей, плана и стратегии. В блоге буду фиксировать:
— идеи (и почему 90% из них — говно собаки)
— что сделал, сколько заработал
— мысли айтишника, который впервые думает как продакт, а не как тупой исполнитель
Я хочу пройти весь путь от основателя продукта до продажника. И выяснить, смогу ли без бизнес-бэкграунда выйти на уровень дядек в элитных пиджаках.
Если тоже хотите создавать свои продукты — посмотрите, как я набиваю шишки первым: @atorbek_it