Your First Microservice
Your First Microservice
A microservice is a small, independently deployable process that owns exactly one business capability, exposes that capability over a network boundary, and can be built, tested, and released without coordination with other services. That definition sounds abstract until you actually write one — so that is exactly what this lesson does.
You already know Spring Boot. A microservice built with Spring Boot is, at its core, a perfectly normal Spring Boot application. What makes it a microservice is a set of design decisions, not a different framework.
The Mental Shift: From Monolith to Single-Responsibility Service
In a monolith, a single deployable artifact contains the order logic, the user logic, the inventory logic, and everything in between. In a microservices architecture, each of those is its own deployable unit. This lesson builds the Product Catalogue Service — a service that does exactly one thing: manage product data. It does not handle orders, users, or anything else.
Project Setup with Spring Initializr
Go to start.spring.io (or use your IDE's Spring Initializr integration) and create a project with these coordinates:
- Group:
com.example - Artifact:
product-service - Java: 21
- Spring Boot: 3.3.x
- Dependencies: Spring Web, Spring Data JPA, H2 Database, Spring Boot Actuator, Validation
Every one of those choices is deliberate. Spring Web gives us the embedded Tomcat and the REST layer. Spring Data JPA and H2 let us persist data without standing up an external database for this first example. Actuator provides the health-check endpoints that orchestration platforms (Kubernetes, ECS) need. Validation lets us enforce API contracts at the boundary.
application.yml — Service Identity First
Rename application.properties to application.yml and give the service a clear identity:
The spring.application.name property is not cosmetic. Service-discovery registries (Eureka, Consul), distributed tracing systems (Micrometer Tracing / Zipkin), and log aggregation pipelines all use this name to identify which service produced a given record. Set it correctly from day one.
The Domain Model
Keep it minimal — a Product with an ID, name, price, and stock count:
Notice that BigDecimal is used for price, not double. Floating-point types cannot represent decimal fractions exactly, which produces rounding errors when you add prices — a serious bug in any financial context.
The Repository
Spring Data JPA eliminates boilerplate. Declare an interface; Spring generates the implementation at startup:
The Service Layer
Keep business logic out of controllers. The service layer enforces rules, coordinates transactions, and is the boundary your unit tests target:
The REST Controller
The controller is deliberately thin. It translates HTTP into service calls and service results into HTTP responses:
Error Handling at the Service Boundary
A microservice is a network citizen. When a caller asks for product 999 and it does not exist, returning a raw Spring 500 page is wrong. Map domain exceptions to appropriate HTTP status codes with a @ControllerAdvice:
Verifying the Service Is Alive
Run the service with ./mvnw spring-boot:run. Spring Boot Actuator exposes GET /actuator/health automatically. In production, your container orchestrator calls this endpoint every few seconds; if it returns anything other than {"status":"UP"}, the instance is taken out of the load balancer rotation and replaced. Get into the habit of checking it locally:
The database component is included because Actuator detects the H2 DataSource and probes it automatically.
What Makes This a Microservice, Not Just a REST App
At this point you have a working REST service. What earns it the "microservice" label is everything you deliberately did not put in it:
- No user authentication logic — that belongs to an Identity Service.
- No order processing — that belongs to an Order Service.
- Its own database schema, owned exclusively by this service.
- A health endpoint ready for an orchestrator.
- An application name that will appear in logs and traces.
The upcoming lessons will connect this service to others, add resilience patterns, and deploy it in a container. The foundation you built here — one responsibility, clear API, structured errors, health endpoint — is what everything else builds on.