Insights into Company
← Spring Boot

Microservices

01 What is microservices architecture?

Solution and explanation

Solution:

Suppose a large job portal contains:

  • User management
  • Company management
  • Job management
  • Applications
  • Interviews
  • Notifications
  • Payments
  • Search
  • Analytics

Instead of putting everything into one independently deployable service, business capabilities can be separated.

Example:

Identity Service Company Service Job Service Application Service Interview Service Notification Service Payment Service Analytics Service

Suppose 5 million users search jobs every day.

The Job Search functionality may need much more capacity than the interview service.

With independently deployable services, job search can be scaled separately.

However, microservices introduce additional problems:

  • Network failures
  • Distributed tracing
  • Service discovery
  • Data consistency
  • Message delivery
  • Deployment complexity
  • Monitoring
  • Authentication between services

Therefore microservices are not simply "many Spring Boot projects".

They require clear ownership and communication boundaries.

Run this example
        Client
           |
        API Gateway
           |
           +---- Identity Service
           |
           +---- Company Service
           |
           +---- Job Service
           |
           +---- Application Service
           |
           +---- Interview Service
           |
           +---- Notification Service
           |
           +---- Analytics Service
Hands-on challenge

Define service boundaries for the job portal and identify which service owns application status.

Quick check

Which statement is correct?

02 What is an API Gateway?

Solution and explanation

Solution:

The API Gateway is normally the entry point between clients and backend services.

Instead of React directly calling:

user-service job-service application-service company-service

the frontend can call:

api.example.com

The gateway routes requests.

Example:

GET /api/jobs

v Job Service

POST /api/applications

v Application Service

GET /api/companies/100

v Company Service

The gateway can also participate in:

  • Authentication integration
  • Rate limiting
  • Routing
  • Request correlation
  • Logging
  • TLS termination
  • Header forwarding

Business rules such as "whether candidate can apply to this job" should remain inside the Application Service.

The gateway should not become a giant business-logic service.

Run this example
        spring:
          cloud:
            gateway:
              routes:

                - id: job-service
                  uri: lb://JOB-SERVICE
                  predicates:
                    - Path=/api/jobs/**

                - id: application-service
                  uri: lb://APPLICATION-SERVICE
                  predicates:
                    - Path=/api/applications/**

                - id: company-service
                  uri: lb://COMPANY-SERVICE
                  predicates:
                    - Path=/api/companies/**
Hands-on challenge

Route jobs, applications and company requests to separate Spring Boot services.

Quick check

Which statement is correct?

03 What is service discovery?

Solution and explanation

  • Solution:
  • Imagine Job Service has three running instances:
  • job-service-1
  • job-service-2
  • job-service-3
  • The IP address of each instance can change.
  • A client should not permanently store:
  • http://10.10.20.31:8080
  • Instead, it can call:
  • http://job-service/api/jobs
  • The platform resolves the logical service name to available instances.
  • In Kubernetes, Services and DNS commonly provide this capability.
  • The important idea is:
  • Client knows the service name.
  • Infrastructure knows where healthy instances currently exist.
  • When one instance fails, traffic can be sent to another healthy instance.
Run this example
        @RestController
        @RequestMapping("/api/jobs")
        public class JobController {

            @GetMapping
            public List<JobDto> jobs() {
                return jobService.findJobs();
            }
        }

        // Internal logical destination:
        //
        // http://job-service/api/jobs
Hands-on challenge

Run three Job Service instances and route requests through the logical service name.

Quick check

Which statement is correct?

04 What is OpenFeign?

Solution and explanation

Solution:

Suppose Application Service needs company information.

Without Feign, developers repeatedly write HTTP client code.

With OpenFeign, the remote API can be represented as a Java interface.

Example:

Application Service:

GET /applications/100

needs:

GET /companies/50

The Feign client performs the HTTP call.

However, Feign does not remove network failure.

Production configuration still needs:

  • Connect timeout
  • Read timeout
  • Error handling
  • Retry policy where safe
  • Circuit breaker where appropriate
  • Authentication between services
Run this example
        @FeignClient(name = "company-service")
        public interface CompanyClient {

            @GetMapping("/api/companies/{id}")
            CompanyDto findCompany(
                @PathVariable("id") Long id
            );
        }

        @Service
        public class ApplicationService {

            private final CompanyClient companyClient;

            public ApplicationService(
                CompanyClient companyClient
            ) {
                this.companyClient = companyClient;
            }

            public CompanyDto getCompany(Long companyId) {

                return companyClient.findCompany(companyId);
            }
        }
Hands-on challenge

Create a Feign client from Application Service to Company Service and configure timeouts.

Quick check

Which statement is correct?

05 What is a circuit breaker?

Solution and explanation

  • Solution:
  • Suppose Application Service calls Company Service.
  • Normally:
  • Application Service
  • |
  • v
  • Company Service
  • |
  • v
  • Database
  • Now Company Service becomes unavailable.
  • If Application Service continues making thousands of requests:
  • Request 1 -> timeout
  • Request 2 -> timeout
  • Request 3 -> timeout
  • ...
  • Request 100000 -> timeout
  • Threads can become exhausted.
  • This can cause failure to spread to other services.
  • A circuit breaker changes this behavior.
  • Closed:
  • Requests are allowed.
  • If failures exceed a threshold:
  • Open:
  • Requests fail fast without repeatedly calling the unhealthy service.
  • After a waiting period:
  • Half-open:
  • A limited request is allowed to test recovery.
  • If successful:
  • Closed.
  • If unsuccessful:
  • Open again.
Run this example
        @CircuitBreaker(
            name = "companyService",
            fallbackMethod = "companyFallback"
        )
        public CompanyDto getCompany(Long id) {

            return companyClient.findCompany(id);
        }

        public CompanyDto companyFallback(
                Long id,
                Throwable exception) {

            return CompanyDto.unavailable(id);
        }
Hands-on challenge

Simulate Company Service timeouts and observe CLOSED -> OPEN -> HALF_OPEN -> CLOSED.

Quick check

Which statement is correct?