Back to all Articles
Karol Andruszków
Karol is a serial entrepreneur who has successfully founded 4 startup companies. With over 11 years of experience in Banking, Financial, IT and eCommerce sector, Karol has provided expert advice to more than 500 companies across 15 countries, including Poland, the USA, the UK, and Portugal.
How to Create Microservices Architecture - Our Experience
Updated:
Thu, Apr 17
Reading time: 8 minutes

Microservices are still highly relevant in 2025. Hovever, the overall hype has settled, giving way to a more pragmatic approach.
Gone are the days of blindly breaking everything into tiny services. Companies now recognize that microservices introduce significant complexity and should only be adopted when they truly align with business needs.
As organizations refine their microservices strategies, many are turning to strategic partnerships to enhance profitability and efficiency.
Gone are the days of blindly breaking everything into tiny services. Companies now recognize that microservices introduce significant complexity and should only be adopted when they truly align with business needs.
As organizations refine their microservices strategies, many are turning to strategic partnerships to enhance profitability and efficiency.
In the microservices architecture landscape, leading companies are increasingly forming strategic partnerships to boost profitability. These collaborations involve various entities working together to design, develop, deploy, and maintain microservices-based systems
As stated in the Microservices Architecture Market Report 2025
If you think it's time for your organization to adopt microservices, this article is for you.
At Ulan Software, we share our firsthand experience of building a microservices architecture for one of our projects.
Read this article to learn what worked, what didn’t, and the key lessons we learned along the way.
At Ulan Software, we share our firsthand experience of building a microservices architecture for one of our projects.
Read this article to learn what worked, what didn’t, and the key lessons we learned along the way.
Why Have We Decided to Write About Microservices?
While numerous articles discuss microservices architecture, we decided to share our hands-on experience implementing microservices framework for our customer - BOWWE.com
BOWWE is a very advanced and easy-to-use website builder with plenty of different functionalities that help businesses succeed online.
The product is very complex due to many additional features like, e.g., booking engine, portfolio engine, drag and drop website builder. Building all those features in monolithic application architecture or in an application as a set of independent components could be very difficult.
So we decided to implement microservice architecture from the very beginning. Using microservices permits us to work simultaneously on several different features, speed up development, and cut delivery time.
BOWWE is a very advanced and easy-to-use website builder with plenty of different functionalities that help businesses succeed online.
The product is very complex due to many additional features like, e.g., booking engine, portfolio engine, drag and drop website builder. Building all those features in monolithic application architecture or in an application as a set of independent components could be very difficult.
So we decided to implement microservice architecture from the very beginning. Using microservices permits us to work simultaneously on several different features, speed up development, and cut delivery time.
What Is Microservices Architecture?
Microservices architecture - is a modular approach to software development, consisting of loosely coupled, independently deployable services. Each service handles a specific functionality and can be developed, deployed, and scaled independently. These services communicate with each other through lightweight protocols, enabling seamless integration and functionality across multiple components of the architecture.
This design pattern improves scalability, performance, and development speed, making it ideal for large, complex applications. It also allows an organization to evolve its technology stack.
However, you need to be conscious that microservices application might create additional problems with, e.g., maintenance, and debugging. Especially for smaller projects or teams lacking maturity.
However, you need to be conscious that microservices application might create additional problems with, e.g., maintenance, and debugging. Especially for smaller projects or teams lacking maturity.
The Microservices Architecture Patterns Step-by-Step
1. Decomposition approach
Available decomposition approaches:
Our approach:
We decomposed our service using decomposition by subdomain, which means that each subdomain corresponds to a different part of the business. We tried to avoid splitting the business relation set of functions between other services and making our developers easy to understand and manage. This way, services are loosely coupled.
E.g., our architecture embraces the following list of microservices:
Definitely, in this approach, you need to understand your business very well.
- Decompose by business capability
- Decompose by subdomain
- Self-contained
- Service Service per team
Our approach:
We decomposed our service using decomposition by subdomain, which means that each subdomain corresponds to a different part of the business. We tried to avoid splitting the business relation set of functions between other services and making our developers easy to understand and manage. This way, services are loosely coupled.
E.g., our architecture embraces the following list of microservices:
- Pages MS
- Domains and Users MS
- Products MS
- Orders MS
- Product Deliveries MS
- Payments MS
- Integrations and mapping MS
- SSR WebPage rendering MS
- Statistics MS
Definitely, in this approach, you need to understand your business very well.
A deep understanding of the business (domain, processes and workflows) is essential when decoupling architecture. This guarantees that services remain both cohesive and loosely coupled.
commented our CTO Wojciech Andruszkow
We thought about a Self-contained Service approach, but they are much harder to maintain in splitting business logic and responsibility. Same functions may be implemented in different services, which we want to avoid as much as possible.
An example of the structure of that service you can see in picture:

2. Data management
Available Data management approaches:
Our approach:
We chose a database per service approach, but we have one service which has a shared database. It was decomposed from other MS and is not temporal because there were many data dependencies.
Removing those dependencies would take too much time. So in the future, we are planning to do it, but there are another significant priorities at the moment.
In BOWWE, each MS has its own database, which is either MySQL, Cassandra, or Redis. We also use Redis as a distributed cache.
Such structures complicate situations when specific tasks demand access to two different databases owned by two other microservices. Sometimes tasks need to change multiple different databases to execute tasks.
In BOWWE, we have had such a type of problem, especially in ‘Orders MS’, which requires communication between products, payments, and delivery microservices.
We considered the CQRS approach, but for this time, it was additional effort and cost for us, so we decided to leave it as an option in the future in case of performance issues. An example of that databases structure you can see in picture above.
- Database per Service
- Shared database
- Saga
- API Composition
- CQRS
- Domain event
- Event sourcing
Our approach:
We chose a database per service approach, but we have one service which has a shared database. It was decomposed from other MS and is not temporal because there were many data dependencies.
Removing those dependencies would take too much time. So in the future, we are planning to do it, but there are another significant priorities at the moment.
In BOWWE, each MS has its own database, which is either MySQL, Cassandra, or Redis. We also use Redis as a distributed cache.
Such structures complicate situations when specific tasks demand access to two different databases owned by two other microservices. Sometimes tasks need to change multiple different databases to execute tasks.
In BOWWE, we have had such a type of problem, especially in ‘Orders MS’, which requires communication between products, payments, and delivery microservices.
We considered the CQRS approach, but for this time, it was additional effort and cost for us, so we decided to leave it as an option in the future in case of performance issues. An example of that databases structure you can see in picture above.
When you're dealing with microservices, things can get tricky when different services need to interact with their own databases. For example, if the 'Orders' microservice needs to coordinate with other services, managing those data interactions can become a real headache. That’s where patterns like Saga or API Composition can help
says our CTO Wojciech Andruszkow
In BOWWE, we have had such a type of problem, especially in ‘Orders MS’, which requires communication between products, payments, and delivery microservices.
We considered the CQRS approach, but for this time, it was additional effort and cost for us, so we decided to leave it as an option in the future in case of performance issues. An example of that databases structure you can see in picture above.
3. Testing
Service Component Test - we use the service Component Test by mocking external service calls. This approach is easier and cheaper. It doesn't require a cross-service test environment setup, but we can have some integration problems that our tests won't catch.
Consumer-driven Contract Test - we are using those kinds of tests to test integration with external services and ensure that their contract has not been changed. So, in that case, we are doing a Consumer-side contract test at the same time.
We are also using cypress for end-to-end and visual regression tests, which allows us to decrease the number of manual testing before each release and gives us better confidence that the functionality we release is working fine.
Consumer-driven Contract Test - we are using those kinds of tests to test integration with external services and ensure that their contract has not been changed. So, in that case, we are doing a Consumer-side contract test at the same time.
We are also using cypress for end-to-end and visual regression tests, which allows us to decrease the number of manual testing before each release and gives us better confidence that the functionality we release is working fine.
4. Deployment
Available Deployment patterns:
Our approach:
We are using the approach of having multiple services per host. Our services are running on dedicated servers. This is more cost-effective for us in comparison with hiring cloud DevOps infrastructure.
We are planning to run each service in a separate container. It will make our services more scalable and easier to configure.
An example of that approach you can see in picture:
- Multiple service instances per host
- Service instance per host
- Service instance per VM
- Service instance per Container
- Serverless deployment
- Service deployment platform
Our approach:
We are using the approach of having multiple services per host. Our services are running on dedicated servers. This is more cost-effective for us in comparison with hiring cloud DevOps infrastructure.
We are planning to run each service in a separate container. It will make our services more scalable and easier to configure.
An example of that approach you can see in picture:

5. Communication styles
Available Communication styles:
Our approach:
For communication, we are using RestAPI (an API gateway) and Apache Thrift. Apache Thrift is a framework with a cross-language code generator that helps us build faster communication between clients and services regardless of the used development languages.
In BOWWE, Apache Thrift is used for communication between services responsible for getting page data. We choose Apache Thrift because of better latency compared to Rest API and programming language independence.
Apache Thrift supports most of the languages, and our core services are written in Java and PHP. We also use REST APIs where latency is not so important and for our public API.
An example of that RestAPI communication structure you can see in picture:
- Remote Procedure Invocation
- Messaging
- Domain-specific protocol
- Idempotent Consumer
Our approach:
For communication, we are using RestAPI (an API gateway) and Apache Thrift. Apache Thrift is a framework with a cross-language code generator that helps us build faster communication between clients and services regardless of the used development languages.
In BOWWE, Apache Thrift is used for communication between services responsible for getting page data. We choose Apache Thrift because of better latency compared to Rest API and programming language independence.
Apache Thrift supports most of the languages, and our core services are written in Java and PHP. We also use REST APIs where latency is not so important and for our public API.
An example of that RestAPI communication structure you can see in picture:

6. Observability
Available Observability solutions:
Our approach:
None of the above.
Each service instance generates its logs and writes to a log file in a standardized format.
The log files contain errors, warnings, information, and debug messages. So far, this approach is good enough for us. In the future, we may start to use dedicated tools like, e.g., Splunk, Logstash, or Appdynamics.
Regarding observability, we can add that BOWWE possesses a dedicated microservice that delivers deep analytics about traffic and customer behavior to the owners of the websites. Tech stack of that microservice: Spring Boot uses the NoSql Cassandra database. In the future, we are thinking about introducing Apache Spark.
- Log aggregation
- Application metrics
- Audit logging
- Distributed tracing
- Exception tracking
- Health check API
- Log deployments and changes
Our approach:
None of the above.
Each service instance generates its logs and writes to a log file in a standardized format.
The log files contain errors, warnings, information, and debug messages. So far, this approach is good enough for us. In the future, we may start to use dedicated tools like, e.g., Splunk, Logstash, or Appdynamics.
Regarding observability, we can add that BOWWE possesses a dedicated microservice that delivers deep analytics about traffic and customer behavior to the owners of the websites. Tech stack of that microservice: Spring Boot uses the NoSql Cassandra database. In the future, we are thinking about introducing Apache Spark.
Key Takeaways from Building Microservices for BOWWE
Front-loaded effort - the initial design phase required significant time and resources, but it laid the groundwork for long-term scalability.
Parallel development - independent services enabled multiple teams to work simultaneously, accelerating feature delivery.
Scalability & flexibility - adding complex features like an e-commerce engine and web app builder would not have been feasible with a monolithic architecture.
Future proofing - the architecture allows us to adopt new technologies and scale services as business needs evolve.
Pros and Cons of Microservices Architecture
Like every architecture, the microservice architecture has its pros and cons, especially when compared with a typical, most popular, startup-loved monolithic architecture. Below are all the pros and cons regarding microservices architecture:
Benefits of Microservices:
- Services can use different technologies and test environments.
- Changes in one service don't impact others.
- Modern containerization tools like Kubernetes enable precise resource allocation for each service.
- Updates and fixes can be deployed without taking the entire application offline.
Challenges of Microservices:
- Designing the microservice architecture, selecting communication protocols, and defining database schemas require extensive planning.
- Separate teams for each service increase operational expenses.
- Distributed systems demand advanced tools like OpenTracing to replicate conditions and trace issues.
- Logs must be aggregated and analyzed to maintain observability across services.
However, we also turned to social listening on Reddit to see what the tech community has to say about their experience with microservices.
One developer pointed out that microservices "allow small teams to move fast in large organizations," enabling them to release features without the bottleneck of centralized approval processes.
Another user highlighted that microservices "help define contracts between systems, and therefore contracts between groups of engineers," making independent development and deployment much easier.
That said, many developers agree that jumping into microservices from day one isn’t always the best approach.
Starting from microservices is almost always a bad choice. It's like getting a very large and expensive house because 'you might have five kids
one Redditor wrote
Final Thoughts
From our experience, building microservices architecture from the very beginning in this particular project was a good decision. Definitely, in the beginning, we have spent a higher number of working hours on the architecture design of the solution, but later it was much easier to develop each functionality separately and manage a few development teams simultaneously.
At this point in the project life, adding such significant parts of code like e-commerce creator and later in the future web app builder would be impossible without this architecture.
If you're interested in learning more about this project read about it in our portfolio:
No-Code & Low Code Design Builder.
If you need help implementing a microservices architecture in your organization, check out our service Software Architecture Design ,
or feel free to reach out to us business@ulansoftware.com
At this point in the project life, adding such significant parts of code like e-commerce creator and later in the future web app builder would be impossible without this architecture.
If you're interested in learning more about this project read about it in our portfolio:
No-Code & Low Code Design Builder.
If you need help implementing a microservices architecture in your organization, check out our service Software Architecture Design ,
or feel free to reach out to us business@ulansoftware.com
Karol Andruszków
Karol is a serial entrepreneur who has successfully founded 4 startup companies. With over 11 years of experience in Banking, Financial, IT and eCommerce sector, Karol has provided expert advice to more than 500 companies across 15 countries, including Poland, the USA, the UK, and Portugal.
Table of Contents:
Why have we decided to write about microservices?
What is microservices architecture?
The microservices architecture patterns step-by-step
Key takeaways from building microservices for BOWWE
Pros and Cons of microservices architecture
Final thoughts
Recommended Articles
Tue, Apr 15
Build Custom Marketplace Software or Use Sharetribe? - an Ultimate Comparison
Compare building a custom marketplace vs using Sharetribe. Explore costs, scale, features, and long-term ROI—based on expert insight and real user feedback.
Mon, Apr 14
Marketplace Software Architecture Trends in 2025
Building or scaling a marketplace in 2025? Discover the latest marketplace software architecture trends—headless, composable, serverless, and AI-ready.
Mon, Apr 14
Comparing MEAN vs MERN vs Next.js and Node for a Marketplace Development
Compare MEAN, MERN, and Next.js + Node stacks for building modern marketplaces. Learn which tech stack fits your product, service, or rental platform in 2025.