Featured resource
Forrester Wave Report 2025
Pluralsight named a Leader in the Forrester Wave™

Our tech skill development platform earned the highest scores possible across 11 criteria.

Learn more
  • Labs icon Lab
  • Core Tech
Labs

Guided: Transitioning from Monolith to Microservices

In this hands-on Code Lab, you will break down a monolithic application into independent microservices. Using an e-commerce example from Globomantics, you will identify service boundaries, extract key functionality, and enable communication using REST APIs. By the end, you will have a working setup of services that run and interact independently.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 58m
Published
Clock icon May 22, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Lab Overview

    In this hands-on lab, you will work as a backend engineer at Globomantics, a growing e-commerce company. The current system is a monolithic application that combines all business domains such as product catalog, user management, and order processing into a single codebase. As the company scales, this architecture presents challenges in agility, scalability, and maintainability.

    Your task is to decompose this monolith into independent microservices. Each service will run separately, communicate with others using REST APIs, and function independently.

    By the end of this lab, you will have broken down the monolith and established inter-service communication through a guided, step-by-step approach that reflects a real-world migration process.

    To help you focus on understanding the migration steps rather than setting up files from scratch, scaffolding has already been provided in each microservice. Blank files are in place to simplify the process, you can copy the relevant code from the monolith into the corresponding files within each microservice.

    info>If you get stuck on a task, you can view the solution in the solution folder in your file tree, or click the Task Solution link at the bottom of each task after you've attempted it.

  2. Challenge

    Understand the Monolith Architecture

    In this step, you will examine the current structure of the monolithic application and understand the limitations that led to the decision to transition to microservices.

    Monolithic Architecture:

    You will observe that a monolithic architecture means the entire application is built and deployed as a single unit. All features such as user management, product catalog, and order processing reside in one codebase and run within the same runtime.

    For example, the Globomantics monolithic application includes:

    • A single Spring Boot application with one @SpringBootApplication main class running on a port (e.g., 8001).
    • Package structure combining all domains within the same project.
    • Shared resources, such as a common set of model classes (User, Product, and Order) used across all features within the monolithic application.
    • Controllers such as UserController, ProductController, and OrderController, all exposed through the same base URL (e.g., http://localhost:8001/users, /products, /orders).

    The structure of monolith:

    monolith-app/
    ├── src/main/java/com/globomantics/
    │   ├── MonolithApplication.java
    │   ├── controller/
    │   │   ├── OrderController.java
    │   │   ├── ProductController.java
    │   │   └── UserController.java
    │   ├── model/
    │   │   ├── Order.java
    │   │   ├── OrderDetail.java
    │   │   ├── Product.java
    │   │   └── User.java
    │   └── service/
    │       ├── OrderService.java
    │       ├── ProductService.java
    │       └── UserService.java
    

    You will see that all components are tightly coupled and run as a single process. Any change or deployment affects the entire application.

    Now you'll start the application and understand the APIs which it offers.

    Limitations of the Monolith:

    As you explore further, you will identify several drawbacks with this architecture:

    • Limited Scalability: You cannot scale individual modules independently. Even if only the product catalog faces high demand, you will have to scale the entire application, which is inefficient.
    • Slower Development and Deployment: A small change in one area, such as user registration, requires rebuilding and redeploying the whole application. This increases coordination overhead among teams.
    • Fault Isolation: A single failure, for example in the OrderController, can crash the entire application since all components share the same runtime.
    • Technology Lock-in: You cannot mix and match technologies easily. Every part of the application must use the same tech stack.
    • Long-Term Maintenance Issues: As the codebase grows, it becomes increasingly difficult to manage. Build times, testing scope, and risk of regressions all increase.

    To overcome these challenges, the monolith is broken down into smaller, independently deployable services. Globomantics is moving to a microservices architecture, where each service is dedicated to a specific business capability and can be developed, deployed, and scaled independently. --- You now understand how the Globomantics monolithic application is structured and what limitations it introduces. You will proceed to identify logical service boundaries in the next step.

  3. Challenge

    Identify Service Boundaries

    In this step, you identify logical service boundaries in the monolithic application to guide its decomposition into microservices.

    You will analyze the functionality within the monolith and group related features into distinct business domains. A good approach is to align these groupings with business capabilities or bounded contexts. In the Globomantics application, you clearly see three primary domains: Users, Products, and Orders.

    Define the following microservices:

    • User Service: handles user registration, login, and profile management. It owns all user-related logic and data.

    • Product Service: manages the product catalog, including inventory, pricing, and descriptions.

    • Order Service: processes customer orders, manages order history, and interacts with the other two services to complete transactions.

    Each service is aligned with a specific business function, making it easier to maintain, scale, and deploy independently. For example, product updates can now be handled without affecting the user or order systems.

    In the monolith, the order functionality likely accessed product and user data directly through shared repositories. As part of the microservices transition, shift this interaction to service-to-service communication using REST APIs. Each service will now be responsible for its own data and expose the necessary endpoints to other services.

    It's best to avoid using a shared database. Instead, assign data ownership to each microservice. While in this lab the persistence is simulated with in-memory collections, the principle remains important for avoiding tight coupling.


    You have successfully identified the domain boundaries within the monolithic application and outlined the responsibilities for three microservices: User, Product, and Order. In the next step, you will begin extracting the Product service into its own standalone microservice.

  4. Challenge

    Extract Product Service

    In this step you will extract the product related functionality from the monolith into a standalone microservice product-service. Navigate to the product-service/src/main/java/com/globomantics folder in the FileTree section.

    The ProductServiceApplication class serves as the new entry point for the extracted product service, separate from the monolith.

    To run this service independently, assign it a unique port. Configure the product service to run on port 9001.

    | Service | Port | |------------------|--------| | Monolith | 8001 | | Product Service | 9001 | | User Service | 9002 | | Order Service | 9003 | info> For simplicity, a plain class with in-memory data structures is used to store data. In real-world applications, this would typically be a JPA @Entity with appropriate annotations, and each service might use its own dedicated database based on the requirements. Next, you will set up dedicated Controller and Service classes for the Product service by copying them from the monolith.

    The ProductService class contains the business logic for product-related operations and will now be part of the standalone product-service. The ProductController exposes REST endpoints for managing products and will now operate independently within the product-service. Great job!

    Now that you've successfully created your first microservice, you'll move on to migrate the User and Order services next.

  5. Challenge

    Extract User Service

    You will now extract the user-service from the monolith.

    Similar to the previous step, update the port for User Service to 9002.

    In this step, you’ve successfully extracted the User Service into its own standalone microservice.

    Next, you will extract the Order Service. Unlike the previous services, this step will also include inter-service communication, where the Order Service will interact with the Product and User services to fetch additional details.

  6. Challenge

    Extract Order Service

    In this step, you'll extract the Order service and also configure the order service to communicate with Product and User service.

    Next you will copy the contents of Controller , Model and Service class files. In addition to the Order.java model, you will also need to include User.java and Product.java to represent the responses received from the respective microservices.

    The OrderDetail.java model will be used to structure the final response returned by the Order Service API. Now that you've copied all the classes, the final step is to set up inter-process communication, which you'll complete in the next step.

  7. Challenge

    Enable Inter-Service Communication

    In this step you will use RestTemplate in the order-service to fetch data from the user-service and product-service using their respective URLs.

    RestTemplate

    RestTemplate is a synchronous client provided by Spring for making HTTP requests to external services. In a microservices architecture, it enables one service to call another over HTTP.

    The RestTemplate has been configured in the AppConfig.java file and is available for use throughout the project. You will enhance OrderService.java to enable inter-service communication. Instead of returning just the raw order data, the Order Service will call the User Service and Product Service to fetch additional details based on the userId and productId in the order.

    Here’s how you can fetch the user details using RestTemplate:

    User user = restTemplate.getForObject(userServiceUrl + "/" + order.getUserId(), User.class);
    

    You’ll use a similar approach to retrieve product details. These responses will be combined into an OrderDetail object, which will be returned by the API.

    Now you will first inject the RestTemplate in the Order Service.

    The @Value annotation in Spring is used to inject values from the application's configuration file i.e application.properties directly into fields.

    Next you will replace the Product and User Services with their respective URLs. Now that the service URLs have been injected into the appropriate fields, you will use them to call the respective microservices. Great work!
    The Order microservice is now set up. In the next step, you’ll verify its API endpoints to ensure everything is working as expected.

  8. Challenge

    Test and Verify the Microservices Setup

    Now that all three services (product-service, user-service, and order-service) are configured to run independently, you will test their endpoints to verify they are working as expected and communicating correctly.

    Now you will ensure that all services are started. You should have five terminal windows open:

    • Terminal 1: Monolith (8001)
    • Terminal 2: Product Service (9001)
    • Terminal 3: User Service (9002)
    • Terminal 4: Order Service (9003)
    • Terminal 5: For testing with curl

    Start each service in its respective terminal. This setup lets you manage and test the services independently.

    info> You can keep the monolith stopped as you only want to test the microservices. To stop any running service, go to its terminal window and press CTRL+C. Great work !

    This confirms that your microservices are functioning independently and are able to interact with each other successfully.

  9. Challenge

    Conclusion and Next Steps

    Conclusion

    You successfully transitioned a monolithic Spring Boot application into a set of independent microservices. Along the way, you identified domain boundaries, extracted services, implemented full CRUD operations, and enabled inter-service communication using RestTemplate.

    By completing this lab, you demonstrated how to:

    • Analyze and break down a monolithic architecture
    • Design and implement domain-driven microservices
    • Enable REST-based communication between services

    Next Steps

    • You can now add database support (e.g., H2, PostgreSQL) to each service for persistent storage.
    • Explore using API gateways (e.g., Spring Cloud Gateway) to centralize request routing.
    • Implement security between services using OAuth2 or JWT.
    • Consider replacing RestTemplate with WebClient or using service discovery tools like Eureka and Spring Cloud.
    • Add unit and integration tests to each service for production readiness.

    This foundational setup prepares you to build scalable, maintainable, and cloud-ready microservice applications.

Amar Sonwani is a software architect with more than twelve years of experience. He has worked extensively in the financial industry and has expertise in building scalable applications.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.