<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Blog — George Mishurovsky: posts tagged series</title>
<link>https://mishurovsky.com/blog/?go=tags/series/</link>
<description>A blog by George Mishurovsky — a senior software engineer with a medical degree. Drawing from both engineering and scientific thinking, he explores software, architecture, design, psychology, and product thinking.</description>
<author></author>
<language>en</language>
<generator>Aegea 11.3 (v4134e)</generator>

<itunes:owner>
<itunes:name></itunes:name>
<itunes:email>george@mishurovsky.com</itunes:email>
</itunes:owner>
<itunes:subtitle>A blog by George Mishurovsky — a senior software engineer with a medical degree. Drawing from both engineering and scientific thinking, he explores software, architecture, design, psychology, and product thinking.</itunes:subtitle>
<itunes:image href="https://mishurovsky.com/blog/pictures/userpic/userpic-square@2x.jpg?1753619610" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>Decoupling Responses from Requests: Event-Driven Approach | Microservice Architecture — Ep. 26</title>
<guid isPermaLink="false">49</guid>
<link>https://mishurovsky.com/blog/?go=all/decoupling-responses-from-requests-event-driven-architecture-mic/</link>
<pubDate>Sat, 21 Mar 2026 12:38:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/decoupling-responses-from-requests-event-driven-architecture-mic/</comments>
<description>
&lt;p&gt;Traditional client-server communication is based on request-response paradigm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;send a request&lt;/li&gt;
&lt;li&gt;show loading state and wait&lt;/li&gt;
&lt;li&gt;get the response&lt;/li&gt;
&lt;li&gt;update client state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, microservice architecture does not go along well with it because of two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multiple network hops (high cumulative latency)&lt;/li&gt;
&lt;li&gt;request-response propagation through service chains&lt;br /&gt;
So many requests turn into small distributed workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consider a simple subscription-based video platform. One frontend and three services: Subscriptions, Payments, Recommendations.&lt;/p&gt;
&lt;p&gt;The typical “subscribe” workflow may look like this:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Client calls Subscriptions.&lt;/li&gt;
&lt;li&gt;Subscriptions calls Payments.&lt;/li&gt;
&lt;li&gt;Payment succeeds.&lt;/li&gt;
&lt;li&gt;Recommendations builds a personalized movie list.&lt;/li&gt;
&lt;li&gt;Client fetches recommendations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Where does this orchestration live?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the frontend? → tight coupling to backend internals&lt;/li&gt;
&lt;li&gt;In a BFF? → centralized coordination and sequential bottlenecks&lt;br /&gt;
Both approaches are fragile due to excessive coupling. And if each service talks to each in request-response paradigm, it becomes a tough task under load, having to support hundreds and thousands of open connections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An alternative is to decouple responses from requests using events. Instead of calling each other and waiting for long responses, services communicate through a message broker:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subscriptions emits ‘UserSubscribed’&lt;/li&gt;
&lt;li&gt;Payments consumes it and processes payment&lt;/li&gt;
&lt;li&gt;Payments emits ‘PaymentCompleted’&lt;/li&gt;
&lt;li&gt;Subscriptions and Recommendations react independently&lt;/li&gt;
&lt;li&gt;Recommendations emits ‘RecommendationsReady’&lt;/li&gt;
&lt;li&gt;Some Notifications service may send an email or a live update to the frontend client&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With event-driven architecture we achieve three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;services no longer keep open connections, waiting only for confirmation from message broker&lt;/li&gt;
&lt;li&gt;if some service breaks, requests are not lost, but can be picked up from the message broker by another service instance&lt;/li&gt;
&lt;li&gt;there is no node concerned with process coordination — coordination complexity is moved to communication space&lt;/li&gt;
&lt;li&gt;the system becomes asynchronous: frontend clients receive immediate feedback and unlock other activities while complex workflows are processed in background&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tradeoff — we lose immediate consistency. The benefit — we gain scalability, resilience, and simple service boundaries. This shift, from waiting for results to reacting to events, is one of the key mindset changes in distributed systems.&lt;/p&gt;
</description>
</item>

<item>
<title>Auto-Scaling Groups and Load Balancers | Microservice Architecture — Ep. 25</title>
<guid isPermaLink="false">48</guid>
<link>https://mishurovsky.com/blog/?go=all/auto-scaling-groups-and-load-balancers-microservice-architecture/</link>
<pubDate>Fri, 06 Mar 2026 10:15:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/auto-scaling-groups-and-load-balancers-microservice-architecture/</comments>
<description>
&lt;p&gt;The purpose of microservice architecture is durability and scalability. Durability means a service continues to serve requests during failures or peak traffic. Scalability means achieving durability with the least resources possible, making the service cost-efficient.&lt;/p&gt;
&lt;p&gt;Most modern microservices typically run on small virtual machines with limited vCPU and RAM. These instances are cheap, but still powerful enough to handle thousands of requests per minute.&lt;/p&gt;
&lt;p&gt;However, running a single instance of a service is never enough, as hardware failures are rare but inevitable — even in the best data centers. To maintain durability, at least two instances of a service must run in different data centers (“availability zones” in AWS terminology).&lt;/p&gt;
&lt;p&gt;Another issue is traffic spikes. When load increases, a single instance becomes incapable of handling all requests, so multiple instances become a necessity.&lt;/p&gt;
&lt;p&gt;In practice, service load changes dynamically, e. g. low at night and ten times higher of that during business hours. For cost efficiency, services are usually placed in auto-scaling groups. A dedicated agent monitors metrics such as CPU usage or request rate and automatically adds or removes instances as load surpasses predefined thresholds. Scaling achieved through changes in a number of small instances is called horizontal scaling.&lt;/p&gt;
&lt;p&gt;Horizontal scaling introduces another challenge: how do clients know which instance to talk to?&lt;/p&gt;
&lt;p&gt;An API gateway routes requests to services, but it should not track which instances currently exist or which ones are healthy. That responsibility is delegated to load balancers — lightweight proxy services that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;track active service instances and their IP addresses&lt;/li&gt;
&lt;li&gt;monitor instance health and availability&lt;/li&gt;
&lt;li&gt;distribute load evenly across instances&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As load balancers expose a stable endpoint (often a static IP or DNS name), API gateways can simply route requests to them — offloading instance discovery and traffic distribution to the combined work of load balancers and auto-scaling groups.&lt;/p&gt;
</description>
</item>

<item>
<title>Why API Gateways Became a Thing (Part 2) | Microservice Architecture — Ep. 24</title>
<guid isPermaLink="false">47</guid>
<link>https://mishurovsky.com/blog/?go=all/why-api-gateways-became-a-thing-part-2-microservice-architecture/</link>
<pubDate>Mon, 02 Mar 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/why-api-gateways-became-a-thing-part-2-microservice-architecture/</comments>
<description>
&lt;p&gt;The key feature of API Gateways is the access to all system requests, services they target, and outgoing responses. This position enables capabilities that go beyond simple routing.&lt;/p&gt;
&lt;p&gt;Let’s peek into these capabilities.&lt;/p&gt;
&lt;p&gt;API Versioning&lt;br /&gt;
If multiple API versions exist, the Gateway can forward requests targeting specific API versions to the matching service implementations, centralizing backward compatibility.&lt;/p&gt;
&lt;p&gt;Canary Deployments&lt;br /&gt;
The Gateway can route portions of traffic to new service instances running updated code. As it has access to request and auth data, it can do so based on routes, headers, regions, or tenant attributes.&lt;/p&gt;
&lt;p&gt;Basic validation&lt;br /&gt;
The Gateway may check for oversized payloads and validate basic schema constraints before traffic reaches services, reducing unnecessary system load.&lt;/p&gt;
&lt;p&gt;Request / Response transformation&lt;br /&gt;
The Gateway may enrich requests, e. g. inject tenant data or correlation IDs. In the same manner it can reshape responses, e. g. by hiding internal fields from response payloads.&lt;/p&gt;
&lt;p&gt;Data aggregation&lt;br /&gt;
In simple cases, the Gateway can split a request across multiple services and combine responses before returning them, reducing the need for separate aggregation services.&lt;/p&gt;
&lt;p&gt;Caching&lt;br /&gt;
The Gateway can cache common GET requests, improving latency for high-traffic endpoints and protecting downstream services from excessive load.&lt;/p&gt;
&lt;p&gt;The API Gateway is not just a router and observer — it is a policy enforcement and traffic management layer.&lt;/p&gt;
</description>
</item>

<item>
<title>Why API Gateways Became a Thing (Part 1) | Microservice Architecture — Ep. 23</title>
<guid isPermaLink="false">46</guid>
<link>https://mishurovsky.com/blog/?go=all/why-api-gateways-became-a-thing-part-1-microservice-architecture/</link>
<pubDate>Sat, 28 Feb 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/why-api-gateways-became-a-thing-part-1-microservice-architecture/</comments>
<description>
&lt;p&gt;As we &lt;a href="https://mishurovsky.com/blog/?go=all/cross-cutting-concerns-in-microservices-microservice-architectur/"&gt;discussed earlier&lt;/a&gt;, microservices tend to accumulate a lot of repeated concerns unrelated to their responsibilities. If something repeats across services, we should try to move it into a separate service that clients hit first before talking to downstream services — some Gateway.&lt;/p&gt;
&lt;p&gt;What can we hand off to the Gateway?&lt;/p&gt;
&lt;p&gt;Routing&lt;br /&gt;
Public-facing services have IPs which are prone to change. The Gateway provides stable routes, discovers service IPs and forwards requests to the right targets.&lt;/p&gt;
&lt;p&gt;Protocol translation&lt;br /&gt;
Services do not need to support any protocol. Teams pick the most appropriate one, and the Gateway translates requests and responses as needed.&lt;/p&gt;
&lt;p&gt;Authentication and tiered access&lt;br /&gt;
Domain services should not parse tokens or know about subscription tiers. The Gateway validates credentials, checks access levels, and can short-circuit unauthorized requests before they reach downstream services.&lt;/p&gt;
&lt;p&gt;TLS termination&lt;br /&gt;
If traffic enters through a single point, TLS can be terminated at the Gateway. Internal services may communicate over simpler internal channels (though in high-security environments, end-to-end encryption may still be required).&lt;/p&gt;
&lt;p&gt;Request logging and monitoring&lt;br /&gt;
As the Gateway handles all requests, it can centrally log user activity and provide metrics.&lt;/p&gt;
&lt;p&gt;Request throttling&lt;br /&gt;
The Gateway can track whether a client puts excessive load on the system and stop propagation of frequent requests. And as it sees authentication context and system-wide traffic patterns, it can enforce global rate-limiting strategies — individual services cannot do that effectively.&lt;/p&gt;
&lt;p&gt;In short, the Gateway provides a stable application programming interface to an unstable internal world — it is the API Gateway. It hides topology, enforces global policies, and lets domain services focus on business logic. That is why it became a foundational pattern in microservice architecture.&lt;/p&gt;
</description>
</item>

<item>
<title>Cross-Cutting Concerns in Microservices | Microservice Architecture  — Ep. 22</title>
<guid isPermaLink="false">43</guid>
<link>https://mishurovsky.com/blog/?go=all/cross-cutting-concerns-in-microservices-microservice-architectur/</link>
<pubDate>Thu, 19 Feb 2026 12:11:37 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/cross-cutting-concerns-in-microservices-microservice-architectur/</comments>
<description>
&lt;p&gt;Let’s return to our migration from a monolith. Imagine we’ve successfully split it into dozens of microservices. Some services are internal, some face clients.&lt;/p&gt;
&lt;p&gt;The company grows, the number of clients increases — along with their demands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;new devices&lt;/li&gt;
&lt;li&gt;new protocols&lt;/li&gt;
&lt;li&gt;new response formats&lt;/li&gt;
&lt;li&gt;new pricing tiers&lt;br /&gt;
Multiple services, combined with lots of clients lead to complex inter-service relations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we take a naive approach and extract domain slices into services along with everything required to provide proper access — every team will be solving the same set of problems.&lt;/p&gt;
&lt;p&gt;Each service now has to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support multiple communication protocols&lt;/li&gt;
&lt;li&gt;handle authentication&lt;/li&gt;
&lt;li&gt;evaluate tenant tiers&lt;/li&gt;
&lt;li&gt;manage throttling and load balancing&lt;/li&gt;
&lt;li&gt;collect logs, metrics, and tracing data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is one more problem — data aggregation. Many endpoints need data from multiple services. To reduce latency, we introduce caching, but:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;some queries are hot, others are rarely used&lt;/li&gt;
&lt;li&gt;some queries require near real-time freshness&lt;/li&gt;
&lt;li&gt;different clients may need different response shapes&lt;/li&gt;
&lt;li&gt;different clients may want to combine data from different domains&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aggregation services risk becoming bloated and complex, with clusters of similar endpoints coupled to specific client needs, and excessive duplication of both code and cached data.&lt;/p&gt;
&lt;p&gt;How can we address these problems?&lt;/p&gt;
</description>
</item>

<item>
<title>Micro-Frontends and the Illusion of Isolation | Microservice Architecture — Ep. 21</title>
<guid isPermaLink="false">42</guid>
<link>https://mishurovsky.com/blog/?go=all/micro-frontends-and-the-illusion-of-isolation-microservice-archi/</link>
<pubDate>Wed, 18 Feb 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/micro-frontends-and-the-illusion-of-isolation-microservice-archi/</comments>
<description>
&lt;p&gt;While the key idea behind micro-frontends is the same as for microservices — independent development and deployment — micro-frontend architecture presents very different problems.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;No real isolation.&lt;/b&gt;&lt;br /&gt;
Backend microservices run in separate processes — often on separate machines. Micro-frontends share the same browser tab: the same DOM, CSS namespace, event system, storage, and main thread.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Limited deployment independence.&lt;/b&gt;&lt;br /&gt;
Backends integrate over the network — but micro-frontends integrate in memory. They depend on a shell application, shared routing and design systems: braking changes in those layers affect everyone.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Shared data is unavoidable.&lt;/b&gt;&lt;br /&gt;
A lot of frontend state is cross-cutting: feature flags, session, auth, cart contents. We can modularize code, but cannot pretend data ownership is cleanly separated.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Shared and constrained hardware.&lt;/b&gt;&lt;br /&gt;
On the backend, a slow service does not block CPU for others and can be easily scaled. In the browser, components compete for the same main thread, often on low-end mobile devices. Performance budgets are a cross-team concern.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Integration problems are very prominent.&lt;/b&gt;&lt;br /&gt;
Backend failures degrade responses. With proper loading and fallback states in UI, users may not even notice. Frontend failures degrade user experience: broken layout, flicker, inconsistent interactions — all seen immediately.&lt;/p&gt;
&lt;p&gt;Splitting responsibility without breaking UX is the real challenge of micro-frontends.&lt;/p&gt;
</description>
</item>

<item>
<title>What are Micro-Frontends? | Microservice Architecture — Ep. 20</title>
<guid isPermaLink="false">41</guid>
<link>https://mishurovsky.com/blog/?go=all/what-are-micro-frontends-microservice-architecture-ep-20/</link>
<pubDate>Wed, 11 Feb 2026 16:32:25 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/what-are-micro-frontends-microservice-architecture-ep-20/</comments>
<description>
&lt;p&gt;Historically, user-facing applications were rendered on the server — the same place where all logic resides. The backend processed requests and generated HTML dynamically.&lt;/p&gt;
&lt;p&gt;Around 2010, single page applications (SPA) emerged. HTML started being generating in the browser using data from backend, which enabled complex state management and rich UI interactions.&lt;/p&gt;
&lt;p&gt;Today, we see a partial return to server-side rendering (SSR) for performance and SEO reasons. Still, state orchestration and smooth UX remain complex enough to require dedicated frontend expertise.&lt;/p&gt;
&lt;p&gt;Just like backend systems, frontend codebases often start as monoliths. And just like in the backend world, once a frontend team grows beyond ~5 engineers, coordination becomes harder, release cycles slow down, and ownership becomes blurry, calling for split teams — the micro-frontend approach.&lt;/p&gt;
&lt;p&gt;Usually this is achieved by having a shell application that provides layout, routing, and shared infrastructure. Independent frontend teams work on separate pages or feature slices, that are composed at runtime.&lt;/p&gt;
&lt;p&gt;Core principles of micro-frontends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isolation&lt;br /&gt;
Unlike backend microservices, code from different teams ends up in the same browser page — so teams have to namespace CSS classes, browser events, cookies and local storage items.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Resilience&lt;br /&gt;
A robust frontend prioritizes server-side rendering and progressive enhancement. Teams should rely on server-side rendering, using client-side JS to enhance UX.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Technology agnosticism&lt;br /&gt;
Teams should be able to choose their frontend stacks, which should not affect performance or user experience of the whole SPA.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Microservice thinking is not limited to backend systems. The idea of independent teams working on well-defined, isolated components applies to any system divisible by such components.&lt;/p&gt;
</description>
</item>

<item>
<title>Team Autonomy That Actually Scales | Microservice Architecture — Ep. 19</title>
<guid isPermaLink="false">40</guid>
<link>https://mishurovsky.com/blog/?go=all/team-autonomy-that-actually-scales-microservice-architecture-ep/</link>
<pubDate>Mon, 09 Feb 2026 11:19:14 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/team-autonomy-that-actually-scales-microservice-architecture-ep/</comments>
<description>
&lt;p&gt;As we learned in &lt;a href="https://mishurovsky.com/blog/?go=all/why-you-dont-want-complete-team-autonomy-microservice-architectu/"&gt;the previous episode&lt;/a&gt;, not every decision benefits from decentralization.&lt;/p&gt;
&lt;p&gt;When microservices use technologies different from the original monolith, the organization pays:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a one-time cost to set up each service&lt;/li&gt;
&lt;li&gt;a recurring cost to operate and support it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cost of building actual features, however, stays roughly the same regardless of language or paradigm.&lt;/p&gt;
&lt;p&gt;So autonomy should be tiered — unify decisions that reduce operational and coordination overhead!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1. Strict tier&lt;/b&gt;&lt;br /&gt;
Single standards to avoid repeated work across teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;infrastructure — cloud provider, core services, machine types&lt;/li&gt;
&lt;li&gt;API standards — protocol, versioning and deprecation rules (might differ by service class)&lt;/li&gt;
&lt;li&gt;monitoring and alerting — shared logging, metrics, and alerting conventions&lt;/li&gt;
&lt;li&gt;security policies — access control, secret rotation, PII handling&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;2. Relaxed tier&lt;/b&gt;&lt;br /&gt;
A small set of options (2–5 choices) to balance flexibility and cognitive load:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;programming languages and frameworks&lt;/li&gt;
&lt;li&gt;messaging technologies&lt;/li&gt;
&lt;li&gt;database technologies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;3. Guardrail tier&lt;/b&gt;&lt;br /&gt;
Default “golden paths” teams follow unless they consciously opt out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;recommended tech stacks&lt;/li&gt;
&lt;li&gt;starters and templates&lt;/li&gt;
&lt;li&gt;base CI/CD pipelines&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4. Free tier&lt;/b&gt;&lt;br /&gt;
Fully team-owned decisions where autonomy improves effectiveness without added recurring costs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;internal quality practices&lt;/li&gt;
&lt;li&gt;release process&lt;/li&gt;
&lt;li&gt;release schedule&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tiered autonomy reduces infrastructure and support costs, while giving teams enough freedom to organize their work effectively.&lt;/p&gt;
</description>
</item>

<item>
<title>Why You Don’t Want Complete Team Autonomy | Microservice Architecture — Ep. 18</title>
<guid isPermaLink="false">39</guid>
<link>https://mishurovsky.com/blog/?go=all/why-you-dont-want-complete-team-autonomy-microservice-architectu/</link>
<pubDate>Fri, 06 Feb 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/why-you-dont-want-complete-team-autonomy-microservice-architectu/</comments>
<description>
&lt;p&gt;Microservice team autonomy means freedom to choose technologies: languages, frameworks, databases, infrastructure.&lt;/p&gt;
&lt;p&gt;Imagine splitting a large monolith into 10-20 microservices. Each team picks a stack different from the original system — and different from each other.&lt;/p&gt;
&lt;p&gt;This leads to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;new folder structures&lt;/li&gt;
&lt;li&gt;new code style conventions&lt;/li&gt;
&lt;li&gt;new linting rules&lt;/li&gt;
&lt;li&gt;new test harnesses&lt;/li&gt;
&lt;li&gt;new database schemas&lt;/li&gt;
&lt;li&gt;new CI/CD pipelines&lt;/li&gt;
&lt;li&gt;new infrastructure definitions&lt;/li&gt;
&lt;li&gt;new monitoring and alerting setups&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And this can turn very problematic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most of these decisions require thorough analysis with long discussions — even within a single team.&lt;/li&gt;
&lt;li&gt;Engineers face a steep learning curve as the whole tech stack differs from the one they are used to.&lt;/li&gt;
&lt;li&gt;API boundaries become harder to reason about when teams mix REST, GraphQL, RPC, and custom protocols.&lt;/li&gt;
&lt;li&gt;Infrastructure complexity explodes — the teams might start spending more time on configuration than on writing new features!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Microservices aim to enable independent teams and faster delivery — but not every decision benefits from decentralization.&lt;/p&gt;
&lt;p&gt;What do you think might be a possible solution here? Share your thoughts in the comments!&lt;/p&gt;
&lt;p&gt;I’m writing a full series on microservice architecture — from base definitions to hands-on topics like testing, deployment, and observability.&lt;br /&gt;
Follow or connect if you want to continue the series, or read them on my blog: &lt;a href="https://mishurovsky.com/blog/tags/microservices-event-driven-architecture/"&gt;https://mishurovsky.com/blog/tags/microservices-event-driven-architecture/&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>DRY vs Microservices: When Reuse Becomes a Liability | Microservice Architecture  — Ep. 17</title>
<guid isPermaLink="false">38</guid>
<link>https://mishurovsky.com/blog/?go=all/dry-vs-microservices-when-reuse-becomes-a-liability-microservice/</link>
<pubDate>Wed, 04 Feb 2026 11:21:33 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/dry-vs-microservices-when-reuse-becomes-a-liability-microservice/</comments>
<description>
&lt;p&gt;“Don’t Repeat Yourself” principle sits at the core of software engineering. We usually structure our code to have as few to changes as possible when requirements shift.&lt;/p&gt;
&lt;p&gt;This approach is right inside any single microservice — use it! But it gets trickier when DRY is applied across microservices. Not every duplicated piece of logic should be extracted into a shared library.&lt;/p&gt;
&lt;p&gt;Remember, the goal of microservice architecture is independent deployment. Shared libraries work against that goal and introduce coupling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Updating a library forces coordinated releases across multiple services (who owns the library and coordination then, by the way?).&lt;/li&gt;
&lt;li&gt;A bug in the library makes all dependent services vulnerable.&lt;/li&gt;
&lt;li&gt;Frequent library updates open a potential for version conflicts and dependency hell.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what if logic really needs to be shared?&lt;/p&gt;
&lt;p&gt;If it is cross-service communication logic, sharing code can be a good tradeoff. Libraries or code generation to keep contracts in sync (schemas, clients, message definitions) usually increase development speed rather than hinder it.&lt;/p&gt;
&lt;p&gt;If it is business logic, this might indicate a boundary problem. Combine microservices into a single, more cohesive one — or extract that logic into a dedicated service.&lt;/p&gt;
&lt;p&gt;If introducing a new service is undesirable, the sidecar pattern is a possible solution. Move shared logic into a separate process running co-host with each service instance. This way service and sidecar lifecycles get separated, avoiding tight compile-time dependencies.&lt;/p&gt;
&lt;p&gt;In microservices, duplication is often cheaper than coordination.&lt;/p&gt;
</description>
</item>

<item>
<title>Problems of the “One Database per Microservice” Approach | Microservice Architecture — Ep. 16</title>
<guid isPermaLink="false">37</guid>
<link>https://mishurovsky.com/blog/?go=all/the-problems-of-the-one-database-per-microservice-principle-micr/</link>
<pubDate>Mon, 02 Feb 2026 12:17:02 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/the-problems-of-the-one-database-per-microservice-principle-micr/</comments>
<description>
&lt;p&gt;As discussed in &lt;a href="https://mishurovsky.com/blog/all/one-microservice-one-database-meda-ep-15/"&gt;the previous post&lt;/a&gt;, the proper approach of data ownership in microservice architecture is for each service to have its own database hidden behind a network API.&lt;/p&gt;
&lt;p&gt;While this approach solves independent service development and deployment, it introduces strong downsides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accessing foreign data now requires a network call, typically adding 100 – 200 ms of latency.&lt;/li&gt;
&lt;li&gt;Cross-service joins become inefficient: data must be fetched from multiple services, normalized, and only then combined.&lt;/li&gt;
&lt;li&gt;Cross-service transactions get much more complicated — some services may use storage technologies that don’t support transactions at all!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How to cope with these problems?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cache foreign data locally to reduce network calls. This improve latency, but introduces tough questions: what to cache and when to invalidate.&lt;/li&gt;
&lt;li&gt;For complex joins, create a dedicated microservice that gathers data on schedule and stores join results in its own database (a benefit here is that it can keep and provide results of previous computations).&lt;/li&gt;
&lt;li&gt;For cross-service transactions, use sagas. Each service defines forward and compensating actions, coordinated either via orchestration (by a separate coordinator service) or choreography (event-driven coordination configured for each participating microservice).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These solutions are not simple. The “one database per service” principle trades local simplicity for system-level complexity — but it remains the most scalable and sustainable approach for microservice architectures.&lt;/p&gt;
</description>
</item>

<item>
<title>One Microservice — One Database | Microservice Architecture — Ep. 15</title>
<guid isPermaLink="false">36</guid>
<link>https://mishurovsky.com/blog/?go=all/one-microservice-one-database-meda-ep-15/</link>
<pubDate>Fri, 30 Jan 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/one-microservice-one-database-meda-ep-15/</comments>
<description>
&lt;p&gt;The core idea of microservice architecture is decoupling: separate teams, codebases, lifecycles. Yet often it is still tempting to share a database between multiple services, especially when the system is relatively small. But it is a wrong decision.&lt;/p&gt;
&lt;p&gt;Why shared databases break microservices:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Microservice A cannot write to tables owned by microservice B, as each microservice must own its data undivided.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Microservice A cannot read tables owned by microservice B, as any schema change, table / row permission update, or migration can silently break downstream services.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Microservice A cannot keep its data in a separate table of microservice B’s database. If the B changes DB technology or scaling strategy, the tables of A have to be moved elsewhere, but by who owns the migration? It is especially complex issue once there are more than two services involved.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="4"&gt;
&lt;li&gt;With direct DB connections, the load on IO from some fast growing service might become so intensive it would degrade operation of unrelated services.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is why each microservice needs its own database. All access to that data must go through the service’s API or events, and never through direct database connections.&lt;/p&gt;
</description>
</item>

<item>
<title>How to Migrate from a Monolith to Microservices (Without Regretting It) | Microservice Architecture — Ep. 14</title>
<guid isPermaLink="false">34</guid>
<link>https://mishurovsky.com/blog/?go=all/how-to-migrate-from-a-monolith-to-microservices-without-regretti/</link>
<pubDate>Mon, 26 Jan 2026 14:59:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/how-to-migrate-from-a-monolith-to-microservices-without-regretti/</comments>
<description>
&lt;p&gt;When an architectural change this big is agreed upon, it is natural to perform migration of the whole monolith at once. Freeze all current development, develop a plan, split tasks and start. But beware!&lt;/p&gt;
&lt;p&gt;If the decision to migrate is made, it is likely we already have a large codebase and an excessively large team that has lost coordination and velocity. The business will not accept months without new features, either.&lt;/p&gt;
&lt;p&gt;The right way is to go incremental. Create a small team of experienced engineers, isolate a narrow component for migration, and set no hard deadlines. You will uncover unexpected issues early — but with limited scope, the cost of mistakes stays low and progress is still clearly visible.&lt;/p&gt;
&lt;p&gt;How to execute the migration?&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Define API of the component to be extracted.&lt;/li&gt;
&lt;li&gt;Ensure its thorough automated test coverage with a 100% pass rate.&lt;/li&gt;
&lt;li&gt;Isolate the component by removing dependencies on the monolith.&lt;/li&gt;
&lt;li&gt;Extract into a microservice and ensure all tests passing.&lt;/li&gt;
&lt;li&gt;Put the microservice behind a facade (e. g., an API gateway).&lt;/li&gt;
&lt;li&gt;Route part of production traffic to it.&lt;/li&gt;
&lt;li&gt;Monitor the service under the real load and fix issues.&lt;/li&gt;
&lt;li&gt;Remove the extracted component from the monolith.&lt;br /&gt;
This approach is commonly known as the Strangler Fig Pattern.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Microservices migrations fail most often not because of technology — but because the change must be both technical and organizational.&lt;/p&gt;
</description>
</item>

<item>
<title>Where to Split? | Microservice Architecture — Ep. 13</title>
<guid isPermaLink="false">33</guid>
<link>https://mishurovsky.com/blog/?go=all/where-to-split-meda-ep-13/</link>
<pubDate>Fri, 23 Jan 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/where-to-split-meda-ep-13/</comments>
<description>
&lt;p&gt;A classic question when designing microservices: what defines a good boundary?&lt;/p&gt;
&lt;p&gt;One approach is to split business capabilities. For an online store they can be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Product Catalog&lt;/li&gt;
&lt;li&gt;Search&lt;/li&gt;
&lt;li&gt;Reviews&lt;/li&gt;
&lt;li&gt;Cart&lt;/li&gt;
&lt;li&gt;Billing&lt;/li&gt;
&lt;li&gt;Shipping&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Capability-based splitting usually leads to very stable services, as business needs evolve slowly and rarely require large-scale changes.&lt;/p&gt;
&lt;p&gt;Another approach is to split by technical domains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Core — unique functionality of this particular business (e. g. Product Catalog)&lt;/li&gt;
&lt;li&gt;Supporting — industry-common core helpers (e. g. Cart, Billing, Shipping)&lt;/li&gt;
&lt;li&gt;Generic — non-unique non-specific functionality (e. g. Auth, Search, Payment, Image Processing)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This model is more intuitive for engineers. It also makes it easier to decompose large domains into smaller services when scale or ownership demands it.&lt;/p&gt;
&lt;p&gt;Both approaches focus on cohesion and loose coupling and achieve quite stable microservice boundaries under changing requirements.&lt;/p&gt;
</description>
</item>

<item>
<title>Principles Behind Good Microservice Boundaries | Microservice Architecture — Ep. 12</title>
<guid isPermaLink="false">31</guid>
<link>https://mishurovsky.com/blog/?go=all/principles-behind-good-microservice-boundaries-meda-ep-12/</link>
<pubDate>Mon, 19 Jan 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/principles-behind-good-microservice-boundaries-meda-ep-12/</comments>
<description>
&lt;ol start="1"&gt;
&lt;li&gt;Single Responsibility. Consumers of a service need to clearly understand its purpose.&lt;/li&gt;
&lt;li&gt;High Cohesion and Exhaustiveness. All related functionality has to end up in the same service.&lt;/li&gt;
&lt;li&gt;Low Coupling. Services should minimize dependencies on others — even if that means duplicating supporting code. Big codebases for microservices are OK as long as the services are cohesive and centered around a single business capability.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Imaging we have a patient data management system for hospital intensive care units (ICUs), built as a monolith. It manages patient information, prescriptions, treatment history, vital parameters, and provides a dashboard with current state and therapy.&lt;/p&gt;
&lt;p&gt;❌ Wrong decomposition:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dashboard&lt;/li&gt;
&lt;li&gt;care plan&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why? Consider we add a new drug into the system. All services must change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;care plan —  to prescribe it&lt;/li&gt;
&lt;li&gt;monitoring — to display past treatments with the new drug&lt;/li&gt;
&lt;li&gt;dashboard — to show current therapy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ Better approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;drugs&lt;/li&gt;
&lt;li&gt;vital parameters&lt;/li&gt;
&lt;li&gt;timeline (treatment plans, current state, history)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why? Available drugs and vital parameters change in one place, while evolution of timeline does not affect other services. Each service owns a stable business concept, not a UI page.&lt;/p&gt;
&lt;p&gt;Good microservice boundaries reduce change coordination, not just code size.&lt;/p&gt;
</description>
</item>

<item>
<title>Benefits and Challenges of Microservice Architecture | Microservice Architecture — Ep. 11</title>
<guid isPermaLink="false">30</guid>
<link>https://mishurovsky.com/blog/?go=all/benefits-and-challenges-of-microservice-architecture-meda-ep-11/</link>
<pubDate>Fri, 16 Jan 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/benefits-and-challenges-of-microservice-architecture-meda-ep-11/</comments>
<description>
&lt;p&gt;The core of microservice approach contains two ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;narrow business domains&lt;/li&gt;
&lt;li&gt;small and independent teams (2-pizza team size)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, splitting monoliths into microservices immediately brings benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;smaller codebases — easier to comprehend, faster to change&lt;/li&gt;
&lt;li&gt;higher cohesion — easier to comprehend, more reasonable to scale when needed&lt;/li&gt;
&lt;li&gt;smaller build sizes — cheaper infrastructure and better horizontal scaling&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These benefits are balanced by fundamental trade-offs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the system becomes distributed — network delays and partitions become ordinary and must be designed for&lt;/li&gt;
&lt;li&gt;the system becomes asynchronous — integration and end-to-end testing becomes significantly harder&lt;/li&gt;
&lt;li&gt;events are now processed by service chains — bugs become harder to trace, reproduce, and reason about&lt;/li&gt;
&lt;li&gt;wrong service boundaries are expensive — errors here lead to numerous inter-service dependencies, spawning a &lt;i&gt;“distributed monolith”&lt;/i&gt;, combining cons of both approaches while bringing few benefits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Microservices shift complexity from code size to communication structure, forcing boundaries between business logic and supporting infrastructure.&lt;/p&gt;
</description>
</item>

<item>
<title>Problems of Monoliths in Growing Projects | Microservice Architecture — Ep. 10</title>
<guid isPermaLink="false">29</guid>
<link>https://mishurovsky.com/blog/?go=all/problems-of-monoliths-in-growing-projects-meda-ep-10/</link>
<pubDate>Wed, 14 Jan 2026 11:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/problems-of-monoliths-in-growing-projects-meda-ep-10/</comments>
<description>
&lt;p&gt;When a project grows successfully, with time amount of code grows, and more devs are hired. This often leads to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a bloated codebase — harder for new engineers to understand, slower to change&lt;/li&gt;
&lt;li&gt;tight coupling between many modules — releases require more coordination and happen less frequently&lt;/li&gt;
&lt;li&gt;growing coordination overhead — N team members can form up to N² communication paths&lt;/li&gt;
&lt;li&gt;legacy accumulation — dependencies receive updates, but codebase upgrades are postponed due to fear of breaking changes&lt;/li&gt;
&lt;li&gt;longer build times&lt;/li&gt;
&lt;li&gt;increasing hardware requirements for all environments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a time when teams start thinking about splitting the system into smaller, independently evolving parts.&lt;/p&gt;
&lt;p&gt;Would you name the approach? :)&lt;/p&gt;
</description>
</item>

<item>
<title>It is Right to Start with a Monolith | Microservice Architecture — Ep. 9</title>
<guid isPermaLink="false">28</guid>
<link>https://mishurovsky.com/blog/?go=all/apps-usually-begin-with-a-monolithic-architecture-meda-ep-9/</link>
<pubDate>Mon, 12 Jan 2026 17:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/apps-usually-begin-with-a-monolithic-architecture-meda-ep-9/</comments>
<description>
&lt;p&gt;Microservices have many benefits — but they are not a default choice for greenfield projects.&lt;/p&gt;
&lt;p&gt;Monoliths have strong advantages that service-oriented approaches cannot offer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the whole app is deployed as a single unit: if it compiles, cross-module integration is likely correct&lt;/li&gt;
&lt;li&gt;development and refactoring are simpler: the compiler helps to track if changes are complete&lt;/li&gt;
&lt;li&gt;cross-module calls are synchronous or close to synchronous, taking less than 1-10 milliseconds&lt;/li&gt;
&lt;li&gt;testing is easier, with clear targets of integration and e2e tests&lt;/li&gt;
&lt;li&gt;debugging is simpler: spin up the app locally, set breakpoints, attach a profiler — and you have the whole system for inspection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When monoliths are OK:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;small projects&lt;/li&gt;
&lt;li&gt;small teams&lt;/li&gt;
&lt;li&gt;unclear domain&lt;/li&gt;
&lt;li&gt;unclear scaling requirements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...basically, in most new projects.&lt;/p&gt;
</description>
</item>

<item>
<title>Decomposition of ESBs into Cloud Services | Microservice Architecture — Ep. 8</title>
<guid isPermaLink="false">27</guid>
<link>https://mishurovsky.com/blog/?go=all/decomposition-of-esbs-into-cloud-services-microservices-event-dr/</link>
<pubDate>Fri, 09 Jan 2026 17:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/decomposition-of-esbs-into-cloud-services-microservices-event-dr/</comments>
<description>
&lt;p&gt;Let’s revise what were the responsibilities of Enterprise Service Buses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;service discovery and communication&lt;/li&gt;
&lt;li&gt;request routing&lt;/li&gt;
&lt;li&gt;protocol mediation&lt;/li&gt;
&lt;li&gt;authN and authZ&lt;/li&gt;
&lt;li&gt;rate limiting&lt;/li&gt;
&lt;li&gt;logging and monitoring&lt;/li&gt;
&lt;li&gt;workflow orchestration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These capabilities are generic. Any sufficiently complex system needs them — but they don’t need to live inside a single, centralized component.&lt;/p&gt;
&lt;p&gt;In cloud-native systems, ESBs were effectively decomposed into specialized services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;service discovery -&gt; service mesh tools (AppMesh, Linkerd)&lt;/li&gt;
&lt;li&gt;service communication -&gt; messaging and event streaming platforms (Kafka, SQS)&lt;/li&gt;
&lt;li&gt;request routing, rate limiting, auth -&gt; API gateways&lt;/li&gt;
&lt;li&gt;logging and monitoring -&gt; observability tools (CloudWatch, CloudTrail)&lt;/li&gt;
&lt;li&gt;orchestration -&gt; workflow engines (Step Functions)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What remained were microservices themselves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;independently developed&lt;/li&gt;
&lt;li&gt;independently deployed&lt;/li&gt;
&lt;li&gt;independently scaled&lt;br /&gt;
...units of a system, focused on isolated business capabilities.&lt;/li&gt;
&lt;/ul&gt;
</description>
</item>

<item>
<title>Tech Background of the Early 2010s | Microservice Architecture — Ep. 7</title>
<guid isPermaLink="false">26</guid>
<link>https://mishurovsky.com/blog/?go=all/tech-background-of-the-early-2010s-microservices-event-driven-ar/</link>
<pubDate>Wed, 07 Jan 2026 17:00:00 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/tech-background-of-the-early-2010s-microservices-event-driven-ar/</comments>
<description>
&lt;p&gt;The late 2000s to early 2010s marked the emergence of cloud computing. AWS and Google Cloud made on-demand compute available at scale.&lt;/p&gt;
&lt;p&gt;The hardware and infrastructure assumptions shifted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ephemeral instances became the norm&lt;/li&gt;
&lt;li&gt;horizontal scaling became cheaper&lt;/li&gt;
&lt;li&gt;infrastructure-as-code tools appeared and matured&lt;/li&gt;
&lt;li&gt;instance and network failures now considered expected, not exceptional&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the same time, communication protocols and platforms stabilized around clear leaders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP as the universal transport&lt;/li&gt;
&lt;li&gt;JSON as the universal data language&lt;/li&gt;
&lt;li&gt;REST / gRPC as dominant API styles&lt;/li&gt;
&lt;li&gt;Linux as the default server OS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This convergence reduced the need for protocol mediation and heavy integration layers — some of the reasons ESBs were invented. The switch from SOA was not driven only by its limitations, but also by changes in technology.&lt;/p&gt;
</description>
</item>


</channel>
</rss>