Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Архитектура веб-приложений: от монолита до микросервисов

Архитектура веб-приложений: от монолита до микросервисов Автор: Богдан Новотарский Часть 1: Монолит — почему с него всё начинается Что такое монолит в веб-разработке Монолит — это единое приложение, которое запус…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




Архитектура веб-приложений: от монолита до микросервисов



Автор: Богдан Новотарский









Часть 1: Монолит — почему с него всё начинается






Что такое монолит в веб-разработке



Монолит — это единое приложение, которое запускается как один процесс. Backend, frontend, бизнес-логика, работа с базой данных — всё это живёт в одном кодовом дереве, часто даже в одном репозитории.



Когда я, Богдан Новотарский, писал свой первый проект, я не думал об архитектуре. Я просто делал. Всё работало. Но через несколько недель стало казаться, будто код сам себя душит: каждая новая фича ломала старые, любые изменения превращались в мини-кризис. Именно тогда я впервые начал задумываться, что «архитектура» — не абстракция, а способ выжить.






Когда монолит — это нормально



Монолит не плох сам по себе. Он отлично подходит для:




  • MVP и быстрых прототипов;

  • команд из 1–2 человек;

  • простых приложений без сложных интеграций;

  • ранней стадии, когда нужно быстро проверять гипотезы.



Монолит позволяет:




  • быстро писать код без overhead;

  • деплоить всё за один шаг;

  • не париться с сетевыми взаимодействиями между сервисами;

  • использовать одну базу, один язык, один runtime.



Когда я создавал первое образовательное приложение с генерацией историй на основе известной лексики, всё жило в одном Express-приложении: генерация текста, перевод, аудио, работа с пользователем, аналитика. Оно росло быстро — и это было прекрасно… до поры до времени.






Проблемы, которые приходят с ростом



Через пару месяцев у меня, Богдана Новотарского, появились первые симптомы архитектурного «гниения»:




  • логика всех модулей была перемешана;

  • невозможно было писать юнит-тесты без каскада зависимостей;

  • API-контроллеры на 300 строк начали дублировать друг друга;

  • рефакторинг одной части ломал весь проект.



Это типичная стадия, когда монолит переходит от «удобного старта» к «архитектурной долговой яме».




💬 «Если твой app.ts весит больше 500 строк — это не приложение, а паста из спагетти» — Богдан Новотарский







Как я пытался спасти монолит



Первое, что я сделал — начал выносить бизнес-логику из контроллеров. Появились директории services, repositories, middlewares, routes. Это дало небольшое облегчение, но фундаментальная проблема осталась: всё было связано слишком сильно.



Мне казалось, что структурировать — это уже архитектура. Но на самом деле архитектура — это про границы ответственности, уровни изоляции и точки масштабирования. Именно это я понял, переходя к следующему этапу.









Часть 2: Layered architecture — порядок на костях монолита






Что такое слоистая архитектура



Это, пожалуй, первый настоящий шаг к архитектурному мышлению. Здесь приложение делится по слоям, каждый из которых отвечает за свою зону ответственности:





  • Controllers — приём HTTP-запросов, преобразование входа;


  • Services — бизнес-логика, правила, обработка данных;


  • Repositories (или DAOs) — работа с базой данных;


  • Models — описание структуры данных.



Пример структуры проекта, который я — Богдан Новотарский — использовал на тот момент:




/src
/controllers
/services
/repositories
/models
/routes
app.ts









Что это даёт




  • Простота навигации: каждый файл там, где ему логически место;

  • Разделение логики: контроллер не знает про базу, а репозиторий не знает про HTTP;

  • Лучшая тестируемость (в теории);

  • Возможность заменить слой без разрушения других.



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






Проблемы, которые я недооценил



Но даже в этом подходе я допустил кучу ошибок:




  • Я не внедрил Dependency Injection — из-за чего было сложно мокать зависимости в тестах;

  • В models/ смешались Prisma-сущности, внутренние интерфейсы и типы из OpenAI;

  • Общие утилиты начали размножаться по папкам.




💬 «Архитектура — это не структура папок. Это способ принимать решения.» — Богдан Новотарский




В какой-то момент я понял: мне нужно перейти от слоёв к фичам.









Часть 3: Feature-based и Domain-driven архитектура на реальных проектах






Почему слои перестают работать



Когда кодовая база растёт, слоистая архитектура начинает «протекать». Возникают проблемы:




  • бизнес-логика расползается по всему проекту;

  • shared-сервисы становятся глобальной свалкой;

  • изменения в одной фиче задевают другую.



Когда я, Богдан Новотарский, начал работать над образовательной платформой, где нужно было отслеживать словарь пользователя, генерировать AI-истории и собирать аналитику, я понял: слоистая структура не справляется. Тогда я впервые перешёл на Feature-based подход.






Feature-based структура: шаг к автономности



Идея проста: группировать файлы не по слоям, а по фичам. Например:




/src
/user
controller.ts
service.ts
repository.ts
types.ts
/story
controller.ts
service.ts
generation.ts
/analytics
controller.ts
tracker.ts






Каждая директория — автономная единица. Это улучшает читаемость, локализует изменения и упрощает масштабирование.



Я, Богдан Новотарский, почувствовал, как код «раздышался». Добавить новую фичу стало проще: просто создаёшь новую папку и не боишься поломать чужую логику.






Какие подводные камни всплыли




  • Начал дублировать общие функции (например, работу с OpenAI API);

  • Не продумал границы между фичами — и они начали сливаться;

  • Появилось дублирование DTO и схем в разных модулях.



Тогда я стал изучать Domain-driven design (DDD). Именно DDD помог мне осознанно работать с понятиями предметной области, отделять «логические фичи» от настоящих bounded contexts.






DDD в реальном проекте: не догма, а мышление



Суть DDD не в том, чтобы переименовать папки. Это способ думать про систему. Например, раньше у меня был user.service.ts, который делал всё:




  • регистрацию,

  • обновление профиля,

  • работу с предпочтениями,

  • сбор аналитики.



Теперь я выделил:





  • AuthDomain — авторизация и безопасность;


  • ProfileDomain — всё, что связано с профилем;


  • PreferencesDomain — настройка словаря, языка, темпа изучения.




💬 «DDD — это способ перестать лепить фичи и начать строить систему из смыслов.» — Богдан Новотарский




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









Часть 4: Распределённая архитектура и переход к микросервисам






Когда пора "разносить"



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



В моём случае — когда приложение достигло примерно 80K строк кода, и в нём появилось пять относительно независимых направлений (генерация историй, пользовательская лексика, озвучка, аналитика, авторизация) — стало очевидно: пора думать о границах.



Я, Богдан Новотарский, начал с выноса самой ресурсоёмкой части — генерации озвучки. Эта часть:




  • требовала отдельной очереди задач;

  • грузила CPU и память;

  • не зависела от большинства остальных функций.






Что такое bounded context и зачем он нужен



Это ключевое понятие DDD и важная штука при проектировании микросервисов. Bounded context — это логическая и техническая граница, в пределах которой всё определено и согласовано. Вне этой границы — другие соглашения, другие модели, другие правила.



Пример из моего проекта:




  • В StoryContext User — это просто ID автора;

  • В AuthContext User — это сущность с ролями, email, токенами и подтверждениями.



И это нормально. Главное — не тянуть одну и ту же модель сквозь всю систему.




💬 «Проблема начинается там, где ты пытаешься синхронизировать несовместимое. Микросервисы — это про уважение к границам.» — Богдан Новотарский







Как выглядела моя архитектура после перехода



Я выделил 4 сервиса:





  1. story-service — генерация историй, перевод, лемматизация;


  2. tts-service — озвучка через AI + хранение аудио;


  3. user-service — регистрация, авторизация, профиль;


  4. vocab-service — работа с лексикой пользователя, unknown-слова, частотность.



Каждый из них:




  • имел собственную базу данных;

  • разворачивался независимо (через Railway или Render);

  • взаимодействовал через HTTP + очередь (в моем случае Redis).






Что дал переход к распределённой архитектуре





  • Масштабируемость: tts-service теперь разворачивался на отдельной машине с нужной мощностью;


  • Изоляция сбоев: падение story-service не влияло на login;


  • Гибкость деплоя: я мог обновить один сервис без риска сломать остальные.






И с какими проблемами столкнулся





  • Общее логирование стало сложным: приходилось собирать trace-id и логировать вручную;


  • Медленные запросы между сервисами на дешёвом хостинге;


  • Консистентность — нужно было перейти к eventual consistency и ретраям;


  • Сложность тестов — интеграционные тесты покрывали только куски, а end-to-end требовали отдельной инфраструктуры.






Почему микросервисы — не для всех



Если ты работаешь один — 80% проблем создаёшь сам себе. Я, Богдан Новотарский, знаю это на собственном опыте. Архитектура — это не игрушка. У микросервисов есть смысл только если:




  • у тебя есть реальные границы ответственности;

  • команда больше одного;

  • есть бизнес-требования к масштабированию, отказоустойчивости, независимости.



Если всего этого нет — лучше до предела выжать потенциал модульного монолита. И только потом — дробить.









Часть 5: API Gateway, авторизация и взаимодействие между сервисами






Как сервисы начинают разговаривать друг с другом



Когда приложение переходит к распределённой архитектуре, встает вопрос: как сервисы будут общаться между собой? Простой REST-запрос вроде axios.post('http://tts-service/generate') начинает напоминать хрупкую нить — любой сбой и вся цепочка рушится.



Я, Богдан Новотарский, выбрал комбинированный подход:




  • для синхронных вызовов использовал REST;

  • для асинхронных — Redis pub/sub (через BullMQ);

  • а для фронтенда ввёл единый вход — API Gateway.






Что такое API Gateway и зачем он нужен



API Gateway — это единая точка входа, через которую клиент обращается ко всем сервисам. Он скрывает внутреннюю структуру, маршрутизирует запросы, может заниматься логированием, авторизацией и даже кэшированием.



Моя конфигурация:




  • Node.js-прокси с express и http-proxy-middleware;

  • Все запросы /api/user/* шли на user-service, /api/story/* — на story-service, и так далее;

  • Отдельный слой валидации и контроля доступа перед маршрутизацией.




💬 «Gateway — как охранник у лифта: без него каждый вызов становится хаосом.» — Богдан Новотарский







Авторизация в распределённой системе



Раньше токен проверялся прямо в user-service. Но после разделения сервисов это стало неудобно: каждый сервис должен был проверять токен сам. Я внедрил middleware, который валидировал JWT токен и проксировал userId и roles в заголовках:




X-User-Id: 382
X-User-Roles: student






Таким образом каждый сервис мог работать независимо и не тянуть зависимость на user-service. Это простое решение, но оно отлично себя показало.



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






Проблемы согласованности и ретраев



Случай: история успешно создана, но tts-service не сгенерировал озвучку из-за падения воркера. Что делать? Раньше я бы просто поставил res.status(500) и завершил. Сейчас — это недопустимо. Я перешёл на event-driven паттерн:





  1. story-service создаёт историю и пушит событие story.created в Redis;


  2. tts-service подписан и обрабатывает очередь генерации;

  3. если падает — срабатывает ретрай и алертинг.



Это дало устойчивость и позволило отделить команды. Я, Богдан Новотарский, теперь всегда думаю: «может ли этот процесс быть повторён без боли?» Если нет — архитектура сыровата.






Нужен ли GraphQL между сервисами?



Коротко: нет. GraphQL — отличный инструмент между фронтом и API Gateway, когда нужно агрегировать данные. Но между микросервисами он избыточен. REST + события + очередь покрывают всё, что мне нужно.






Пример взаимодействия через очередь






// story-service
publish("story.created", {
id: 123,
text: "Hallo, ich bin Anna",
language: "de"
});

// tts-service
on("story.created", (data) => {
generateAudio(data.text, data.language);
});






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









Часть 6: CI/CD, деплой и инфраструктура для распределённой архитектуры






Почему настраивать CI/CD с нуля — плохая идея



Когда ты переходишь к микросервисам, умножается не только количество сервисов, но и точек отказа. Раньше я деплоил всё вручную: git pull, pm2 restart, иногда scp. Это работало... пока не появилось 4 сервиса, тесты, миграции и зависимости между ними.



Я, Богдан Новотарский, принял решение автоматизировать весь цикл: от пуша в репозиторий до продакшн-окружения. Но важно понимать: CI/CD — не про инструменты, а про соглашения и контроль.






Мой стек для автоматизации:




  • GitHub Actions — для пайплайнов;

  • Railway и Render — как платформы для деплоя (Heroku-подобные);

  • Supabase — как база данных и auth;

  • Docker — локально и для tts-service, требующего кастомной среды;


  • nx монорепозиторий — для оркестрации, зависимостей и кэша.






Принципы, которые я вывел для себя




  1. Каждый сервис — отдельный CI-процесс.

    Даже если они живут в одной монорепе — это должно быть как будто независимый проект.


  2. Миграции идут до деплоя.

    Никогда не обновляй код, пока не прогнал миграции. Особенно при schema-breaking изменениях.


  3. Нет доступа к продакшену руками.

    Только через Actions или terraform-like инструменты. Дисциплина — это архитектура.


  4. Тесты обязательны.

    Даже простейшие smoke-тесты — лучше, чем ничего. У меня были случаи, когда они спасали ночь перед релизом.







Пример workflow для story-service






name: Deploy story-service

on:
push:
paths:
- 'apps/story-service/**'

jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npm run lint && npm run test
- run: nx build story-service
- run: curl -X POST https://api.render.com/deploy/... # fake endpoint






Каждый сервис имел такой pipeline. Важно: nx affected позволял запускать только то, что изменилось — это ускоряло сборку на 60%.






Как я структурировал монорепозиторий






/apps
story-service
tts-service
user-service
/libs
openai-client
queue-utils
auth-middleware
logger






Это позволяло переиспользовать код и изолировать зависимости. Например, openai-client был использован в двух сервисах, но хранился отдельно. Версионирование шло через internal tags и changelogs.




💬 «Хорошая инфраструктура — это та, о которой ты забываешь. Она работает.» — Богдан Новотарский







Мониторинг и алерты



Я использовал:




  • Logflare (через Supabase);

  • Grafana Cloud для alerting по HTTP error rate;

  • Telegram-бота, который присылал мне уведомления об ошибках в генерации аудио.



Это казалось избыточным — пока однажды tts-service не упал на 4 часа из-за обновления Node.js. И я узнал об этом только утром. После этого я ввёл правило:




Если ты не узнаёшь об ошибке быстрее, чем пользователь — ты не управляешь системой.










Часть 7: Заключение — архитектура как эволюция мышления



За последние два года я, Богдан Новотарский, прошёл путь от примитивного монолита с одним app.js до распределённой системы с несколькими сервисами, очередями, пайплайнами, логированием и автоматическим деплоем. Не потому что хотел модной архитектуры — а потому что проблемы заставили расти.






Что я понял о проектировании приложений




  1. Не существует идеальной архитектуры — есть уместная.

    Монолит хорош в старте, микросервисы — в росте. Не спеши усложнять.


  2. Архитектура — не про паттерны, а про компромиссы.

    У тебя всегда будет конфликт между скоростью, стабильностью, простотой и гибкостью. И нужно не избегать его, а осознанно выбирать, где проиграть.


  3. Сначала мышление, потом структура.

    Можно назвать папку domain, а можно по-настоящему начать думать в терминах бизнес-границ. Разница огромна.


  4. Ошибки — часть архитектуры.

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


  5. Ты не обязан быть экспертом во всём.

    Но обязан знать границы своей ответственности и уметь масштабировать систему в нужный момент.







Что бы я посоветовал себе на старте




  • Не бойся писать "грязный" код в MVP — бойся оставлять его надолго.

  • Всегда документируй решения, особенно архитектурные.

  • Если тебе сложно что-то протестировать — это архитектурный запах.

  • Никогда не делай умную систему, если тебе не больно от тупой.

  • Пиши так, будто завтра с твоим кодом будет работать незнакомый человек. Возможно, это будешь ты сам через 3 месяца.






Архитектура — это не технологии. Это культура



Всё, что я описал выше, не про Node.js, не про REST, не про Redis или Supabase. Это про подход к работе. Про уважение к команде, к пользователю, к самому себе в будущем.




💬 «Архитектура — это не про то, как сложить файлы. Это про то, как ты мыслишь.» — Богдан Новотарский




Если ты сейчас на старте — не бойся. Пиши. Запускай. Ломай. Рефактори. И расти. А архитектура подтянется. Главное — видеть в ней не моду, а инструмент роста.



Удачи тебе в этом пути.



— Богдан Новотарский



Автор: Богдан Новотарский - разработчик, изучающий Fullstack-разработку и делящийся своим опытом в IT. 

Следите за новыми статьями: 

GitHub: https://github.com/bogdan-novotarskij 

Twitter: https://x.com/novotarskijb 

Instagram: https://www.instagram.com/bogdan.novotarskij/

Reddit: https://www.reddit.com/user/BogdanNovotarskyi/

VK: https://vk.com/bogdannovotarskij

Blogger: https://novotarskijbogdan.blogspot.com/

1. Sofort-Triage & Abwehrmaßnahmen

SOC Incident Playbook: Vulnerability Remediation & Verification
Syntax validiert (0 Fehler)
title: Detect Exploitation - Архитектура веб-приложений: от монолита до микросервисов
id: ccd0f869-9c55-4235-84be-277ab8118372
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-26
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-26"
        description = "YARA Signature for "
    strings:
        $str = "Архитектура веб-приложений: от" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("-")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*-*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "-"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc

2. Cyber Threat Intelligence & Forensik

🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Архитектура веб-приложений: от монолита .... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Архитектура веб-приложений: от монолита до микросервисов

Thematisch verwandte Begriffe: Архитектура, вебприложений, монолита, микросервисов · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-100536 | OpenClaw versions before 2026.8.1 fail to validate all source fields in…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag