Helpful information ...
Microservices Architecture: An In-Depth Explanation and Decision Guide
Microservices architecture: an in-depth explanation and decision guide
Microservices architecture breaks an application down into small, independent services, where each one covers a single business function and communicates through clearly defined interfaces. Before choosing this approach, check four key criteria:
- Independent scaling is essential. If one part of the system (e.g. payments) needs significantly more capacity than the rest, microservices let you scale just that part.
- Multiple teams work in parallel. When different teams are developing separate features, independent services prevent them from blocking each other.
- Technology diversity adds value. Different services can run on different languages or databases, where that's justified by the business.
- Domain complexity is high and growing. Microservices make sense for systems where business requirements dictate clearly separated contexts.
Microservices aren't the right choice for smaller projects with a single team, for MVPs, or when a team's operational maturity hasn't yet reached the level a distributed system requires. Initial and operating costs are significantly higher than with a monolith.
Key takeaways
Microservices are architecturally justified for complex domains with multiple teams, but they require mature DevOps processes, observability, and clearly defined service boundaries before they deliver on their promised advantages.
| Point | Details |
|---|---|
| When to choose microservices | Sensible for a team of 5+ developers, a complex domain, and requirements for independent scaling. |
| Key technologies | Docker, Kubernetes, Kong, RabbitMQ or Kafka, Keycloak with OAuth2/OpenID Connect. |
| The most common mistake | Transitioning too early, without established monitoring, distributed tracing, and automated tests. |
| Migration strategy | The strangler fig pattern with incremental decomposition by bounded contexts, building the system's skeleton first. |
| Moxy-web | Offers architecture analysis, a PoC, and gradual development of microservice systems with long-term support. |
Table of contents
- How do microservices work, and how do they differ from a monolith and SOA?
- Which concepts form the foundation of good microservices architecture?
- Which technologies and components do you need for a reliable system?
- What do you gain, and what do you pay for, with microservices architecture?
- What are the main challenges, and how do you solve them in practice?
- How to safely deploy microservices to production?
- When and how to move from a monolith to microservices?
- What does microservices architecture look like in practice?
- Are microservices the right choice for your project?
- The Moxy-web perspective: what we've learned about architecture decisions
- Moxy-web helps you plan and build your architecture
- Sources
- Frequently asked questions
How do microservices work, and how do they differ from a monolith and SOA?
Explaining microservices architecture starts with understanding what this approach replaces. A classic monolith is a single application that contains every business function in one codebase and gets deployed as a whole. Every change requires redeploying the entire application, and scaling means duplicating everything, not just the part under load.
Service-oriented architecture (SOA) was a step forward: it split a system into larger services that communicated through a central message broker (ESB). Microservices go further, since each service covers a single business function, has no central broker, and deploys completely independently. The difference isn't just technical - it's organizational: microservices follow Conway's Law, which states that a system's architecture reflects the communication structure of the organization behind it.
Imagine an online store. In a monolith, the order module, payments, and authentication are all part of the same application. In a microservices architecture, each of these three elements is a separate service with its own database, its own API, and its own deployment cycle. The order service doesn't know how the payment service works - it only knows how to call it.
| Dimension | Monolith | SOA | Microservices |
|---|---|---|---|
| Deployment unit | The whole application | A larger service | One service / one function |
| Communication | Internal (function calls) | ESB broker | REST, gRPC, message queue |
| Database | Shared | Often shared | Separate per service |
| Scaling | The whole thing together | A service together | An individual function |
| Operational complexity | Low | Medium | High |
| Suitable for | Smaller systems, one team | Enterprise environments | Complex domains, multiple teams |
An academic review of microservices architectures confirms that microservices often involve Docker for containerization, Kubernetes for orchestration, and HTTP/REST, gRPC, and asynchronous mechanisms (RabbitMQ, Kafka) for communication between services.
Communication between services happens in two ways. Synchronous (REST or gRPC) suits cases where a call needs an immediate response, for example checking stock before confirming an order. Asynchronous communication through message queues (RabbitMQ, Apache Kafka) is better for processes that don't need an immediate response, for example sending an email notification after an order is completed.
Which concepts form the foundation of good microservices architecture?
Well-designed microservices don't come from randomly splitting up code. They rest on four design principles that determine where the boundaries between services lie.
Bounded context comes from domain-driven design (DDD). Every service has its own domain of concepts and doesn't share models with other services. The order service has its own definition of a "customer," and the delivery service has its own, even though both refer to the same person. This separation prevents a change in one service from breaking another.
Loose coupling means services communicate with each other only through public interfaces, never through shared databases or direct calls to internal methods. When this principle is violated, you end up with a "distributed monolith": a system with the complexity of microservices but the rigidity of a monolith.
Single responsibility dictates that each service does one thing well. A service that simultaneously handles orders, stock, and notifications isn't a microservice - it's a mini-monolith.
Fault isolation ensures that a failure in one service doesn't cause a cascading collapse of the entire system. Patterns like circuit breaker, retry, and bulkhead are standard resilience recommendations, as confirmed by an overview of communication patterns and practices.
Three practical warnings for preventing a "distributed monolith":
- Never share the same database between two services, even if it initially seems convenient.
- Avoid chained synchronous calls (A calls B, which calls C, which calls D) - this creates fragile dependencies and lengthens response time.
- Define service boundaries by business function, not by technical layer (not "database service," but "order service").
Which technologies and components do you need for a reliable system?
Microservices architecture requires infrastructure that isn't needed in a monolith. Each of the components below solves a specific problem that arises once you split an application into ten or a hundred independent parts.

| Component | Tool / example | Role in the system |
|---|---|---|
| API Gateway | Kong | A single entry point, routing, authentication, rate limiting |
| Message queue | RabbitMQ, Apache Kafka | Asynchronous communication, decoupling services |
| Orchestration | Kubernetes | Container management, automatic scaling, health checks |
| Containerization | Docker | Packaging a service with all its dependencies |
| Identity and access | Keycloak, OAuth2/OpenID Connect | Centralized authentication and authorization |
| Service discovery | Consul, Kubernetes DNS | Dynamically finding service addresses |
| Configuration | Kubernetes ConfigMap, Vault | Centralized configuration with no redeployment needed |
Kong as the API Gateway takes on the role a single entry-point controller plays in a monolith: it routes traffic to the right services, verifies tokens, and logs requests. Without it, every service would need to manage these cross-cutting concerns on its own.
RabbitMQ suits messages where delivery order and guaranteed processing matter. Apache Kafka is the better choice for high data throughput and when you need the ability to replay past messages, for example for analytics or audit trails.
Keycloak, together with OAuth2 and OpenID Connect, provides centralized authentication: services don't manage passwords - they verify tokens issued by Keycloak. This significantly reduces the attack surface and simplifies access management, as confirmed by a regional example using Kong and Keycloak.
Expert tip: Plan for service discovery, an API Gateway, and centralized authentication already at the initial system design stage. Adding these layers later, once you already have many services, is significantly more expensive and riskier.
What do you gain, and what do you pay for, with microservices architecture?
Microservices bring real advantages, but each one comes with a cost. Understanding this trade-off is essential for justifying the decision on business grounds.
The main advantages are independent scaling of individual functions, faster development since teams work in parallel without blocking each other, technological freedom in choosing languages and databases, and easier rollout of changes without risking the entire system. Data on the importance of microservices in organizations shows that organizations attribute an important role to microservices in application modernization, while also highlighting challenges in achieving sustained success at large-scale rollout.
| Dimension | Advantages | Trade-offs |
|---|---|---|
| Development | Parallel teams, independent cycles | More complex testing, API versioning |
| Operations | Independent scaling, fault isolation | Requires DevOps maturity, monitoring, CI/CD |
| Costs | Cloud cost optimization per function | Higher upfront infrastructure and development costs |
| Time to deploy | Faster deployment of individual services | Longer time to a first production version |
| Organization | Clear team ownership | Coordination needed between teams (API contracts) |
Gartner's industry perspective confirms that engineering organizations are finding success with microservices, while also flagging challenges with large-scale rollout. The academic review likewise finds that operating costs for microservices are higher and require mature DevOps processes for automation and stability.
Microservices are business-justified when a team has at least 5-8 developers, when the business domain contains clearly separable contexts, and when the system's expected growth means a monolithic architecture would become a bottleneck within 12-18 months. For web application scalability, the microservices approach is one of the proven patterns, but not the only one.
What are the main challenges, and how do you solve them in practice?
Microservices shift complexity out of the code and into infrastructure and operations. Here are four areas where teams most often run into trouble.
Observability is significantly more demanding in a distributed system than in a monolith. When a request travels through five services, you need to know which one is slow or broken. The standard approach involves three pillars: distributed tracing (OpenTelemetry, Jaeger), centralized logs (the ELK stack or Loki), and metrics (Prometheus, Grafana). Setting up automated testing and monitoring before decomposing a monolith at scale is advice that experts consistently repeat.
Testing becomes more complex, since you need to verify not just individual services, but the contracts between them. Consumer-driven contract testing (the Pact tool) ensures that a change in one service doesn't break its consumers. For integration tests, Testcontainers is a practical tool that spins up real dependencies (databases, message queues) in Docker containers during testing.
Data consistency is one of the hardest problems. Once every service has its own database, distributed transactions aren't possible in the classic sense. The Saga pattern solves this with a sequence of local transactions and compensating actions in case of failure. Eventual consistency is acceptable for most business cases, where a short synchronization delay doesn't cause business harm.
Security requires a centralized approach. OAuth2 and OpenID Connect through Keycloak ensure that every service verifies tokens against a central authority, instead of each service managing authentication on its own. The API Gateway (Kong) is the natural place to verify tokens before forwarding requests to services. You can find more on security practices for business systems in the overview of security trends for business web systems.
Expert tip: Before decomposing a monolith, set up distributed tracing with OpenTelemetry. Without it, you'll be blind to the causes of errors in production, and diagnostics will take many times longer than the fix itself.

How to safely deploy microservices to production?
Deploying microservices requires automated processes that reduce risk with every change. Manual deployment across ten or more services isn't sustainable.
Standard deployment patterns include:
- Blue/green deployment: parallel production environments; traffic switches to the new version only after successful verification.
- Canary deployment: the new version receives a small share of traffic (e.g. 5%), then gradually increases as metrics stay healthy.
- Rolling update: Kubernetes gradually replaces old pods with new ones, with no downtime.
- GitOps: the state of the infrastructure is defined in a Git repository; tools like ArgoCD or Flux ensure the production environment matches the repository.
A CI/CD pipeline for microservices needs to include the following steps:
- Building and testing the code (unit, integration, contracts)
- Building the Docker image and pushing it to the image registry
- Scanning the image for security vulnerabilities
- Deploying to a test environment and running end-to-end tests
- Gradual rollout to production with automatic rollback on failure
Before going into production, check this list:
- Every service has a health check (liveness and readiness probes in Kubernetes)
- SLIs and SLOs are defined (e.g. 99.9% availability, response time under 200 ms)
- Centralized monitoring with alerts is set up
- Rollback is tested and automated
- Secrets (passwords, keys) are stored in a dedicated vault (Vault, Kubernetes Secrets)
- Network policies restrict inter-service communication to the minimum necessary
When and how to move from a monolith to microservices?
Moving away from a monolith isn't a one-off project - it's a gradual process. Warnings about transitioning too early are a recurring theme in the expert literature: teams that split a system apart before establishing automated tests and monitoring often end up with a system that's more expensive and less stable.
Before you start, check your organizational and technical prerequisites:
- A readiness assessment: does the team have experience with Docker, CI/CD, and monitoring? Are there automated tests that cover at least the key paths?
- Identifying bounded contexts: which business functions are clearly separable? Where are the boundaries that business experts themselves recognize?
- Choosing the first function to extract: pick a service with clear boundaries, low dependency on the rest of the system, and high value from independent scaling.
- The strangler fig pattern: instead of replacing the monolith all at once, gradually "wrap" individual functions with new services. The monolith stays operational until every function has been migrated.
- Building the system's skeleton: first set up all the containers, communication paths, and infrastructure, then implement the business logic of the services.
- Incremental decomposition: only extract the next service once the previous one is stable in production.
The typical timeline for migrating a mid-sized system (5-15 functional modules) is 6-18 months, depending on existing test coverage and the team's DevOps maturity. Costs are significantly higher than maintaining a monolith in the short term, but they pay off for systems that require frequent scaling or parallel development.
What does microservices architecture look like in practice?
A thesis from FER documents the architecture of a construction equipment rental system, one of the few publicly available regional examples with technology decisions described in detail. The example shows four microservices with the following components:
- Kong as the API Gateway for centralized routing and security verification of all requests
- RabbitMQ as the message queue for asynchronous communication between services (e.g. notifications on a booking)
- Keycloak for centralized authentication with OAuth2/OpenID Connect
- Docker for packaging each service with all its dependencies
- Kubernetes for orchestrating and managing containers
The authors chose asynchronous communication through RabbitMQ for processes that don't require an immediate response, and synchronous REST communication for queries where response time is critical. Each service has its own database, ensuring independence in deployment.
The implementation approach followed the "skeleton first" recommendation: they first set up all the containers and communication paths, and only then implemented the business logic. This approach reduces the dependency and versioning problems that otherwise arise when a team builds services in parallel.
The challenges the authors highlighted are typical of microservices projects: managing dependencies between services during development, API versioning, and the operational complexity of setting up the entire environment for local development. Similar experiences are documented in examples of e-commerce systems using Apache Kafka, Docker, and Kubernetes, where the same patterns and the same challenges show up.
Are microservices the right choice for your project?
The answer depends on three factors: team size, domain complexity, and business requirements around scaling.
Microservices make sense when:
- The team has at least 5-8 developers and is organized into separate teams by domain
- The system has clearly separable business functions with different scaling requirements
- You expect rapid growth or frequent addition of new features
- The team already has a handle on Docker, CI/CD, and the basics of monitoring
A custom-built monolith is the better choice when:
- You're building an MVP or an early-stage product where requirements change quickly
- The team is smaller than 5 developers, or lacks DevOps experience
- The domain isn't complex enough to justify the operating costs
Next steps for those considering a transition:
- Carry out a bounded contexts analysis in your domain (a workshop using DDD techniques)
- Check the team's DevOps maturity: do you have automated tests and CI/CD?
- Build a small PoC with one extracted service before committing to a full migration
- Estimate cloud infrastructure costs for the target architecture
For deciding between a custom-built solution and standard platforms, it's worth reviewing when a custom-built web application is the right choice.
The Moxy-web perspective: what we've learned about architecture decisions
Microservices are often sold as a one-size-fits-all solution. In practice, though, we find that most companies who come to us asking for microservices architecture actually need a well-designed monolith with clear modules and a solid CI/CD pipeline. That's not a compromise - it's a smart decision.
When a project genuinely justifies microservices, discipline in defining service boundaries is essential. Teams that split a system along technical layers ("frontend service," "backend service," "database service") don't end up with microservices - they end up with a distributed monolith carrying the downsides of both worlds. Real microservices follow business functions, not technical abstractions.
What genuinely fascinates me about this field is the gap between theory and production reality. Patterns like circuit breaker and saga look elegant on paper, but they require discipline in implementation and a culture where the team understands why those patterns are there. Without that culture, they become just another layer of code nobody understands.
My recommendation for any team considering the transition: build observability first, then automate testing, and only then start decomposing. The order isn't arbitrary. Without the first two steps, you'll be blind in production, and every bug will take three times as long to diagnose.
Moxy-web helps you plan and build your architecture
Microservices architecture delivers real value, but it requires an experienced partner who knows when to recommend it and when not to. At Moxy-web, we start with an analysis of your domain and technical requirements, not a default answer. If microservices aren't the right step, we'll tell you honestly and propose an architecture that fits your situation.
For projects where the microservices approach is justified, we offer the whole process: from bounded contexts analysis and a PoC through to development, hosting, and long-term technical support. Our approach is built on a gradual transition that reduces risk and keeps the system stable during migration.
Get in touch for a free preliminary analysis of your architecture. Let's assess together whether microservices are the right step for your project, and figure out where to start. Visit Moxy-web and describe your challenge to us.
Sources
For a deeper dive into individual topics, we recommend the following resources:
- Microservices architecture (FOI repository)
- Microservices architecture in the example of a construction equipment rental company (FER)
- Architecture of modern web applications - Part 5: Microservices architecture - design and challenges (ITNetwork)
- Gartner: microservices architecture - have engineering organizations found success
- Statista: importance of microservices for organizations
Frequently asked questions
What is microservices architecture in one sentence?
Microservices architecture breaks an application down into small, independently deployed services, where each covers a single business function and communicates through clearly defined interfaces.
When is a monolith a better choice than microservices?
A monolith is the better choice for smaller teams (up to 5 developers), MVPs, and projects where the domain isn't complex enough to justify the operating costs of a distributed system.
Which tools are essential for a production microservices architecture?
The minimum toolkit includes Docker for containerization, Kubernetes for orchestration, an API Gateway (e.g. Kong), centralized authentication (Keycloak with OAuth2), and distributed tracing (OpenTelemetry).
How do you approach migrating from a monolith to microservices?
The recommended approach is the strangler fig pattern: gradually extract individual business functions into separate services while the monolith stays operational. Set up automated tests and monitoring before you start.
How does Moxy-web help with the architecture decision?
Moxy-web carries out a preliminary analysis of your domain and technical requirements, recommends the appropriate architecture (monolith or microservices), and, if needed, guides the entire process from PoC to a production system with long-term support.
Recommended