Building Your First Microservice with Spring Boot
Modern enterprise software systems are no longer built as massive monolithic applications. Organizations today prefer microservices architecture because it improves scalability, deployment flexibility, fault isolation, and development velocity. Spring Boot has become one of the most widely adopted frameworks for building production-grade Java microservices because it simplifies configuration, reduces boilerplate code, and integrates seamlessly with cloud-native ecosystems.
In this complete guide, you will learn how to build your first microservice using Spring Boot from scratch. This tutorial goes far beyond a basic CRUD application. You will understand the internal architecture of microservices, request lifecycles, layered design principles, REST API best practices, validation, exception handling, observability, production deployment concerns, and enterprise engineering practices.
What You Will Learn
- What microservices architecture is
- How Spring Boot simplifies enterprise backend development
- How to create a production-ready Spring Boot project
- How REST APIs work internally
- How to build controllers, services, and repositories
- How dependency injection works in Spring
- How Spring Boot auto-configuration works
- How to connect microservices with databases
- How to validate requests
- How to handle exceptions globally
- How to configure application properties
- How to structure enterprise microservices
- How to debug Spring Boot applications
- How to monitor and scale services
- How production deployments work
- How to prepare for Spring Boot microservices interviews
Prerequisites
This guide is beginner-friendly, but basic Java knowledge will help you understand concepts faster.
- Basic Java programming
- Understanding of object-oriented programming
- Basic HTTP knowledge
- Java 17 or later installed
- Maven installed
- IDE such as IntelliJ IDEA or VS Code
What Is a Microservice?
A microservice is a small, independently deployable application focused on a specific business capability. Instead of building one giant application that handles everything, microservices split functionality into smaller services.
For example, an e-commerce platform may have:
- User Service
- Product Service
- Inventory Service
- Payment Service
- Notification Service
- Order Service
Each service can:
- Run independently
- Scale independently
- Have its own database
- Be deployed independently
- Use different technologies if needed
Monolith vs Microservices
| Feature | Monolith | Microservices |
|---|---|---|
| Deployment | Single deployment | Independent deployments |
| Scaling | Entire application | Individual services |
| Technology flexibility | Limited | High |
| Fault isolation | Poor | Better |
| Complexity | Lower initially | Higher operationally |
Microservice Architecture Diagram
+-------------------+
| API Gateway |
+---------+---------+
|
-----------------------------------------
| | |
+---------------+ +---------------+ +----------------+
| User Service | | Order Service | | Payment Service|
+-------+-------+ +-------+-------+ +--------+-------+
| | |
+-------v-------+ +-------v-------+ +--------v-------+
| User Database | | Order Database| | Payment DB |
+---------------+ +---------------+ +----------------+
Why Use Spring Boot for Microservices?
Spring Boot is built on top of the Spring Framework and dramatically simplifies enterprise Java development.
Traditional Spring applications required extensive XML configuration, manual dependency management, and complicated setup. Spring Boot removes that complexity using:
- Auto-configuration
- Embedded web servers
- Starter dependencies
- Production-ready monitoring
- Convention over configuration
Key Advantages
- Rapid development
- Minimal boilerplate
- Enterprise-grade ecosystem
- Cloud-native support
- Excellent community support
- Production observability
- Easy integration with databases and messaging systems
Understanding Spring Boot Internals
Before building the application, understanding how Spring Boot works internally is extremely important.
Spring Boot Startup Lifecycle
Main Method
|
v
SpringApplication.run()
|
v
Create Application Context
|
v
Component Scanning
|
v
Bean Creation
|
v
Dependency Injection
|
v
Auto Configuration
|
v
Embedded Tomcat Starts
|
v
Application Ready
What Is Dependency Injection?
Dependency Injection means Spring creates objects for you and injects required dependencies automatically.
Without dependency injection:
UserService service = new UserService();
With Spring Boot:
@Autowired
private UserService userService;
Spring manages object creation internally using the IoC container.
What Is IoC Container?
IoC stands for Inversion of Control. The Spring container manages:
- Object creation
- Object lifecycle
- Dependency injection
- Bean scopes
- Configuration
Creating Your First Spring Boot Project
Recommended Project Structure
user-service
|
+--- src
| |
| +--- main
| |
| +--- java
| | |
| | +--- com.example.userservice
| | |
| | +--- controller
| | +--- service
| | +--- repository
| | +--- entity
| | +--- dto
| | +--- exception
| |
| +--- resources
| |
| +--- application.yml
|
+--- pom.xml
Maven Dependencies
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
Main Application Class
package com.example.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
The @SpringBootApplication annotation combines:
- @Configuration
- @EnableAutoConfiguration
- @ComponentScan
Building Your First REST API
REST APIs are the communication backbone of microservices.
REST Request Flow
Client
|
v
Controller
|
v
Service Layer
|
v
Repository Layer
|
v
Database
Step 1: Create Entity
package com.example.userservice.entity;
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
public User() {
}
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Step 2: Create Repository
package com.example.userservice.repository;
import com.example.userservice.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
Spring Data JPA automatically provides CRUD methods.
Step 3: Create Service Layer
package com.example.userservice.service;
import com.example.userservice.entity.User;
import com.example.userservice.repository.UserRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
public User createUser(User user) {
return repository.save(user);
}
public List<User> getAllUsers() {
return repository.findAll();
}
public User getUserById(Long id) {
return repository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
}
}
Step 4: Create Controller
package com.example.userservice.controller;
import com.example.userservice.entity.User;
import com.example.userservice.service.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService service;
public UserController(UserService service) {
this.service = service;
}
@PostMapping
public User createUser(@RequestBody User user) {
return service.createUser(user);
}
@GetMapping
public List<User> getUsers() {
return service.getAllUsers();
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return service.getUserById(id);
}
}
Application Configuration
Spring Boot configuration is commonly stored in:
- application.properties
- application.yml
application.yml Example
server:
port: 8080
spring:
datasource:
url: jdbc:h2:mem:testdb
username: sa
password:
h2:
console:
enabled: true
jpa:
show-sql: true
hibernate:
ddl-auto: update
Why YAML Is Preferred
- Cleaner structure
- Hierarchical readability
- Easier environment separation
Understanding REST Endpoints
| HTTP Method | Purpose |
|---|---|
| GET | Fetch data |
| POST | Create data |
| PUT | Update data |
| DELETE | Delete data |
Sample Requests
POST /api/users
{
"name": "Naresh",
"email": "naresh@example.com"
}
GET /api/users
GET /api/users/1
Request Validation
Production APIs should never trust incoming data blindly.
DTO Example
package com.example.userservice.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
public class UserRequest {
@NotBlank(message = "Name is required")
private String name;
@Email(message = "Invalid email")
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Controller Validation
@PostMapping
public User createUser(@Valid @RequestBody UserRequest request) {
}
Validation prevents invalid payloads from entering business logic.
Global Exception Handling
Enterprise APIs should never expose stack traces to clients.
Global Exception Handler
package com.example.userservice.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ex.getMessage());
}
}
Why Centralized Exception Handling Matters
- Consistent API responses
- Better debugging
- Security protection
- Cleaner controllers
Testing Your API
APIs can be tested using:
- Postman
- curl
- Swagger
- JUnit
curl Example
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{
"name":"Naresh",
"email":"naresh@example.com"
}'
How Spring Boot Handles Requests Internally
HTTP Request
|
v
DispatcherServlet
|
v
Handler Mapping
|
v
Controller Method
|
v
Service Layer
|
v
Repository Layer
|
v
Database
|
v
Response Returned
DispatcherServlet is the front controller in Spring MVC. It receives every request and routes it to the appropriate controller.
Database Integration Best Practices
Production Database Recommendations
- PostgreSQL
- MySQL
- Oracle
- Microsoft SQL Server
Connection Pooling
Spring Boot uses HikariCP by default for efficient database connection pooling.
Why Connection Pooling Matters
- Reduced connection creation overhead
- Improved throughput
- Better resource utilization
- Lower latency
Logging and Monitoring
Observability is critical in microservices environments.
What Should Be Logged?
- Incoming requests
- Errors and exceptions
- Authentication failures
- Database latency
- External API failures
Enable Logging
logging:
level:
root: INFO
com.example: DEBUG
Production Monitoring Tools
- Prometheus
- Grafana
- ELK Stack
- OpenTelemetry
- Spring Boot Actuator
Spring Boot Actuator
Spring Boot Actuator provides production-ready monitoring endpoints.
Add Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Useful Endpoints
| Endpoint | Purpose |
|---|---|
| /actuator/health | Application health |
| /actuator/metrics | Performance metrics |
| /actuator/env | Environment properties |
Production Best Practices
Use Layered Architecture
- Controller layer
- Service layer
- Repository layer
- DTO layer
Never Expose Entities Directly
Use DTOs instead of returning database entities directly.
Externalize Configuration
Store secrets outside code using:
- Environment variables
- Vault systems
- Kubernetes secrets
Use Profiles
spring:
profiles:
active: dev
Environment Profiles
- dev
- test
- staging
- production
Security Considerations
Security must be integrated from the beginning.
Critical Security Practices
- Use HTTPS
- Validate all inputs
- Implement JWT authentication
- Use role-based authorization
- Enable rate limiting
- Sanitize logs
- Hide stack traces
Authentication Workflow
Client Login
|
v
Authentication Service
|
v
JWT Token Generated
|
v
Client Sends JWT
|
v
API Validates Token
|
v
Access Granted
Learn more in: JWT Authentication and Authorization
Dockerizing Your Microservice
Containers are essential in modern deployments.
Dockerfile
FROM eclipse-temurin:17
WORKDIR /app
COPY target/user-service.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
Build Docker Image
docker build -t user-service .
Run Container
docker run -p 8080:8080 user-service
Scaling Microservices
One of the biggest advantages of microservices is independent scalability.
Horizontal Scaling
Load Balancer
|
---------------------------------
| | |
+-------------+ +-------------+ +-------------+
| Instance 1 | | Instance 2 | | Instance 3 |
+-------------+ +-------------+ +-------------+
Benefits
- Higher availability
- Better traffic handling
- Fault tolerance
- Improved resilience
Common Beginner Mistakes
- Putting business logic inside controllers
- Returning entities directly
- Ignoring validation
- Not handling exceptions globally
- Using field injection everywhere
- Ignoring logging
- Not separating environments
- Hardcoding credentials
- Ignoring API versioning
Debugging Spring Boot Applications
Common Startup Errors
| Error | Cause |
|---|---|
| Port already in use | Another application using same port |
| Bean not found | Component scanning issue |
| Database connection failure | Wrong datasource config |
| 404 endpoint not found | Incorrect mapping |
Useful Debugging Techniques
- Enable debug logging
- Use breakpoints
- Inspect stack traces carefully
- Use actuator endpoints
- Monitor SQL queries
Real-World Enterprise Architecture
+------------------+
| API Gateway |
+---------+--------+
|
-------------------------------------------------
| | | |
+---------------+ +---------------+ +--------------+ +--------------+
| User Service | | Order Service | | Product Svc | | Payment Svc |
+-------+-------+ +-------+-------+ +------+-------+ +------+-------+
| | | |
------------------------------------------------------
|
+--------v---------+
| Message Broker |
| Kafka / RabbitMQ |
+------------------+
Enterprise Components
- API Gateway
- Service Discovery
- Distributed Tracing
- Centralized Logging
- Circuit Breakers
- Event Streaming
- Container Orchestration
Recommended next topics:
Interview Questions and Answers
What Is Spring Boot?
Spring Boot is a framework built on top of Spring that simplifies enterprise Java application development using auto-configuration and embedded servers.
Why Are Microservices Popular?
Microservices improve scalability, deployment independence, fault isolation, and development agility.
What Is Dependency Injection?
Dependency Injection is a design pattern where the framework provides required dependencies instead of objects creating them manually.
What Is the Difference Between @Component and @Service?
Both create Spring beans, but @Service is semantically used for business logic classes.
What Is Spring Boot Auto Configuration?
Auto configuration automatically configures beans based on dependencies present in the classpath.
What Is DispatcherServlet?
DispatcherServlet is the central front controller in Spring MVC that routes incoming requests.
Frequently Asked Questions
Is Spring Boot good for beginners?
Yes. Spring Boot significantly reduces configuration complexity and helps beginners focus on application logic.
Can microservices share databases?
Ideally no. Each microservice should own its database to maintain loose coupling.
Which database is best for Spring Boot?
PostgreSQL is commonly preferred for enterprise applications because of reliability and advanced features.
What is the difference between Spring and Spring Boot?
Spring is the core framework, while Spring Boot simplifies setup and configuration using auto-configuration.
Do microservices always need Docker?
Not necessarily, but containers make deployment and scaling significantly easier.
Should beginners start with monolith or microservices?
Beginners should first understand layered monolithic architecture before moving to distributed microservices.
What is the default embedded server in Spring Boot?
Spring Boot uses embedded Tomcat by default.
How does Spring Boot reduce boilerplate code?
It uses starter dependencies, auto-configuration, and convention-based setup to reduce manual configuration.
Summary
Building your first microservice with Spring Boot is an important milestone in becoming a modern backend engineer.
In this guide, you learned:
- Core microservices concepts
- Spring Boot architecture
- REST API development
- Layered architecture
- Validation and exception handling
- Monitoring and observability
- Production engineering practices
- Containerization basics
- Scaling strategies
Spring Boot is one of the most powerful technologies for enterprise backend development. Mastering it opens opportunities in:
- Enterprise backend engineering
- Cloud-native development
- Distributed systems
- Platform engineering
- Site reliability engineering
- DevOps and infrastructure automation