Spring Boot Interview Preparation
A. Spring Boot Basics Spring Boot is an extension of the Spring Framework that simplifies the development of Java applications by providing auto-configuration, starter dependencies, and embedded servers.β¦
A. Spring Boot Basics
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Spring Boot is an extension of the Spring Framework that simplifies the development of Java applications by providing auto-configuration, starter dependencies, and embedded servers.
The main goal of Spring Boot is to reduce boilerplate configuration so developers can focus on business logic rather than infrastructure setup.
Instead of configuring XML files, servlet containers, dependency versions, and numerous Spring beans manually, Spring Boot configures most things automatically based on the project’s dependencies.
Example
Without Spring Boot:
- Configure DispatcherServlet
- Configure Tomcat
- Configure DataSource
- Configure Jackson
- Configure Logging
With Spring Boot:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Everything is configured automatically.
Real-world Usage
Almost all modern Java microservices are built using Spring Boot because it enables faster development and easier deployment.
Interview Tip: Spring Boot is not a replacement for Spring Framework.
It is built on top of Spring Framework.
Before Spring Boot, developing Spring applications involved a lot of configuration.
Developers had to:
- configure XML files
- configure web.xml
- deploy WAR files
- install Tomcat separately
- manage dependency versions manually
This made development slow and error-prone.
Spring Boot was introduced to solve these problems by providing:
- Auto Configuration
- Starter Dependencies
- Embedded Server
- Production-ready features
- Opinionated defaults
Before Spring Boot
Developer
β
Configure XML
Configure Tomcat
Configure Servlet
Configure Logging
Configure DataSource
Configure JPA
With Spring Boot
Developer
β
Write Business Logic
Interview Tip: Whenever asked this question, mention:
Spring Boot follows the Convention over Configuration principle.
| Spring Framework | Spring Boot |
|---|---|
| Core framework | Built on Spring Framework |
| Requires manual configuration | Auto configuration |
| External Tomcat required | Embedded Tomcat |
| XML configuration common | Java configuration |
| Dependency versions managed manually | Starter dependencies |
| Slower setup | Faster setup |
| Suitable for any Spring application | Best for microservices |
Interview One-liner
Spring Boot is a rapid application development framework built on top of the Spring Framework.
Major advantages are:
1. Auto Configuration
Configures beans automatically.
2. Starter Dependencies
No need to find compatible dependency versions.
Example:
spring-boot-starter-web
adds
- Spring MVC
- Jackson
- Validation
- Embedded Tomcat
automatically.
3. Embedded Server
No external Tomcat installation.
4. Production Ready
Provides
- Actuator
- Health Checks
- Metrics
- Monitoring
5. Less Configuration
Almost zero XML.
6. Faster Development
Developers write business logic instead of infrastructure.
Interview Tip: The top three advantages interviewers expect are:
- Auto Configuration
- Starter Dependencies
- Embedded Server
Auto Configuration automatically configures Spring Beans based on the libraries present in the classpath.
Suppose you add
spring-boot-starter-data-jpa
Spring Boot automatically creates:
- DataSource
- EntityManager
- TransactionManager
- Hibernate configuration
without manual configuration.
Internal Working
Spring Boot checks
Classpath
β
Conditions
β
Required Classes Available?
β
Yes
β
Create Beans Automatically
using annotations like
@ConditionalOnClass
@ConditionalOnMissingBean
@ConditionalOnProperty
Example
Add dependency
spring-boot-starter-web
Boot automatically configures
- DispatcherServlet
- Jackson
- MessageConverters
- Embedded Tomcat
Interview Tip: Auto Configuration works only when the required dependency exists on the classpath.
@SpringBootApplication is a combination of three annotations.
@SpringBootApplication
is equivalent to
@Configuration
@EnableAutoConfiguration
@ComponentScan
Breakdown
@Configuration
Marks this class as a configuration class.
@EnableAutoConfiguration
Automatically configures beans.
@ComponentScan
Scans packages for Spring Beans.
Internal Flow
@SpringBootApplication
β
@Configuration
β
@EnableAutoConfiguration
β
@ComponentScan
β
Create Beans
Interview Tip: One of the most commonly asked annotation questions.
This annotation tells Spring Boot to configure the application automatically based on the dependencies present in the classpath.
Example:
If MySQL driver exists,
Spring Boot configures
- DataSource
- JdbcTemplate
- TransactionManager
automatically.
Internally it loads configuration classes from
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
(Older versions used spring.factories.)
Interview Tip: Do not say it creates all beans.
It creates only those beans whose conditions match.
Component Scanning is the process where Spring searches packages for classes annotated with
- @Component
- @Service
- @Repository
- @Controller
- @RestController
and registers them as Spring Beans.
Example
@Service
public class UserService {
}
Spring automatically creates its bean.
Default Package
Spring Boot scans
- current package
- all child packages
Example
com.company.app
|
|---controller
|---service
|---repository
Everything is discovered automatically.
Interview Tip: If a bean isn’t being detected, check whether it is inside the component scan package.
Starter dependencies are pre-defined dependency bundles that include all required libraries for a specific feature.
Example
spring-boot-starter-web
includes
- Spring MVC
- Jackson
- Validation
- Embedded Tomcat
- Logging
without adding each dependency manually.
Common Starters
| Starter | Purpose |
|---|---|
| spring-boot-starter-web | REST APIs |
| spring-boot-starter-data-jpa | JPA/Hibernate |
| spring-boot-starter-security | Security |
| spring-boot-starter-test | Testing |
| spring-boot-starter-actuator | Monitoring |
Interview Tip: Starter dependencies help avoid version conflicts because Spring Boot manages compatible versions.
spring-boot-starter-parent is a parent Maven POM that provides sensible defaults and dependency management.
It mainly offers:
- Dependency version management
- Plugin configuration (e.g., Maven Compiler, Surefire)
- Default Java settings
- Build configuration
Example
org.springframework.boot
spring-boot-starter-parent
3.x.x
Now you don’t need to specify versions for Spring Boot dependencies.
Interview Tip: It helps keep all Spring Boot libraries compatible by managing their versions centrally.
Embedded Tomcat is a Tomcat server packaged inside the Spring Boot application.
When you run the application, Tomcat starts automatically.
No separate installation or deployment of a WAR file is required.
Application
|
Embedded Tomcat
|
HTTP Requests
Advantage
Deployment becomes as simple as:
java -jar app.jar
Interview Tip: Spring Boot packages applications as executable JARs with an embedded server by default.
Yes.
Spring Boot is not tied to Tomcat.
You can use:
- Jetty
- Undertow
- Netty (with Spring WebFlux)
- No web server (batch or CLI applications)
Example
Exclude Tomcat and add Jetty:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-tomcat
org.springframework.boot
spring-boot-starter-jetty
Interview Tip: Spring Boot is server-independent; Tomcat is simply the default embedded servlet container for Spring MVC applications.
When the main() method calls SpringApplication.run(), Spring Boot follows a sequence of startup steps:
- Creates a SpringApplication instance.
- Detects the application type (Servlet, Reactive, or Non-Web).
- Loads environment properties.
- Creates the appropriate ApplicationContext.
- Runs ApplicationContextInitializers.
- Loads bean definitions through component scanning and configuration classes.
- Performs auto-configuration.
- Creates and initializes singleton beans.
- Starts the embedded server (if it’s a web application).
- Executes CommandLineRunner and ApplicationRunner.
Simplified flow:
main()
β
SpringApplication.run()
β
Prepare Environment
β
Create ApplicationContext
β
Component Scan
β
Auto Configuration
β
Create Beans
β
Start Embedded Server
β
Application Ready
Interview Tip: Interviewers often ask this to assess your understanding of the Spring Boot lifecycle. Mention ApplicationContext, auto-configuration, bean creation, and embedded server startup.
SpringApplication.run() is the entry point that bootstraps a Spring Boot application.
It performs tasks such as:
- Creating the ApplicationContext
- Loading configuration
- Performing component scanning
- Applying auto-configuration
- Initializing beans
- Starting the embedded server
- Returning the fully initialized ApplicationContext
Example:
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(Application.class, args);
}
Interview Tip: You can mention that it returns a ConfigurableApplicationContext, which can be used to retrieve beans programmatically if required.
#
B. Dependency Injection & Bean Management
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Inversion of Control (IoC) is a design principle where the responsibility of creating and managing objects is transferred from the application code to the Spring IoC Container.
Without IoC:
UserService service = new UserService();
With IoC:
@Autowired
private UserService service;
Spring creates and injects the object.
Benefits
- Loose coupling
- Easier testing
- Better maintainability
- Centralized object management
Interview Tip: IoC is the principle; Dependency Injection is one of the ways Spring implements IoC.
Dependency Injection (DI) is a technique where the Spring container supplies an object’s dependencies instead of the object creating them itself.
Example:
@Service
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
}
Spring creates UserRepository and injects it into UserService.
Advantages
- Loose coupling
- Easier unit testing
- Better maintainability
- Easier mocking
| Constructor Injection | Field Injection | Setter Injection |
|---|---|---|
| Injects via constructor | Uses @Autowired on field | Injects through setter |
| Recommended | Not recommended | Used for optional dependencies |
| Supports immutable fields | Mutable | Mutable |
| Easy to unit test | Hard to test | Testable |
| Ensures mandatory dependencies | Hidden dependencies | Good for optional dependencies |
Example
Constructor
@Service
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
}
Field
@Autowired
private UserRepository repository;
Setter
@Autowired
public void setRepository(UserRepository repository) {
this.repository = repository;
}
Constructor Injection is preferred because:
- Dependencies are mandatory and explicit.
- Allows final fields, making classes immutable.
- Makes unit testing easy without Spring.
- Prevents partially initialized objects.
- Spring can detect circular dependencies earlier.
Interview Tip: If asked what you use in production, answer:
We primarily use constructor injection because it promotes immutability, explicit dependencies, and better testability.
@Component is a generic stereotype annotation that marks a class as a Spring-managed bean.
@Component
public class EmailUtil {
}
Spring detects it during component scanning and registers it in the IoC container.
| Annotation | Purpose |
|---|---|
| @Component | Generic Spring bean |
| @Service | Business logic layer |
| @Repository | Data access layer; also translates persistence exceptions into Spring’s DataAccessException hierarchy |
| @Controller | Handles MVC web requests and returns views |
| @RestController | Combination of @Controller and @ResponseBody; returns JSON/XML responses |
Interview Tip: All of these are specialized forms of @Component, but using the appropriate stereotype improves readability and enables layer-specific behavior (for example, exception translation in @Repository).
@Bean is used on a method inside a @Configuration class to register the method’s return object as a Spring bean.
Example:
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
Use @Bean when you need to create or configure objects that you cannot annotate directly (e.g., third-party classes).
| @Bean | @Component |
|---|---|
| Method-level annotation | Class-level annotation |
| Used in @Configuration classes | Used directly on the class |
| Good for third-party libraries | Good for application classes |
| Manual bean creation | Automatic component scanning |
Interview Tip: Use @Component for your own classes and @Bean for external or specially configured objects.
Bean scope defines how many instances of a bean Spring creates and how long they live.
Common scopes are:
- singleton (default)
- prototype
- request
- session
- application
Singleton
- One instance per Spring container.
- Shared across the application.
- Default scope.
@Component
@Scope("singleton")
class UserService { }
Prototype
- A new instance is created each time the bean is requested.
@Component
@Scope("prototype")
class ReportGenerator { }
Interview Tip: Singleton scope is managed throughout the container’s lifetime. Prototype beans are created and injected, but Spring does not manage their full lifecycle after creation.
Request Scope
- One bean instance per HTTP request.
- Commonly used for request-specific data.
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
Session Scope
- One bean instance per user session.
- Useful for shopping carts or user preferences.
@Scope(value = WebApplicationContext.SCOPE_SESSION)
Application Scope
- One bean instance per ServletContext.
- Shared across the entire web application.
@Scope(value = WebApplicationContext.SCOPE_APPLICATION)
Lifecycle Steps
Bean Definition Loaded
β
Bean Instantiated
β
Dependencies Injected
β
@PostConstruct
β
InitializingBean.afterPropertiesSet()
β
Custom init-method (if configured)
β
Bean Ready for Use
β
Application Running
β
@PreDestroy
β
DisposableBean.destroy()
β
Custom destroy-method (if configured)
Interview Tip: Know the order of initialization and destruction callbacks. This is a favorite interview topic.
| @PostConstruct | InitializingBean |
|---|---|
| JSR/Jakarta standard annotation | Spring-specific interface |
| Method annotated with @PostConstruct | Override afterPropertiesSet() |
| No Spring API dependency | Tightly coupled to Spring |
| Preferred in most applications | Used when implementing Spring lifecycle interfaces is acceptable |
Example:
@PostConstruct
public void init() {
// Initialization logic
}
or
@Override
public void afterPropertiesSet() {
// Initialization logic
}
Interview Tip: @PostConstruct is generally preferred because it keeps your code framework-agnostic.
| @PreDestroy | DisposableBean |
|---|---|
| Jakarta standard annotation | Spring-specific interface |
| Called before bean destruction | Override destroy() |
| Preferred | Used when implementing lifecycle interfaces is needed |
Example:
@PreDestroy
public void cleanup() {
// Release resources
}
or
@Override
public void destroy() {
// Release resources
}
Interview Tip: Use @PreDestroy for cleanup tasks such as closing files, sockets, or database connections. Like @PostConstruct, it keeps your code less coupled to the Spring Framework.
C. Configuration & Properties
Configuration management is one of the most frequently asked Spring Boot interview topics, especially for experienced candidates.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Both application.properties and application.yml are used to configure a Spring Boot application.
The only difference is the format in which the configuration is written.
application.properties
server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/studentdb
spring.datasource.username=root
spring.datasource.password=root
application.yml
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/studentdb
username: root
password: root
Difference
| application.properties | application.yml |
|---|---|
| Key-value format | YAML format |
| Easier for small projects | Better for large configurations |
| More repetitive | Less repetitive |
| Supports flat structure | Supports hierarchical structure |
| Harder to read for nested configs | Easier to read for nested configs |
Interview Tip: Both files serve the same purpose. Spring Boot treats them equally; the choice mainly depends on readability and team preference.
It depends on the project.
application.properties
- Easier for beginners
- Simple syntax
- Good for small projects
application.yml
- Cleaner for nested configurations
- Less duplication
- Better readability in large applications
Example
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
jpa:
hibernate:
ddl-auto: update
This is much cleaner than writing multiple property keys.
Interview Tip: In most enterprise Spring Boot projects, YAML is commonly preferred because of its readability for complex configurations, though many teams continue using .properties for simplicity and consistency.
Spring Boot provides multiple ways to read configuration values.
Method 1 β @Value
app.name=InterviewBliss
@Value("${app.name}")
private String appName;
Method 2 β Environment
@Autowired
private Environment environment;
String name = environment.getProperty("app.name");
Method 3 β @ConfigurationProperties
app.name=InterviewBliss
app.version=1.0
@ConfigurationProperties(prefix = "app")
@Component
public class AppConfig {
private String name;
private String version;
// getters and setters
}
Usage
appConfig.getName();
Interview Tip: For a few properties use @Value.
For many related properties use @ConfigurationProperties.
| @Value | @ConfigurationProperties |
|---|---|
| Reads one property | Reads multiple related properties |
| Suitable for small configs | Suitable for large configs |
| No object mapping | Maps properties to POJO |
| Harder to maintain for many fields | Easier to maintain |
| No relaxed binding | Supports relaxed binding (e.g., app-name β appName) |
| Limited validation | Supports validation with @Validated and Bean Validation |
Example
Using @Value
@Value("${app.name}")
private String name;
@Value("${app.version}")
private String version;
Using ConfigurationProperties
@ConfigurationProperties(prefix="app")
public class AppConfig {
private String name;
private String version;
}
Interview Tip: For enterprise applications with many configuration values, prefer @ConfigurationProperties because it is cleaner, type-safe, and easier to validate.
Profiles allow us to maintain different configurations for different environments.
Example
- Development
- Testing
- Staging
- Production
Instead of changing configuration manually, Spring Boot loads the configuration based on the active profile.
Example
application-dev.properties
application-test.properties
application-prod.properties
Each contains different database URLs.
Interview Tip: Profiles eliminate the need to modify configuration files before deployment.
@Profile tells Spring to create a bean only when a specific profile is active.
Example
@Configuration
@Profile("dev")
public class DevConfiguration {
}
Another example
@Service
@Profile("prod")
public class PaymentService {
}
This bean exists only in the prod environment.
Interview Tip: @Profile is commonly used to provide different implementations for development and production.
Create separate property files.
application-dev.properties
application-test.properties
application-prod.properties
Each file contains environment-specific values.
Example
Development
server.port=8081
Production
server.port=8080
Spring Boot loads only the active profile’s configuration and then applies profile-specific overrides on top of the base application.properties (or application.yml) if present.
Interview Tip: Never store production secrets inside source code.
Method 1
Inside application.properties
spring.profiles.active=dev
Method 2
Command line
java -jar app.jar --spring.profiles.active=prod
Method 3
Environment Variable
SPRING_PROFILES_ACTIVE=prod
Interview Tip: Production environments usually activate profiles using environment variables or deployment configuration instead of changing application files.
Spring Boot can directly read operating system environment variables.
Example
DATABASE_URL
DATABASE_USERNAME
DATABASE_PASSWORD
Reference them in configuration
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
Why use Environment Variables?
- Hide secrets
- Better security
- Different values per environment
- Easy deployment on Docker/Kubernetes
Interview Tip: Sensitive information like passwords, API keys, and tokens should generally come from environment variables or a secrets manager, not be hardcoded.
Externalized Configuration means keeping configuration outside the application code so the same JAR can run in different environments with different settings.
Configuration can come from multiple sources such as:
- application.properties / application.yml
- Profile-specific files
- Environment variables
- JVM system properties
- Command-line arguments
- External configuration files
Example
Instead of
String url = "jdbc:mysql://localhost";
Use
spring.datasource.url=${DATABASE_URL}
Advantages
- No code changes between environments
- Better security
- Easy deployment
- Cloud-friendly
Interview Tip: One of Spring Boot’s biggest strengths is externalized configuration, which follows the 12-Factor App principle of separating configuration from code.
#
D. Spring Boot Annotations
These are among the most repeated interview questions.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
@SpringBootApplication is a convenience annotation that combines three annotations.
@SpringBootApplication
equals
@Configuration
@EnableAutoConfiguration
@ComponentScan
Responsibilities
- Marks configuration class
- Enables auto configuration
- Enables component scanning
Interview Tip: Almost every Spring Boot application starts with this annotation.
@Component marks a class as a Spring-managed bean.
@Component
public class EmailUtil {
}
Spring discovers it during component scanning.
Interview Tip: It is the generic stereotype annotation. Other stereotypes such as @Service and @Repository are built on top of it.
@Service marks a class as the business logic layer.
@Service
public class UserService {
}
Although functionally similar to @Component, it clearly communicates that the class contains business logic.
Interview Tip: Use @Service for service classes to improve readability and maintain a layered architecture.
@Repository marks a class responsible for database operations.
@Repository
public class UserRepository {
}
Extra Feature
It automatically translates persistence exceptions into Spring’s DataAccessException hierarchy.
Interview Tip: This exception translation is the key difference from @Component.
@Controller handles web requests in Spring MVC.
@Controller
public class HomeController {
}
It typically returns the name of a view (JSP, Thymeleaf, etc.).
Example
@GetMapping("/")
public String home() {
return "home";
}
Interview Tip: Used for traditional MVC applications.
@RestController is used to build REST APIs.
It combines
@Controller
+
@ResponseBody
Example
@RestController
public class UserController {
@GetMapping("/users")
public List getUsers() {
return service.getUsers();
}
}
The returned object is automatically converted to JSON (or another supported format).
Interview Tip: For REST APIs, use @RestController instead of @Controller.
@Autowired tells Spring to inject a dependency automatically.
Example
@Service
public class UserService {
@Autowired
private UserRepository repository;
}
Spring finds the matching bean and injects it.
Interview Tip: In modern Spring, constructor injection is preferred. With a single constructor, @Autowired on the constructor can even be omitted.
@Qualifier is used when multiple beans of the same type exist.
Example
@Component
class PaytmPayment {}
@Component
class RazorpayPayment {}
Injection
@Autowired
@Qualifier("paytmPayment")
private Payment payment;
Spring injects the bean with the matching name.
Interview Tip: Without @Qualifier, multiple beans of the same type can cause NoUniqueBeanDefinitionException.
@Primary marks one bean as the default choice when multiple beans of the same type exist.
@Component
@Primary
class PaytmPayment {
}
Now Spring injects this bean unless another bean is explicitly selected using @Qualifier.
Interview Tip: @Primary provides a default; @Qualifier overrides that default for a specific injection point.
By default, singleton beans are created during application startup.
@Lazy delays bean creation until it is first requested.
@Component
@Lazy
public class HeavyService {
}
Advantages
- Faster startup
- Saves memory for rarely used beans
Interview Tip: Useful for expensive-to-create beans or to help break some circular dependency scenarios, though redesigning the dependency graph is usually a better long-term solution.
@Scope defines the lifecycle and visibility of a Spring bean.
Example
@Component
@Scope("prototype")
public class ReportGenerator {
}
Common scopes
- singleton
- prototype
- request
- session
- application
Interview Tip: Singleton is the default scope.
@Bean registers the return value of a method as a Spring bean.
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
Use it when creating or configuring objects that cannot be annotated directly.
Interview Tip: Often used for third-party libraries.
@Configuration marks a class as a source of bean definitions.
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
Spring processes this class and registers all @Bean methods.
Interview Tip: Think of @Configuration as the Java-based replacement for XML configuration.
@Value injects a property value into a field, constructor parameter, or method parameter.
app.name=InterviewBliss
@Value("${app.name}")
private String appName;
It can also provide default values.
@Value("${server.port:8080}")
private int port;
Interview Tip: Best for injecting a small number of simple configuration values.
@ConfigurationProperties binds a group of related configuration properties to a POJO.
Example
app.name=InterviewBliss
app.version=1.0
app.owner=Prakash
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String version;
private String owner;
// getters and setters
}
Usage
System.out.println(appProperties.getName());
Advantages
- Type-safe configuration
- Cleaner than multiple @Value annotations
- Supports relaxed binding
- Supports validation with @Validated
Interview Tip: A common interview question is:
When would you use @Value and when would you use @ConfigurationProperties?
A strong answer is:
- Use @Value when you need only one or two configuration values.
- Use @ConfigurationProperties when you have many related properties because it is cleaner, type-safe, easier to maintain, and supports validation. This is the preferred approach in large production applications.
E. REST API Development
REST API development is one of the most frequently asked Spring Boot interview topics, especially for developers with 2+ years of experience. Interviewers expect not only definitions but also best practices and real-world examples.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
In Spring Boot, REST APIs are created using the Spring Web (Spring MVC) module.
The basic steps are:
- Add spring-boot-starter-web
- Create a Controller
- Annotate it with @RestController
- Map URLs using @GetMapping, @PostMapping, etc.
- Return data (usually POJOs), which Spring converts to JSON automatically using Jackson.
Example
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUser(id);
}
}
Request
GET /api/users/1
Response
{
"id":1,
"name":"John"
}
Internal Flow
HTTP Request
β
DispatcherServlet
β
Controller
β
Service
β
Repository
β
Database
β
JSON Response
Interview Tip: Always mention:
- @RestController
- @RequestMapping
- HTTP methods
- Jackson converts Java objects into JSON automatically.
| Method | Purpose | Idempotent |
|---|---|---|
| GET | Retrieve data | β Yes |
| POST | Create resource | β No |
| PUT | Replace entire resource | β Yes |
| PATCH | Update partial resource | Usually Yes |
| DELETE | Delete resource | β Yes |
Example
GET /users
POST /users
PUT /users/1
PATCH /users/1
DELETE /users/1
Interview Tip: Interviewers often ask:
Which HTTP methods are idempotent?
Answer:
GET, PUT and DELETE are idempotent. POST is not.
PUT
Replaces the entire resource.
Existing User
{
"id":1,
"name":"John",
"city":"Delhi"
}
Request
{
"name":"David"
}
After PUT
city becomes null
because the whole object is replaced.
PATCH
Updates only specified fields.
Request
{
"name":"David"
}
Result
{
"id":1,
"name":"David",
"city":"Delhi"
}
Difference
| PUT | PATCH |
|---|---|
| Full update | Partial update |
| Sends complete object | Sends changed fields only |
| Replaces resource | Modifies resource |
Interview Tip: In production:
- PUT β Full replacement
- PATCH β Partial update
@PathVariable
Reads value from URL path.
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id){
}
URL
GET /users/10
@RequestParam
Reads query parameters.
@GetMapping("/users")
public List users(@RequestParam String city){
}
URL
GET /users?city=Delhi
Difference
| @PathVariable | @RequestParam |
|---|---|
| URL Path | Query Parameter |
| Mandatory by default | Can be optional |
| Used for resource identifier | Used for filtering/searching |
Interview Tip: “`
/users/10
β PathVariable
/users?page=1
β RequestParam
@RequestBody converts incoming JSON into a Java object.
Example
Request
{
"name":"John",
"city":"Delhi"
}
Controller
@PostMapping("/users")
public User save(@RequestBody User user){
}
Spring automatically converts JSON into a User object using Jackson.
Interview Tip: Without @RequestBody, Spring won’t automatically deserialize JSON into the object.
@ResponseBody converts the returned Java object into JSON or XML.
Example
@ResponseBody
@GetMapping("/users")
public User getUser(){
}
Actually,
@RestController
is equivalent to
@Controller
@ResponseBody
Interview Tip: For REST APIs, prefer @RestController instead of @Controller + @ResponseBody.
ResponseEntity represents the entire HTTP response.
It allows us to control:
- Status Code
- Headers
- Body
Example
@GetMapping("/{id}")
public ResponseEntity getUser(@PathVariable Long id){
User user = service.getUser(id);
return ResponseEntity.ok(user);
}
Not Found
return ResponseEntity.notFound().build();
Created
return ResponseEntity.status(HttpStatus.CREATED)
.body(user);
Advantages
- Custom status code
- Custom headers
- Flexible response
Interview Tip: Most production APIs return ResponseEntity.
Spring provides predefined HTTP status codes through the HttpStatus enum.
Examples
HttpStatus.OK
HttpStatus.CREATED
HttpStatus.BAD_REQUEST
HttpStatus.NOT_FOUND
HttpStatus.INTERNAL_SERVER_ERROR
Common Status Codes
| Code | Meaning |
|---|---|
| 200 | OK |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 409 | Conflict |
| 500 | Internal Server Error |
Interview Tip: Always return meaningful HTTP status codes instead of returning 200 OK for every request.
A good REST API should follow these practices:
- Use nouns instead of verbs.
- Use correct HTTP methods.
- Return proper HTTP status codes.
- Validate request data.
- Handle exceptions globally.
- Support pagination for large datasets.
- Use versioning.
- Keep APIs stateless.
- Use meaningful error messages.
- Follow consistent naming conventions.
Interview Tip: These points are commonly expected in system design and API design interviews.
Good URLs
GET /users
GET /users/1
POST /users
PUT /users/1
DELETE /users/1
Bad URLs
/getUser
/createUser
/deleteUser
Best Practices
- Use plural nouns.
- Use lowercase.
- Use hyphens instead of underscores if needed.
- Avoid verbs.
- Use HTTP methods to define the action.
Interview Tip: REST URLs represent resources, while HTTP methods represent actions.
An API is idempotent if calling it multiple times with the same request produces the same result.
Example
DELETE /users/10
First request deletes the user.
Second request doesn’t change anything because the user is already deleted.
The final state remains the same.
Idempotent Methods
- GET
- PUT
- DELETE
Not idempotent
- POST
Interview Tip: This is one of the most frequently asked REST theory questions.
Pagination retrieves records in smaller chunks instead of loading everything.
Example
GET /users?page=0&size=10
Spring Data
Page findAll(Pageable pageable);
Benefits
- Faster APIs
- Less memory
- Better user experience
- Reduced database load
Interview Tip: Always use pagination for APIs returning large datasets.
Sorting returns records in a specific order.
Example
GET /users?sort=name
Descending
GET /users?sort=name,desc
Spring
Pageable pageable =
PageRequest.of(0,10,
Sort.by("name"));
Interview Tip: Sorting is usually combined with pagination.
Filtering retrieves only matching records.
Example
GET /users?city=Delhi
or
GET /users?age=25
or
GET /users?department=IT
Interview Tip: Filtering is generally implemented using query parameters (@RequestParam) rather than path variables.
Versioning allows APIs to evolve without breaking existing clients.
URI Versioning (Most Common)
/api/v1/users
/api/v2/users
Header Versioning
API-Version: 1
Request Parameter Versioning
/users?version=1
Difference
| Type | Example |
|---|---|
| URI | /v1/users |
| Header | API-Version:1 |
| Parameter | ?version=1 |
Interview Tip: URI versioning (/api/v1/…) is the simplest and most commonly used approach.
Spring Boot uploads files using MultipartFile.
Example
@PostMapping("/upload")
public String upload(
@RequestParam MultipartFile file){
}
HTML Form
multipart/form-data
Interview Tip: Use MultipartFile for uploads and validate file size and type.
Files can be downloaded using ResponseEntity.
Example
@GetMapping("/download")
public ResponseEntity download(){
}
Return
- File
- Headers
- Content-Type
Interview Tip: Set proper Content-Disposition and Content-Type headers so browsers download the file correctly.
#
F. Exception Handling
Exception handling is one of the favorite Spring Boot interview topics because it demonstrates how you build robust, production-ready APIs.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Spring Boot provides Global Exception Handling using @ControllerAdvice or @RestControllerAdvice.
Instead of handling exceptions in every controller, we centralize exception handling in one class.
Example
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity handle(Exception ex){
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ex.getMessage());
}
}
Advantages
- Centralized logic
- Reusable
- Cleaner controllers
- Consistent error responses
Interview Tip: Always mention @RestControllerAdvice for REST APIs.
@ExceptionHandler is used to handle a specific exception.
Example
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity handle(
UserNotFoundException ex){
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(ex.getMessage());
}
Whenever UserNotFoundException is thrown, this method is invoked.
Interview Tip: It can be used inside a controller or inside a @ControllerAdvice class for centralized handling.
@ControllerAdvice provides global exception handling for all Spring MVC controllers.
It can also be used for cross-cutting concerns such as:
- Exception handling
- Model attributes
- Data binding
Example
@ControllerAdvice
public class GlobalExceptionHandler {
}
Interview Tip: It works with traditional MVC applications that return views.
@RestControllerAdvice is a combination of:
@ControllerAdvice
+
@ResponseBody
It is designed specifically for REST APIs.
Example
@RestControllerAdvice
public class GlobalExceptionHandler {
}
Interview Tip: Use @RestControllerAdvice instead of @ControllerAdvice when your application returns JSON responses.
A custom exception represents a business-specific error.
Example
public class UserNotFoundException
extends RuntimeException {
public UserNotFoundException(String message){
super(message);
}
}
Usage
throw new UserNotFoundException(
"User not found");
Why Use Custom Exceptions?
- Better readability
- Business-specific errors
- Easier global handling
Interview Tip: Extend RuntimeException for most application-specific exceptions unless there is a strong reason to use a checked exception.
Instead of returning plain strings, return a structured error object.
Example
public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;
// getters and setters
}
Handler
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity handle(
UserNotFoundException ex,
HttpServletRequest request){
ErrorResponse error = new ErrorResponse();
error.setTimestamp(LocalDateTime.now());
error.setStatus(HttpStatus.NOT_FOUND.value());
error.setError("Not Found");
error.setMessage(ex.getMessage());
error.setPath(request.getRequestURI());
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(error);
}
Sample Response
{
"timestamp":"2026-07-27T10:15:30",
"status":404,
"error":"Not Found",
"message":"User not found",
"path":"/api/users/10"
}
Interview Tip: Consistent error responses make APIs easier to consume and debug.
ResponseStatusException allows you to throw an exception with an HTTP status without creating a custom exception class.
Example
throw new ResponseStatusException(
HttpStatus.NOT_FOUND,
"User not found");
Spring automatically returns a 404 Not Found response.
Interview Tip: Use it for simple scenarios. For reusable business logic and standardized error handling, custom exceptions with global handlers are usually a better approach.
@ResponseStatus associates an exception or controller method with a specific HTTP status.
Example
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException
extends RuntimeException {
public UserNotFoundException(String message){
super(message);
}
}
Whenever this exception is thrown, Spring returns 404 Not Found.
Interview Tip: @ResponseStatus is useful for simple exception-to-status mapping. For custom error bodies, combine custom exceptions with @RestControllerAdvice.
Spring Boot uses Bean Validation annotations to validate request data.
Example DTO
public class UserRequest {
@NotBlank
private String name;
@Email
private String email;
@Min(18)
private int age;
// getters and setters
}
Controller
@PostMapping("/users")
public ResponseEntity createUser(
@Valid @RequestBody UserRequest request){
return ResponseEntity.ok(service.create(request));
}
Global Handler
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity> handleValidation(
MethodArgumentNotValidException ex) {
Map errors = new HashMap<>();
ex.getBindingResult()
.getFieldErrors()
.forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
Sample Response
{
"name":"must not be blank",
"email":"must be a well-formed email address",
"age":"must be greater than or equal to 18"
}
Interview Tip: A production-ready validation flow typically includes:
- Bean Validation annotations (@NotBlank, @Email, @Size, etc.)
- @Valid on the request body
- A global @RestControllerAdvice to return consistent validation error responses
G. Validation
Validation is one of the most frequently asked Spring Boot interview topics because every production API validates incoming requests before processing them.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Bean Validation is a specification (Jakarta Bean Validation) that provides a standard way to validate Java objects using annotations.
Spring Boot integrates Bean Validation through Hibernate Validator, which is the default implementation.
Instead of writing manual validation code, we annotate fields with constraints such as:
- @NotNull
- @NotBlank
- @Size
Example
public class UserRequest {
@NotBlank
private String name;
@Email
private String email;
@Min(18)
private int age;
}
Spring automatically validates the object before the controller method executes.
Advantages
- Less boilerplate code
- Centralized validation rules
- Consistent validation
- Easy maintenance
Interview Tip: Bean Validation is the specification, while Hibernate Validator is its most common implementation in Spring Boot.
@Valid triggers validation for an object annotated with Bean Validation constraints.
Example
@PostMapping("/users")
public ResponseEntity createUser(
@Valid @RequestBody UserRequest request){
return ResponseEntity.ok(service.save(request));
}
If validation fails, Spring throws MethodArgumentNotValidException.
Interview Tip: @Valid is commonly used on:
- @RequestBody
- Method parameters
- Nested objects
@Validated is Spring’s validation annotation that supports:
- Validation Groups
- Method-level validation
Example
@Validated
@Service
public class UserService {
}
Difference
| @Valid | @Validated |
|---|---|
| Jakarta Validation | Spring Validation |
| No validation groups | Supports validation groups |
| Mostly for request objects | Used for classes and methods |
Interview Tip: Use @Valid for normal request validation and @Validated when you need validation groups or method-level validation.
@NotNull ensures a value is not null.
Example
@NotNull
private Integer age;
Allowed
age = 25
Not Allowed
age = null
Empty strings are still allowed.
Interview Tip: @NotNull checks only for null, not empty values.
@NotBlank is used for Strings.
It rejects:
- null
- “”
- ” “
Example
@NotBlank
private String name;
Interview Tip: Use @NotBlank for names, usernames, addresses, etc.
@NotEmpty ensures a value is:
- not null
- not empty
Works for:
- String
- List
- Set
- Map
- Arrays
Example
@NotEmpty
private List skills;
Difference
| Annotation | Rejects null | Rejects empty | Rejects whitespace |
|---|---|---|---|
| @NotNull | β | β | β |
| @NotEmpty | β | β | β |
| @NotBlank | β | β | β (Strings only) |
Interview Tip: This comparison is a very common interview question.
@Size validates the length of:
- String
- Collection
- Array
- Map
Example
@Size(min = 3, max = 20)
private String username;
Allowed
John
Not Allowed
Jo
Interview Tip: @Size checks length, not numeric value.
@Pattern validates a String using a regular expression.
Example
@Pattern(regexp = "^[0-9]{10}$")
private String mobile;
Valid
9876543210
Invalid
98765
Interview Tip: Frequently used for:
- Mobile numbers
- PAN
- Aadhaar
- Password validation
@Email validates email format.
Example
@Email
private String email;
Valid
abc@gmail.com
Invalid
abcgmail.com
Interview Tip: Usually combined with @NotBlank.
@NotBlank
@Email
private String email;
When built-in annotations are insufficient, create a custom validation annotation.
Step 1
Create annotation
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AgeValidator.class)
public @interface ValidAge {
}
Step 2
Implement validator
public class AgeValidator
implements ConstraintValidator{
@Override
public boolean isValid(Integer age,
ConstraintValidatorContext context){
return age >= 18;
}
}
Step 3
Use annotation
@ValidAge
private Integer age;
Interview Tip: Custom validators are useful for complex business rules that cannot be expressed with built-in annotations.
Validation Groups allow different validation rules for different operations.
Example
Create
Update
Admin
Example
public interface Create {}
public interface Update {}
Validation
@NotNull(groups = Update.class)
private Long id;
@NotBlank(groups = Create.class)
private String name;
Controller
@PostMapping
public void create(
@Validated(Create.class)
@RequestBody UserRequest request){
}
Advantages
- Different validation for create/update
- Cleaner code
- Reusable DTOs
Interview Tip: Validation Groups are useful when one DTO is reused for multiple operations with different validation requirements.
#
H. Spring Boot Data Access
Spring Data JPA and Hibernate are among the most frequently asked Spring Boot interview topics, especially for developers with 2+ years of experience.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Spring Data JPA is a Spring module that simplifies database access using JPA.
Instead of writing boilerplate DAO code, we create interfaces and Spring automatically generates implementations.
Example
public interface UserRepository
extends JpaRepository{
}
Now we automatically get methods like:
- save()
- findById()
- findAll()
- deleteById()
without implementing them.
Advantages
- Less boilerplate
- Pagination
- Sorting
- Query methods
- Custom queries
- Transaction support
Interview Tip: Spring Data JPA sits on top of JPA and usually uses Hibernate as the JPA provider.
| CrudRepository | JpaRepository |
|---|---|
| Basic CRUD | CRUD + JPA features |
| save(), delete(), findById() | All CRUD methods |
| No pagination | Pagination support |
| No batch operations | Batch operations |
| Minimal functionality | Most commonly used |
Hierarchy
Repository
β
CrudRepository
β
PagingAndSortingRepository
β
JpaRepository
Interview Tip: In most Spring Boot projects, JpaRepository is preferred because it includes CRUD, pagination, sorting, flushing, and batch operations.
It extends CrudRepository and adds pagination and sorting support.
Example
Page findAll(Pageable pageable);
Sorting
Sort.by("name");
Interview Tip: JpaRepository already extends PagingAndSortingRepository, so using JpaRepository gives you these features automatically.
| Hibernate | JPA |
|---|---|
| ORM framework | Java specification |
| Implementation | API/Standard |
| Provides actual implementation | Defines interfaces only |
| Developed by Hibernate team | Defined by Jakarta EE |
Relationship
Application
β
JPA
β
Hibernate
β
Database
Interview Tip: JPA is only a specification. Hibernate is the most popular implementation of that specification.
The Entity Lifecycle describes how an entity moves through different states while interacting with the persistence context.
New
β persist()
Managed
β detach()
Detached
β merge()
Managed
β remove()
Removed
Interview Tip: Interviewers often ask this together with Entity States.
There are four entity states.
1. Transient (New)
Created using new.
Not associated with Persistence Context.
User user = new User();
2. Managed (Persistent)
Entity is managed by Hibernate.
Changes are automatically synchronized with the database during flush/commit.
3. Detached
Previously managed but no longer associated with the persistence context.
Needs merge() to become managed again.
4. Removed
Marked for deletion.
Deleted when the transaction commits.
Interview Tip: Remember:
Transient β Managed β Detached β Removed
Marks a class as a JPA entity.
@Entity
public class User {
}
Each entity is mapped to a database table.
Interview Tip: Every entity must have a primary key.
Maps an entity to a specific database table.
@Entity
@Table(name="users")
public class User {
}
Without it, Hibernate uses the class name (or its naming strategy) to derive the table name.
Marks the primary key.
@Id
private Long id;
Every entity requires an identifier.
Automatically generates primary key values.
Example
@Id
@GeneratedValue(strategy =
GenerationType.IDENTITY)
private Long id;
Strategies
- AUTO
- IDENTITY
- SEQUENCE
- TABLE
Interview Tip: IDENTITY is commonly used with MySQL. SEQUENCE is preferred with databases like PostgreSQL and Oracle because it supports efficient sequence-based ID generation.
Maps a field to a database column.
Example
@Column(name="user_name",
nullable=false,
length=50)
private String name;
Common Attributes
- name
- nullable
- unique
- length
- precision
- scale
@Transient tells JPA not to persist a field.
Example
@Transient
private String confirmPassword;
Useful for temporary or calculated values.
Interview Tip: Do not confuse JPA’s @Transient with Java’s transient keyword. The annotation affects persistence, while the keyword affects Java serialization.
Stores Java enums in the database.
Example
public enum Status {
ACTIVE,
INACTIVE
}
@Enumerated(EnumType.STRING)
private Status status;
Options
- ORDINAL
- STRING
Interview Tip: Prefer EnumType.STRING because it is more readable and avoids data corruption if enum constants are reordered.
Maps large objects.
Example
@Lob
private String description;
Used for:
- Large text (CLOB)
- Binary data (BLOB)
Interview Tip: Useful for storing documents, images, or long descriptions.
LAZY
Loads related data only when accessed.
@OneToMany(fetch = FetchType.LAZY)
EAGER
Loads related data immediately.
@OneToMany(fetch = FetchType.EAGER)
Difference
| LAZY | EAGER |
|---|---|
| Loads on demand | Loads immediately |
| Better performance for large relationships | Can load unnecessary data |
| Default for @OneToMany and @ManyToMany | Default for @OneToOne and @ManyToOne |
Interview Tip: Use LAZY by default and fetch eagerly only when there is a clear business need. This helps avoid unnecessary queries and improves performance.
Cascade operations automatically propagate persistence actions from the parent entity to related child entities.
Types
- PERSIST
- MERGE
- REMOVE
- REFRESH
- DETACH
- ALL
Example
@OneToMany(cascade = CascadeType.ALL)
private List orders;
Example
Saving a parent automatically saves its children.
Deleting a parent deletes its children when CascadeType.REMOVE (or ALL) is configured.
Interview Tip: Use only the cascade types you actually need. Avoid using CascadeType.ALL blindly, especially on relationships where deleting a parent should not delete shared child records.
orphanRemoval = true automatically deletes child entities that are removed from the parent’s collection.
Example
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true)
private List orders;
If an Order is removed from orders, Hibernate deletes that record from the database.
Interview Tip: CascadeType.REMOVE deletes children when the parent is deleted, whereas orphanRemoval deletes a child when it is removed from the parent’s relationship, even if the parent itself is not deleted.
One record is associated with exactly one other record.
Example
Person
β
Passport
Entity
@OneToOne
@JoinColumn(name = "passport_id")
private Passport passport;
Interview Tip: Use @JoinColumn on the owning side of the relationship.
One parent has many child records.
Example
Department
β
Employees
Entity
@OneToMany(mappedBy = "department")
private List employees;
Interview Tip: The mappedBy attribute indicates that the foreign key is maintained by the child entity.
Many child records belong to one parent.
Example
Many Employees
β
One Department
Entity
@ManyToOne
@JoinColumn(name = "department_id")
private Department department;
Interview Tip: @ManyToOne is the owning side and contains the foreign key column.
Many records are associated with many other records.
Example
Students
β
Courses
Entity
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List courses;
Interview Tip: Many-to-many relationships use a join table. In production systems, if the relationship itself has additional attributes (such as enrollment date or role), it’s often better to replace @ManyToMany with an explicit join entity (e.g., StudentCourse) modeled as two @ManyToOne relationships. This provides greater flexibility and is a common enterprise design pattern.
I. Transactions
Transactions are one of the most frequently asked topics in Spring Boot interviews, especially for 3+ years experienced developers. Interviewers usually expect you to explain ACID, @Transactional, propagation, isolation, rollback behavior, and real-world scenarios.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
A Transaction is a group of one or more database operations that are executed as a single logical unit of work.
A transaction ensures that either all operations succeed or all operations fail.
For example, during bank money transfer:
- Debit βΉ1000 from Account A
- Credit βΉ1000 to Account B
Both operations must succeed together. If one fails, both should be rolled back.
Example
Transfer Money
β
Debit Account A
β
Credit Account B
β
Commit
If Credit fails
Transfer Money
β
Debit Account A
β
Credit Failed
β
Rollback
No money is deducted.
Real-world Example
In an E-commerce application:
Place Order
β
Save Order
β
Reduce Inventory
β
Process Payment
β
Generate Invoice
If payment fails, inventory and order should also roll back.
Interview Tip: A transaction guarantees data consistency by ensuring all operations complete successfully or none do.
ACID properties ensure reliable transaction processing.
A β Atomicity
All operations execute successfully or none execute.
Example
Bank Transfer
Debit succeeds
Credit fails
β
Rollback debit
C β Consistency
A transaction moves the database from one valid state to another.
Example
Total balance before transfer
A = 5000
B = 3000
Total = 8000
After transfer
A = 4000
B = 4000
Total = 8000
Consistency maintained.
I β Isolation
Multiple transactions should not interfere with each other.
Example
Two users updating the same account simultaneously.
Isolation prevents inconsistent results.
D β Durability
Once committed, data remains permanent even if the server crashes.
Example
Commit
β
Power Failure
β
Data still exists
Interview Tip: Remember
A
Atomicity
C
Consistency
I
Isolation
D
Durability
@Transactional marks a method or class as transactional.
Spring automatically:
- Starts a transaction before method execution.
- Commits the transaction if the method completes successfully.
- Rolls back the transaction if an eligible exception occurs.
Example
@Service
public class PaymentService {
@Transactional
public void transferMoney() {
debit();
credit();
}
}
Spring internally performs
Begin Transaction
β
Execute Method
β
Success?
β β
Yes No
β β
Commit Rollback
Advantages
- Automatic transaction management
- Cleaner code
- No manual commit/rollback
Interview Tip: Spring implements @Transactional using AOP (Proxy-based interception).
Propagation defines how a transactional method behaves when another transaction already exists.
REQUIRED (Default)
Join existing transaction.
Otherwise create a new one.
@Transactional(propagation = Propagation.REQUIRED)
Example
Transaction Exists
β
Join it
REQUIRES_NEW
Always creates a new transaction.
Existing transaction is suspended.
@Transactional(propagation =
Propagation.REQUIRES_NEW)
Example
Main Transaction
β
Suspended
β
New Transaction
Used for
- Audit logs
- Notifications
- Logging
SUPPORTS
Uses existing transaction.
Otherwise executes without one.
NOT_SUPPORTED
Suspends current transaction.
Executes non-transactionally.
MANDATORY
Must have an existing transaction.
Otherwise throws exception.
NEVER
Should never execute inside a transaction.
Throws exception if one exists.
NESTED
Creates a savepoint inside the current transaction.
Can roll back to that savepoint without rolling back the entire outer transaction (requires underlying support, such as JDBC savepoints).
Interview Tip: The three most important propagation types are:
- REQUIRED
- REQUIRES_NEW
- NESTED
Isolation controls how transactions interact with each other when running concurrently.
READ_UNCOMMITTED
Can read uncommitted data.
Possible problem
Dirty Read
READ_COMMITTED
Reads only committed data.
Prevents dirty reads.
Most commonly used by databases like Oracle.
REPEATABLE_READ
Ensures repeated reads return the same data within a transaction.
Prevents:
- Dirty Read
- Non-repeatable Read
(MySQL’s default isolation level.)
SERIALIZABLE
Highest isolation level.
Transactions execute one after another.
Safest but slowest.
Difference
| Isolation | Dirty Read | Non-Repeatable Read | Phantom Read |
|---|---|---|---|
| READ_UNCOMMITTED | β Allowed | β Allowed | β Allowed |
| READ_COMMITTED | β Prevented | β Allowed | β Allowed |
| REPEATABLE_READ | β Prevented | β Prevented | β May occur* |
| SERIALIZABLE | β Prevented | β Prevented | β Prevented |
\\*Depending on the database implementation. For example, InnoDB’s implementation prevents many phantom-read scenarios using next-key locking.
Interview Tip: For most enterprise applications:
- Default database isolation is sufficient.
- Increase isolation only when required because higher isolation reduces concurrency.
Spring rolls back a transaction when an eligible exception occurs.
Default behavior:
- Rollback for RuntimeException
- Rollback for Error
- Commit for checked exceptions unless configured otherwise
Example
@Transactional(
rollbackFor = Exception.class)
public void save(){
}
Now even checked exceptions trigger rollback.
Interview Tip: Know the default rollback behaviorβit is one of the most frequently asked Spring transaction questions.
| Runtime Exception | Checked Exception |
|---|---|
| Rolls back by default | Does not roll back by default |
| Extends RuntimeException | Extends Exception |
| Unchecked | Checked |
Example
throw new RuntimeException();
β
Rollback
Example
throw new IOException();
β
Commit (unless configured with rollbackFor)
Interview Tip: If asked:
Why doesn’t Spring roll back checked exceptions by default?
Answer:
Because checked exceptions often represent recoverable business conditions. If you want rollback, configure it explicitly using rollbackFor.
A read-only transaction indicates that the transaction is intended only for reading data.
Example
@Transactional(readOnly = true)
public List getUsers(){
}
Benefits
- Avoids unnecessary dirty checking in JPA/Hibernate
- Can improve performance
- Expresses developer intent clearly
Interview Tip: Use readOnly = true for query methods.
A nested transaction creates a savepoint inside an existing transaction.
If the nested transaction fails, it can roll back to the savepoint while allowing the outer transaction to continue (if appropriate).
Example
Main Transaction
β
Savepoint
β
Nested Transaction
β
Failure
β
Rollback to Savepoint
β
Continue Main Transaction
Example
@Transactional(propagation =
Propagation.NESTED)
Interview Tip: Nested transactions require savepoint support from the underlying transaction manager and database. They are less commonly used than REQUIRED or REQUIRES_NEW.
#
J. Spring Boot Security
Spring Security is one of the most important interview topics for experienced Java developers. Interviewers usually focus on JWT, authentication flow, filters, authorization, and security architecture.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Spring Security secures applications using a chain of servlet filters.
Request Flow
HTTP Request
β
Security Filter Chain
β
Authentication Filter
β
AuthenticationManager
β
UserDetailsService
β
PasswordEncoder
β
SecurityContext
β
Controller
Main Components
- SecurityFilterChain
- AuthenticationManager
- UserDetailsService
- PasswordEncoder
- SecurityContextHolder
Interview Tip: Remember:
Every incoming request first passes through the Security Filter Chain before reaching the controller.
| Authentication | Authorization |
|---|---|
| Who are you? | What are you allowed to do? |
| Identity verification | Permission verification |
| Login | Access control |
| Happens first | Happens after authentication |
Example
Authentication
Username + Password
Authorization
ROLE_ADMIN
can access
/admin
Interview Tip: Authentication verifies identity.
Authorization verifies permissions.
UserDetailsService loads user details from a data source during authentication.
Method
UserDetails loadUserByUsername(
String username);
Example
@Service
public class CustomUserDetailsService
implements UserDetailsService{
@Override
public UserDetails loadUserByUsername(
String username){
return repository.findByUsername(username);
}
}
Interview Tip: Spring Security calls this service automatically during username/password authentication.
PasswordEncoder hashes passwords before storing them and verifies passwords during login.
Example
PasswordEncoder encoder =
new BCryptPasswordEncoder();
String hash =
encoder.encode("password");
Verification
encoder.matches(rawPassword,
encodedPassword);
Interview Tip: Never store plain-text passwords.
Always store hashed passwords.
BCrypt is the most commonly used password hashing algorithm in Spring Security.
Features
- One-way hashing
- Automatically generates a random salt
- Configurable work factor
- Resistant to rainbow-table attacks
Example
BCryptPasswordEncoder encoder =
new BCryptPasswordEncoder();
Interview Tip: Do not compare encoded passwords using equals().
Always use matches().
JWT (JSON Web Token) is a stateless authentication mechanism.
Flow
Login
β
Username + Password
β
JWT Generated
β
Client Stores Token
β
Every Request
β
Authorization:
Bearer JWT
β
JWT Validation
β
Controller
A JWT typically contains:
- Header
- Payload (claims)
- Signature
Advantages
- Stateless
- Scalable
- Suitable for microservices
- No server-side session storage
Interview Tip: The server validates the JWT on every request but does not usually store session state.
OAuth2 is an authorization framework that allows users to grant an application limited access to their resources without sharing their password.
Example
Login with Google
Login with GitHub
Login with Facebook
Main Roles
- Resource Owner
- Client
- Authorization Server
- Resource Server
Interview Tip: OAuth2 is for authorization/delegated access, while OpenID Connect (OIDC) adds an identity layer for authentication.
| Session | JWT |
|---|---|
| Server stores session | Client stores token |
| Stateful | Stateless |
| Session ID in cookie | JWT in Authorization header |
| Better for traditional web apps | Better for REST APIs and microservices |
| Harder to scale across servers without shared session storage | Easier to scale |
Interview Tip: Modern microservices usually prefer JWT because it supports stateless authentication.
In stateless authentication, the server does not store any client session.
Each request contains all the information needed for authentication.
Example
Request
β
Authorization:
Bearer JWT
β
Validate Token
β
Process Request
Advantages
- Scalable
- No session management
- Ideal for distributed systems
Interview Tip: JWT-based authentication is a common implementation of stateless authentication.
SecurityFilterChain is the central configuration mechanism for Spring Security in modern Spring Boot.
Example
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
It defines:
- Authentication rules
- Authorization rules
- CORS
- CSRF
- Session management
- Filters
Interview Tip: WebSecurityConfigurerAdapter has been deprecated. SecurityFilterChain is the recommended approach in Spring Security 6 / Spring Boot 3.
OncePerRequestFilter guarantees that a filter executes only once per HTTP request.
It is commonly used to validate JWT tokens.
Example
public class JwtAuthenticationFilter
extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
// Validate JWT
filterChain.doFilter(request, response);
}
}
Interview Tip: Most custom JWT authentication filters extend OncePerRequestFilter.
CORS (Cross-Origin Resource Sharing) controls whether a browser allows a frontend from one origin to access resources on another origin.
Example
Frontend
http://localhost:3000
Backend
http://localhost:8080
Without CORS configuration, the browser blocks the request.
Example configuration
http.cors(Customizer.withDefaults());
Interview Tip: CORS is enforced by browsers, not by Spring itself.
CSRF (Cross-Site Request Forgery) is an attack where a malicious website tricks an authenticated user into performing unintended actions.
Spring Security enables CSRF protection by default for browser-based applications.
For stateless REST APIs using JWT, it is commonly disabled.
Example
http.csrf(csrf -> csrf.disable());
Interview Tip: Do not disable CSRF for traditional session-based web applications unless you understand the security implications. Disabling it is common for stateless JWT APIs.
Role-based authorization restricts access based on user roles.
Example
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**")
.hasRole("ADMIN")
.requestMatchers("/user/**")
.hasAnyRole("USER", "ADMIN")
)
Interview Tip: Authentication identifies the user; authorization checks whether the user’s role permits access.
Method Security secures individual service or controller methods using annotations.
Enable it
@EnableMethodSecurity
Example
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) {
}
}
Interview Tip: Method security provides fine-grained authorization even if URL-based security is already configured.
@PreAuthorize checks authorization before a method executes.
Example
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser() {
}
You can also use expressions:
@PreAuthorize("#id == authentication.principal.id")
or
@PreAuthorize("hasAnyRole('ADMIN','MANAGER')")
Interview Tip: @PreAuthorize is the most commonly used method security annotation in Spring Security.
@PostAuthorize performs authorization after the method executes.
Example
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long id) {
}
The method runs first, and then Spring evaluates the authorization expression against the returned object.
Interview Tip: Use @PostAuthorize only when authorization depends on the returned object. In most scenarios, @PreAuthorize is preferred because it prevents unauthorized method execution altogether.
K. Spring Boot Actuator
Spring Boot Actuator is one of the most commonly asked production-ready features in Spring Boot interviews. It helps monitor, manage, and troubleshoot applications running in production.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Spring Boot Actuator provides production-ready monitoring and management features for Spring Boot applications.
It exposes endpoints that provide information about the application’s:
- Health
- Metrics
- Environment
- Beans
- Mappings
- Logging
- Thread dumps
- Heap dumps
Dependency
org.springframework.boot
spring-boot-starter-actuator
Access endpoint
http://localhost:8080/actuator
Common Endpoints
| Endpoint | Purpose |
|---|---|
| /actuator/health | Health Status |
| /actuator/info | Application Information |
| /actuator/metrics | JVM & Application Metrics |
| /actuator/env | Environment Properties |
| /actuator/beans | Spring Beans |
| /actuator/mappings | REST API Mappings |
| /actuator/loggers | Logger Levels |
| /actuator/threaddump | Thread Dump |
| /actuator/heapdump | Heap Dump |
Interview Tip: Actuator is mainly used for monitoring, troubleshooting, and production support.
The Health endpoint shows whether the application is healthy and ready to serve requests.
URL
GET /actuator/health
Response
{
"status":"UP"
}
If the database is down
{
"status":"DOWN"
}
Spring automatically checks components like:
- Database
- Disk Space
- Redis
- RabbitMQ
- MongoDB
- Elasticsearch
(if configured)
Health Status
| Status | Meaning |
|---|---|
| UP | Working |
| DOWN | Failure |
| OUT_OF_SERVICE | Maintenance |
| UNKNOWN | Status unavailable |
Interview Tip: Kubernetes commonly uses /actuator/health for liveness and readiness probes.
Metrics provide runtime information about application performance.
Example
GET /actuator/metrics
Common Metrics
- JVM Memory
- CPU Usage
- Garbage Collection
- HTTP Requests
- Database Connections
- Thread Count
- Request Latency
Example
/actuator/metrics/http.server.requests
shows
- Total requests
- Average response time
- Status code distribution
Interview Tip: Metrics are commonly collected by Prometheus and visualized using Grafana.
The Info endpoint exposes custom application information.
Configuration
management.info.env.enabled=true
info.app.name=InterviewBliss
info.app.version=1.0
info.company=Quescol
Access
GET /actuator/info
Response
{
"app":{
"name":"InterviewBliss",
"version":"1.0"
},
"company":"Quescol"
}
Interview Tip: Useful for displaying application version, build information, Git commit, and deployment details.
Implement the HealthIndicator interface.
Example
@Component
public class DatabaseHealthIndicator
implements HealthIndicator {
@Override
public Health health() {
boolean dbUp = checkDatabase();
if (dbUp) {
return Health.up().build();
}
return Health.down()
.withDetail("Database", "Not Reachable")
.build();
}
}
Now
/actuator/health
includes your custom health indicator.
Interview Tip: Custom health checks are useful for checking:
- Third-party APIs
- Kafka
- Redis
- Payment Gateway
- External Microservices
In production, Actuator is integrated with monitoring tools.
Architecture
Spring Boot App
β
Actuator
β
Prometheus
β
Grafana
Typical Monitoring
- CPU Usage
- Memory Usage
- Response Time
- Error Rate
- JVM Heap
- GC Time
- Active Threads
- Database Connections
- HTTP Requests
Interview Tip: A common production stack is:
- Spring Boot Actuator
- Micrometer
- Prometheus
- Grafana
#
L. Logging
Logging is another favorite interview topic because it helps diagnose production issues.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
SLF4J (Simple Logging Facade for Java) is a logging abstraction.
It provides a common logging API while allowing different logging implementations underneath.
Example
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger =
LoggerFactory.getLogger(UserService.class);
Usage
logger.info("User created");
Why Use SLF4J?
- Decouples application code from logging implementation
- Easy to switch implementations
- Standard logging API
Interview Tip: SLF4J is not a logging framework.
It is only a facade.
Logback is the default logging framework used by Spring Boot.
Architecture
Application
β
SLF4J
β
Logback
β
Console/File
Configuration
logback.xml
or
logback-spring.xml
Advantages
- Fast
- Flexible
- Asynchronous logging support
- Rolling log files
- Pattern customization
Interview Tip: Spring Boot uses SLF4J + Logback by default.
Log levels control how much information is logged.
Levels
TRACE
DEBUG
INFO
WARN
ERROR
Configuration
logging.level.root=INFO
logging.level.com.company.service=DEBUG
Difference
| Level | Purpose |
|---|---|
| TRACE | Detailed execution flow |
| DEBUG | Debugging information |
| INFO | Normal application events |
| WARN | Potential problems |
| ERROR | Failures and exceptions |
Interview Tip: Production systems usually use:
INFO
WARN
ERROR
while DEBUG and TRACE are typically enabled temporarily during troubleshooting.
Structured logging stores logs in a machine-readable format (commonly JSON) instead of plain text.
Example
{
"timestamp":"2026-07-27T10:00:00Z",
"level":"INFO",
"service":"user-service",
"traceId":"abc123",
"message":"User created"
}
Advantages
- Easy searching
- Better analytics
- Centralized logging
- Works well with ELK/OpenSearch
Interview Tip: Structured logs are preferred in microservices because log aggregation tools can parse them efficiently.
MDC (Mapped Diagnostic Context) stores contextual information for the current thread so every log entry automatically includes it.
Example
MDC.put("requestId", "12345");
logger.info("Order Created");
Log
[requestId=12345]
Order Created
Uses
- User ID
- Request ID
- Tenant ID
- Trace ID
Interview Tip: Always clear MDC after the request completes to prevent data leakage between reused threads.
A Correlation ID uniquely identifies a request as it travels through multiple microservices.
Example
Client
β
API Gateway
β
Order Service
β
Payment Service
β
Inventory Service
All services log
Correlation-ID: abc123
This allows developers to trace the complete request.
Interview Tip: Correlation IDs are essential for debugging distributed systems.
Centralized logging collects logs from multiple applications into one place.
Architecture
Spring Boot Apps
β
Fluent Bit / Logstash
β
Elasticsearch (or OpenSearch)
β
Kibana
Advantages
- Single dashboard
- Faster debugging
- Searchable logs
- Log analytics
Interview Tip: A common production logging stack is:
- Logback
- Fluent Bit (or Logstash)
- Elasticsearch/OpenSearch
- Kibana
#
M. Caching
Caching is a very common product company interview topic, especially for performance optimization.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Caching stores frequently accessed data in fast memory to reduce database calls and improve performance.
Without Cache
Client
β
Database
β
Database
β
Database
With Cache
Client
β
Redis
β
Database (Only on Cache Miss)
Advantages
- Faster response time
- Reduced database load
- Better scalability
- Lower latency
Interview Tip: Cache should be used for data that is read frequently but changes infrequently.
@Cacheable stores a method’s result in the cache.
Example
@Cacheable("users")
public User getUser(Long id){
return repository.findById(id).orElseThrow();
}
First Call
Database
Second Call
Cache
Interview Tip: If the value exists in the cache, the method body is not executed.
@CachePut updates the cache every time the method executes.
Example
@CachePut(value="users",
key="#user.id")
public User update(User user){
return repository.save(user);
}
Unlike @Cacheable, the method always runs and the cache is refreshed with the returned value.
Interview Tip: Use @CachePut after updating data.
@CacheEvict removes data from the cache.
Example
@CacheEvict(value="users",
key="#id")
public void delete(Long id){
repository.deleteById(id);
}
Delete All Cache
@CacheEvict(value="users",
allEntries=true)
Interview Tip: Always evict or update cache after modifying data to avoid stale values.
Redis is an in-memory key-value database widely used as a distributed cache.
Architecture
Application
β
Redis
β
Database
Workflow
- Check Redis.
- If present β return cached data.
- If absent β query database.
- Store result in Redis.
- Return response.
Advantages
- Extremely fast (memory-based)
- Supports TTL (Time-To-Live)
- Distributed cache
- Supports clustering and replication
Interview Tip: Redis is the most commonly used cache in Spring Boot microservices.
Cache Aside (Lazy Loading) is the most common caching strategy.
Flow
Request
β
Cache
β
Hit?
β
Yes β Return
β
No
β
Database
β
Store in Cache
β
Return
Advantages
- Simple
- Efficient
- Cache only stores requested data
Interview Tip: Spring’s @Cacheable naturally follows the Cache Aside pattern.
Cache invalidation ensures that cached data stays consistent with the database after updates.
Common Strategies
1. Time-To-Live (TTL)
Automatically expire cache entries after a fixed time.
Example
TTL = 10 minutes
2. Explicit Eviction
Remove cache immediately after update or delete.
Example
@CacheEvict(value = "users", key = "#id")
3. Cache Refresh
Update the cache with the latest value after modifying the database.
Example
@CachePut(value = "users", key = "#user.id")
Interview Tip: A stale cache can return outdated data. A robust caching strategy always defines when to refresh, evict, or expire cached entries to maintain consistency between the cache and the database.
N. Scheduling & Async
Scheduling and Asynchronous processing are very common interview topics, especially for 2+ years experienced developers. Interviewers often ask about @Scheduled, @Async, ThreadPoolTaskExecutor, and CompletableFuture.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
@Scheduled is used to execute a method automatically at fixed intervals or specific times.
Before using it, scheduling must be enabled.
Java@EnableScheduling
@SpringBootApplication
public class Application {
}
Example
Java@Component
public class ReportScheduler {
@Scheduled(fixedRate = 5000)
public void generateReport() {
System.out.println(“Generating Report…”);
}
}
The method executes every 5 seconds.
Real-world Example
–
Daily report generation
–
Email notifications
–
Database cleanup
–
Session cleanup
–
Cache refresh
Interview Tip
@Scheduled methods:
–
Should return void
–
Should not accept parameters
–
Are managed by Spring
- Fixed Delay vs Fixed Rate
Fixed Rate
Runs after a fixed interval measured from the start of the previous execution.
Java@Scheduled(fixedRate = 5000)
Timeline
Start —-5s—- Start —-5s—- Start
If execution takes longer than the interval, executions may overlap when using a scheduler with multiple threads.
Fixed Delay
Runs after a fixed interval measured from the end of the previous execution.
Java@Scheduled(fixedDelay = 5000)
Timeline
Start —- End —-5s—- Start
No overlap for the same scheduled task because Spring waits until the previous execution completes before applying the delay.
Difference
Fixed RateFixed DelayTime counted from method startTime counted from method completionCan overlap with a multi-threaded schedulerWaits until previous execution finishesBetter for periodic tasksBetter for long-running tasks
Interview Tip
For long-running jobs, fixedDelay is generally safer to avoid overlapping executions.
Cron expressions schedule tasks at specific times.
Example
Java@Scheduled(cron = “0 0 2 * * *”)
Runs every day at 2:00 AM.
Cron Format
Second Minute Hour Day Month DayOfWeek
Example
0 0 12 * * *
β
Every day at 12 PM
Common Examples
CronMeaning0 * * * * *Every minute0 0 * * * *Every hour0 0 2 * * *Every day at 2 AM0 0 9 * * MON-FRIWeekdays at 9 AM
Interview Tip
Cron provides much more flexibility than fixedRate or fixedDelay.
@EnableScheduling enables Spring’s scheduling support.
Example
Java@Configuration
@EnableScheduling
public class SchedulerConfig {
}
Without this annotation, @Scheduled methods are ignored.
Interview Tip
@EnableScheduling is required only once in the application.
@Async executes a method asynchronously in a separate thread.
Example
Java@Service
public class EmailService {
@Async
public void sendEmail(){
}
}
Caller
β
Returns immediately
β
Email executes in the background.
Real-world Example
–
Email sending
–
SMS
–
Push Notifications
–
PDF generation
–
Report generation
Interview Tip
Enable async support with
Java@EnableAsync
CompletableFuture represents the result of an asynchronous computation.
Example
Java@Async
public CompletableFuture<String> process(){
return CompletableFuture.completedFuture(“Done”);
}
Usage
JavaCompletableFuture<String> future = service.process();
String result = future.get();
Advantages
–
Async programming
–
Callback support
–
Parallel execution
–
Combine multiple async tasks
Interview Tip
CompletableFuture is preferred over the old Future because it supports chaining, callbacks, composition, and better exception handling.
By default, Spring uses a simple async executor.
In production, we should configure our own thread pool.
Example
Java@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor(){
ThreadPoolTaskExecutor executor =
new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.initialize();
return executor;
}
}
Interview Tip
Avoid relying on the default executor in production because it is usually not tuned for your workload.
ThreadPoolTaskExecutor manages a pool of reusable threads for asynchronous tasks.
Architecture
Task
β
Thread Pool
β
Worker Thread
β
Execute Task
Instead of creating a new thread for every request, existing threads are reused.
Advantages
–
Better performance
–
Controlled thread creation
–
Reduced memory usage
–
High scalability
Interview Tip
In production, always use a properly sized thread pool instead of creating threads manually.
##
O. Spring Boot Testing
Testing is one of the most frequently asked Spring Boot interview topics, especially for experienced developers.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Unit Testing verifies an individual class or method in isolation.
Dependencies are mocked.
Example
Java@Test
void testAdd(){
assertEquals(5, calculator.add(2,3));
}
Tools
–
JUnit 5
–
Mockito
Interview Tip
Unit tests are:
–
Fast
–
Independent
–
No database required
Integration Testing verifies how multiple components work together.
Example
Controller
β
Service
β
Repository
β
Database
All layers are tested together.
Interview Tip
Integration tests are slower than unit tests but validate real application behavior.
@SpringBootTest loads the entire Spring Boot application context.
Example
Java@SpringBootTest
class UserServiceTest {
}
Suitable for:
–
Integration testing
–
End-to-end Spring context testing
Interview Tip
@SpringBootTest is slower because it starts the full application context.
@WebMvcTest loads only the Spring MVC layer.
Example
Java@WebMvcTest(UserController.class)
class UserControllerTest {
}
Loaded
–
Controller
–
Spring MVC
–
Validation
Not Loaded
–
Service
–
Repository
–
Database
Interview Tip
Use @MockBean (or @MockitoBean in newer Spring Boot versions) for service dependencies when using @WebMvcTest.
@DataJpaTest loads only the JPA components.
Loads
–
Entity
–
Repository
–
Hibernate
Does not load
–
Controller
–
Service
Example
Java@DataJpaTest
class UserRepositoryTest {
}
Interview Tip
Usually uses an embedded database by default unless configured otherwise.
@MockBean replaces a Spring bean with a Mockito mock in the application context.
Example
Java@WebMvcTest(UserController.class)
class UserControllerTest {
@MockBean
private UserService service;
}
Now Spring injects the mock instead of the real service.
Interview Tip
Use @MockBean when testing Spring components that depend on other beans.
Mockito is a Java mocking framework.
Example
Javawhen(service.getUser(1L))
.thenReturn(user);
Verification
Javaverify(service).getUser(1L);
Advantages
–
Mock dependencies
–
Verify method calls
–
Simulate exceptions
–
Isolate units under test
Interview Tip
Mockito is commonly used together with JUnit 5.
MockMvc tests Spring MVC controllers without starting a real HTTP server.
Example
JavamockMvc.perform(get(“/users”))
.andExpect(status().isOk());
Advantages
–
Fast
–
No Tomcat required
–
Tests REST endpoints
Interview Tip
Commonly used with @WebMvcTest.
Testcontainers is a Java library that starts real Docker containers for integration testing.
Example
JUnit
β
Docker
β
MySQL Container
β
Run Tests
Instead of using an in-memory database, tests run against the same database technology used in production.
Advantages
–
Real database testing
–
Isolated environment
–
Repeatable tests
–
Better production parity
Interview Tip
Product companies increasingly prefer Testcontainers over H2 because they reduce differences between test and production environments.
##
P. Spring Boot Internals
Spring Boot Internals is a favorite topic in product-based company interviews. Interviewers want to know what happens behind the scenes, not just how to use annotations.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
When main() calls SpringApplication.run(), Spring Boot performs the following steps:
main()
β
SpringApplication.run()
β
Prepare Environment
β
Create ApplicationContext
β
Load Configuration
β
Component Scan
β
Auto Configuration
β
Create Beans
β
Start Embedded Server
β
Application Ready
Detailed Steps
- Create SpringApplication
- Determine application type (Servlet/Reactive/Non-Web)
- Prepare Environment
- Create ApplicationContext
- Register configuration classes
- Perform component scanning
- Apply auto-configuration
- Instantiate singleton beans
- Start embedded server
- Run CommandLineRunner / ApplicationRunner
Interview Tip: This is one of the most frequently asked Spring Boot internals questions.
Execution Flow
main()
β
SpringApplication.run()
β
Environment
β
ApplicationContext
β
BeanFactory
β
Component Scan
β
Auto Configuration
β
Bean Creation
β
Tomcat Starts
β
Application Ready
Interview Tip: Mention:
- Environment preparation
- Bean creation
- Embedded server startup
Bean creation process
@Component
β
Component Scan
β
Bean Definition
β
BeanFactory
β
Object Creation
β
Dependency Injection
β
@PostConstruct
β
Ready
Steps
- Scan classes
- Register bean definitions
- Instantiate bean
- Inject dependencies
- Invoke lifecycle callbacks
- Store singleton bean in the container
Interview Tip: Spring creates singleton beans eagerly by default during context initialization unless they are marked as lazy.
@ComponentScan searches packages for stereotype annotations.
It detects:
- @Component
- @Service
- @Repository
- @Controller
- @RestController
Example
com.company
β
controller
β
service
β
repository
All discovered classes are registered as beans.
Interview Tip: Scanning starts from the package containing the @SpringBootApplication class and includes its subpackages by default.
Auto Configuration configures beans based on:
- Classpath
- Existing beans
- Configuration properties
Flow
Dependency Present
β
Check Conditions
β
Conditions Match
β
Create Bean
Example
If
spring-boot-starter-data-jpa
exists,
Spring automatically configures:
- DataSource
- EntityManager
- TransactionManager
using conditional annotations such as:
- @ConditionalOnClass
- @ConditionalOnMissingBean
- @ConditionalOnProperty
Interview Tip: Auto Configuration is driven by conditional annotations.
In older Spring Boot versions (primarily Boot 2.x and earlier), spring.factories was used to register auto-configuration classes and other extension points.
Location
META-INF/spring.factories
Example
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
com.example.MyAutoConfiguration
Interview Tip: For Spring Boot 3.x, AutoConfiguration.imports is the preferred mechanism for auto-configuration registration, while spring.factories is still used for some other extension points.
Spring Boot 3 introduced:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
This file lists auto-configuration classes to be loaded.
Example
com.example.MyAutoConfiguration
com.example.SecurityAutoConfiguration
Benefits
- Faster startup
- Simpler registration
- Better maintainability
Interview Tip: Spring Boot 3 uses AutoConfiguration.imports instead of spring.factories for discovering auto-configuration classes.
| BeanFactory | ApplicationContext |
|---|---|
| Basic IoC container | Advanced Spring container |
| Lazy bean creation by default | Eager singleton initialization by default |
| Minimal features | Supports events, internationalization, resource loading, AOP integration, environment, etc. |
| Lightweight | Enterprise-ready |
Interview Tip: ApplicationContext extends BeanFactory and is used in almost all Spring Boot applications.
BeanPostProcessor allows customization of beans before and after initialization.
Methods
postProcessBeforeInitialization()
postProcessAfterInitialization()
Flow
Bean Created
β
Before Initialization
β
@PostConstruct
β
After Initialization
β
Ready
Uses
- Logging
- Proxy creation
- Custom initialization
- Framework integrations
Interview Tip: Many Spring features, including AOP proxy creation, rely on BeanPostProcessor.
FactoryBean is a special Spring interface used when the bean creation process is complex.
Instead of returning the FactoryBean itself, Spring returns the object produced by it.
Example
public class UserFactoryBean
implements FactoryBean {
@Override
public User getObject() {
return new User();
}
}
Interview Tip: A FactoryBean creates other objects. If you actually want the FactoryBean instance itself, retrieve it using the bean name prefixed with &.
A circular dependency occurs when two or more beans depend on each other.
Example
Service A
β
Service B
β
Service A
Example
@Service
class A {
public A(B b){}
}
@Service
class B {
public B(A a){}
}
Result
BeanCurrentlyInCreationException
(for constructor injection)
Solutions
- Redesign to remove the cycle (preferred)
- Use @Lazy in limited cases
- Extract shared logic into another bean
Interview Tip: Constructor injection exposes circular dependencies immediately, which is one reason it is preferred.
Spring creates proxies to implement features such as:
- Transactions (@Transactional)
- Security
- Caching
- Async (@Async)
- AOP
Flow
Client
β
Proxy
β
Actual Bean
The proxy intercepts method calls and adds cross-cutting behavior before or after invoking the target object.
Proxy Types
- JDK Dynamic Proxy β Used when the target implements an interface.
- CGLIB Proxy β Used when no suitable interface exists (or class-based proxying is enabled).
Example
@Transactional
public void transferMoney() {
}
Execution
Client
β
Transaction Proxy
β
Begin Transaction
β
Method Execution
β
Commit / Rollback
Interview Tip: One of the most common Spring interview questions is:
How does @Transactional work internally?
A strong answer is:
- Spring uses AOP proxies.
- The proxy intercepts the method call.
- It starts a transaction before the target method executes.
- If the method completes successfully, it commits the transaction.
- If an eligible exception occurs, it rolls back the transaction.
- The proxy then returns the result (or propagates the exception) to the caller.
Q. Performance & Optimization
Performance optimization is a favorite topic in product-based company interviews, especially for developers with 3+ years of experience. Interviewers expect you to know how to optimize startup time, database access, memory usage, and application throughput.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
There is no single optimization. We improve performance at multiple layers.
Common Techniques
–
Use HikariCP for database connection pooling.
–
Enable caching (Redis, Caffeine).
–
Use LAZY fetching where appropriate.
–
Optimize SQL queries and add proper indexes.
–
Avoid N+1 query problems.
–
Use pagination instead of loading large datasets.
–
Use asynchronous processing for long-running tasks.
–
Tune JVM heap and garbage collection.
–
Reduce unnecessary Spring Beans.
–
Enable compression (GZIP) for REST APIs.
–
Monitor using Actuator, Micrometer, Prometheus, and Grafana.
Real-world Example
Without optimization
Client
β
Database
β
Database
β
Database
With optimization
Client
β
Redis Cache
β
Database (only on cache miss)
Interview Tip
If asked:
How did you improve performance in your project?
A good answer is:
“We optimized SQL queries, introduced Redis caching, switched expensive relationships to lazy loading where appropriate, enabled pagination, configured HikariCP, and monitored performance using Actuator with Prometheus and Grafana.”
By default, Spring creates singleton beans during application startup.
Lazy Initialization delays bean creation until the bean is actually required.
Example
Java@Component
@Lazy
public class ReportService {
}
Bean is created only when first used.
Advantages
–
Faster startup
–
Lower memory usage at startup
–
Avoids creating unused beans
Disadvantages
–
First access may be slower
–
Startup errors may appear later instead of during application startup
Interview Tip
Use lazy initialization only for expensive or rarely used beans.
Creating a database connection for every request is expensive.
Connection Pooling maintains a pool of reusable database connections.
Without Pool
Request
β
Create Connection
β
Query
β
Close Connection
With Pool
Request
β
Connection Pool
β
Existing Connection
β
Database
Advantages
–
Faster response
–
Better scalability
–
Less database overhead
–
Efficient resource utilization
Interview Tip
Every production application should use a connection pool.
HikariCP is the default JDBC connection pool in Spring Boot.
It is known for:
–
High performance
–
Low latency
–
Small memory footprint
–
Fast connection acquisition
Configuration
propertiesspring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
Common Configuration
PropertyMeaningmaximumPoolSizeMaximum connectionsminimumIdleMinimum idle connectionsconnectionTimeoutWait time for a connectionidleTimeoutIdle connection timeoutmaxLifetimeMaximum lifetime of a connection
Interview Tip
Spring Boot automatically uses HikariCP if it is available on the classpath.
JVM tuning improves memory usage and garbage collection performance.
Common JVM options
-Xms512m
-Xmx2g
Meaning
–
Xms β Initial Heap Size
–
Xmx β Maximum Heap Size
Other areas
–
Garbage Collector selection (e.g., G1 GC, ZGC depending on Java version and workload)
–
Heap sizing
–
Thread count
–
Metaspace sizing
–
GC monitoring
Interview Tip
You don’t need to memorize many JVM flags. Understand:
–
Heap size
–
Garbage Collection
–
Monitoring using GC logs or tools
Common techniques
–
Remove unused dependencies.
–
Enable lazy initialization where appropriate.
–
Reduce component scanning scope.
–
Disable unnecessary auto-configurations.
–
Reduce unnecessary bean creation.
–
Optimize database initialization.
–
Avoid expensive work in constructors or @PostConstruct.
–
Use Spring AOT/native image where suitable (for compatible workloads).
Interview Tip
Large enterprise applications often have startup delays due to excessive bean creation and unnecessary auto-configuration.
Database optimization includes:
–
Proper indexing
–
Optimized SQL queries
–
Pagination
–
Batch inserts/updates
–
Lazy loading
–
Caching
–
Avoiding N+1 queries
–
Using connection pooling
–
Selecting only required columns instead of SELECT *
Interview Tip
Database optimization usually provides greater performance improvements than Java code optimization.
The N+1 Query Problem occurs when one query loads parent records and additional queries are executed for each parent to load related data.
Example
Load Departments
β
1 Query
Then load Employees
β
100 Queries
Total
101 Queries
Solution
–
Fetch Join
–
Entity Graph
–
Batch Fetching
–
DTO projections (when only specific fields are needed)
Example
Java@Query(“””
SELECT d
FROM Department d
JOIN FETCH d.employees
“””)
Interview Tip
N+1 is one of the most common Hibernate performance issues.
Batch Processing executes many records together instead of one by one.
Instead of
Insert
Insert
Insert
Insert
Use
Batch Insert
Hibernate
propertiesspring.jpa.properties.hibernate.jdbc.batch_size=50
Advantages
–
Fewer database round trips
–
Better throughput
–
Reduced network overhead
Interview Tip
Use batching for:
–
Bulk inserts
–
Bulk updates
–
Data migration
–
ETL jobs
##
R. Microservices Integration
Microservices are among the most important topics for experienced Spring Boot developers. Interviewers often ask about Spring Cloud, Eureka, Gateway, Feign, Resilience4j, Config Server, and distributed systems.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Spring Cloud provides tools for building distributed microservices.
It solves common microservice problems such as:
–
Service Discovery
–
Configuration Management
–
API Gateway
–
Load Balancing
–
Circuit Breaker
–
Distributed Tracing
–
Messaging
Architecture
Client
β
API Gateway
β
User Service
β
Order Service
β
Payment Service
Common Spring Cloud Components
–
Eureka
–
Config Server
–
OpenFeign
–
Spring Cloud Gateway
–
Resilience4j
–
Spring Cloud LoadBalancer
Interview Tip
Spring Boot builds microservices.
Spring Cloud helps them communicate and operate together.
Eureka is a Service Registry.
Instead of hardcoding service URLs, services register themselves with Eureka.
Architecture
User Service
β
Eureka Server
β
Order Service
Each service registers its own address.
Advantages
–
Dynamic registration
–
Dynamic discovery
–
No hardcoded URLs
Interview Tip
Eureka is the service registry used in the Spring Cloud Netflix ecosystem.
Service Discovery allows one microservice to locate another without hardcoded URLs.
Without Discovery
Order Service
β
http://localhost:8082
With Discovery
Order Service
β
USER-SERVICE
Eureka resolves the actual instance.
Interview Tip
Service Discovery enables dynamic scaling because instances can be added or removed without changing client configuration.
API Gateway is the single entry point for all client requests.
Architecture
Client
β
API Gateway
β
User Service
β
Payment Service
β
Order Service
Responsibilities
–
Authentication
–
Routing
–
Rate Limiting
–
Logging
–
Load Balancing
–
CORS
Interview Tip
Spring Cloud Gateway is the recommended gateway for modern Spring Boot applications.
OpenFeign simplifies REST communication between microservices.
Without Feign
Use RestTemplate or WebClient.
With Feign
Java@FeignClient(name = “USER-SERVICE”)
public interface UserClient {
@GetMapping(“/users/{id}”)
User getUser(@PathVariable Long id);
}
Spring generates the implementation automatically.
Advantages
–
Less boilerplate
–
Declarative REST client
–
Easy integration with service discovery
Interview Tip
Feign integrates seamlessly with Eureka and Spring Cloud LoadBalancer.
Load Balancing distributes requests across multiple service instances.
Example
Gateway
β
User Service 1
β
User Service 2
β
User Service 3
This prevents overloading a single instance.
Interview Tip
Modern Spring Cloud uses Spring Cloud LoadBalancer for client-side load balancing.
A Circuit Breaker prevents repeated calls to a failing service.
Without Circuit Breaker
Service A
β
Service B (Down)
β
Timeout
β
Timeout
β
Timeout
With Circuit Breaker
Service A
β
Circuit Open
β
Fallback
Advantages
–
Prevents cascading failures
–
Faster failure response
–
Improves resilience
Interview Tip
Resilience4j is the preferred circuit breaker library in modern Spring Boot.
Retry automatically attempts a failed operation again before giving up.
Example
Call
β
Fail
β
Retry
β
Success
Typical uses
–
Temporary network issues
–
Database connection hiccups
–
External API timeouts
Interview Tip
Always configure:
–
Maximum retry attempts
–
Backoff delay
Avoid infinite retries.
Spring Cloud Config Server centralizes configuration for multiple microservices.
Architecture
Git Repository
β
Config Server
β
User Service
β
Order Service
β
Payment Service
Instead of storing configuration in every service, all services retrieve it from the Config Server.
Advantages
–
Centralized configuration
–
Easy environment management
–
Dynamic refresh (when configured)
Interview Tip
Configuration changes can often be refreshed without rebuilding every service, depending on the refresh mechanism used.
Distributed Tracing tracks a request across multiple microservices.
Example
Client
β
Gateway
β
Order Service
β
Payment Service
β
Inventory Service
All services share the same Trace ID.
Tools
–
OpenTelemetry
–
Jaeger
–
Zipkin
–
Grafana Tempo
Interview Tip
Distributed tracing makes it much easier to identify where latency or failures occur in a microservice request flow.
A Feign Interceptor automatically adds headers to outgoing Feign requests.
Example
Java@Bean
public RequestInterceptor requestInterceptor() {
return template -> {
template.header(“Authorization”, “Bearer ” + token);
};
}
Common uses
–
JWT propagation
–
Correlation ID
–
Custom headers
–
Tenant ID
Interview Tip
Feign Interceptors help avoid duplicating header-setting logic across multiple Feign clients.
Resilience4j is a lightweight fault-tolerance library used with Spring Boot.
Features
–
Circuit Breaker
–
Retry
–
Rate Limiter
–
Bulkhead
–
Time Limiter
Example
Java@CircuitBreaker(
name = “paymentService”,
fallbackMethod = “fallback”
)
public Payment getPayment() {
}
Interview Tip
Resilience4j replaced Netflix Hystrix, which is now in maintenance mode.
Rate Limiting restricts how many requests a client can make within a given time period.
Example
100 Requests
β
1 Minute
β
Allowed
101st request
β
HTTP 429
Too Many Requests
Why Use Rate Limiting?
–
Prevent abuse
–
Protect backend services
–
Avoid DoS-style overload
–
Ensure fair resource usage
Interview Tip
Rate limiting can be implemented at:
–
API Gateway (most common)
–
Application level (e.g., Resilience4j RateLimiter or Bucket4j)
–
Reverse proxy (e.g., NGINX)
In microservices, the API Gateway is often the preferred place because it protects all downstream services consistently.
<button type=”button” class=”text-token-text-secondary hover:bg-token-surface-hover rounded-lg” aria-label=”Copy response”
S. Production & Deployment
Production and Deployment topics are very common in interviews for experienced developers (3+ years). Interviewers want to know how you deploy, configure, and operate Spring Boot applications in real-world environments.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
External Configuration means keeping configuration outside the application code so that the same application can run in different environments without rebuilding it.
Instead of hardcoding values
String dbUrl = "jdbc:mysql://localhost:3306/demo";
use
spring.datasource.url=${DATABASE_URL}
Configuration sources (highest priority first)
- Command-line arguments
- Environment variables
- JVM System properties
- External application.properties / application.yml
- Internal application.properties
- Default values in code
Advantages
- No code changes between environments
- Better security
- Easier deployment
- Supports cloud-native applications
Interview Tip: Never hardcode:
- Database Passwords
- JWT Secret
- API Keys
- AWS Credentials
Docker packages the application along with its runtime and dependencies into a portable container.
Example Dockerfile
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
Build Image
docker build -t user-service .
Run Container
docker run -p 8080:8080 user-service
Advantages
- Same environment everywhere
- Easy deployment
- Faster scaling
- Better portability
Interview Tip: Most microservices today are deployed as Docker containers.
Kubernetes manages containerized applications.
Basic Architecture
User
β
Ingress
β
Service
β
Pod
β
Container
Example Deployment
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 3
Three pods will run simultaneously.
Kubernetes Components
- Pod
- Deployment
- Service
- ConfigMap
- Secret
- Ingress
Interview Tip: Deployment manages Pods.
Service exposes Pods.
Health checks determine whether an application is running correctly.
Spring Boot provides
/actuator/health
Example
{
"status":"UP"
}
or
{
"status":"DOWN"
}
Interview Tip: Kubernetes uses health checks to decide whether traffic should be sent to the application.
A Readiness Probe checks whether the application is ready to receive traffic.
Example
Application Started
β
Database Connected
β
Ready
β
Receive Requests
If the readiness probe fails
β
No traffic is routed to that Pod.
Interview Tip: Readiness indicates “Can I serve requests?”
A Liveness Probe checks whether the application is still alive.
Example
Application Running
β
Deadlock
β
No Response
β
Restart Pod
Difference
| Readiness | Liveness |
|---|---|
| Ready to receive traffic | Application still alive |
| Removes Pod from load balancing | Restarts unhealthy Pod |
Interview Tip: Readiness prevents traffic.
Liveness restarts the application.
Graceful Shutdown allows the application to finish in-flight requests before shutting down.
Without Graceful Shutdown
Shutdown
β
Current Requests Lost
With Graceful Shutdown
Shutdown
β
Complete Existing Requests
β
Stop Application
Configuration
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=30s
Advantages
- No request loss
- Better user experience
- Safe deployment
Interview Tip: Essential in Kubernetes rolling deployments.
Different environments require different configurations.
Example
application-dev.properties
application-test.properties
application-prod.properties
Activate
spring.profiles.active=prod
Development
server.port=8081
Production
server.port=8080
Interview Tip: Use Profiles rather than modifying application files before deployment.
#
T. Frequently Asked Scenario Questions
These questions test your real-world experience, not just your knowledge of annotations.
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Implementation Steps
- Spring Security authenticates the user.
- Generate a JWT containing user details and roles.
- Return the JWT to the client.
- Client sends the JWT in the Authorization header.
- A custom OncePerRequestFilter validates the token.
- If valid, store the authenticated user in the SecurityContext.
Flow
Login
β
Authenticate
β
Generate JWT
β
Client Stores Token
β
Authorization: Bearer
β
JWT Filter
β
Controller
Interview Tip: Always mention:
- Spring Security
- JWT
- OncePerRequestFilter
- SecurityFilterChain
- Stateless Authentication
Store user roles such as:
- ADMIN
- USER
- MANAGER
Protect endpoints
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser() {
}
or
.authorizeHttpRequests(auth ->
auth.requestMatchers("/admin/**")
.hasRole("ADMIN"))
Interview Tip: Authentication verifies identity.
Authorization checks permissions.
A production approach includes:
- Use streaming instead of loading the entire file into memory.
- Configure multipart size limits.
- Store the file directly on disk or object storage (e.g., S3) instead of keeping it in memory.
- Process the file asynchronously if needed.
- Validate file type and size.
- Support resumable uploads for unreliable networks if required.
Interview Tip: Never read a 500 MB file completely into memory.
Typical optimization steps:
- Enable SQL logging to identify slow queries.
- Add database indexes.
- Eliminate N+1 queries.
- Introduce Redis caching.
- Enable pagination.
- Configure HikariCP properly.
- Use lazy loading where appropriate.
- Profile CPU and memory usage.
- Monitor with Actuator + Prometheus + Grafana.
Interview Tip: Start by identifying the bottleneck instead of optimizing blindly.
Steps
- Check application metrics using Actuator.
- Capture a thread dump (jstack).
- Identify busy threads.
- Analyze GC behavior.
- Profile the application using tools such as Java Flight Recorder (JFR) or VisualVM.
- Review logs.
- Identify infinite loops or expensive queries.
Interview Tip: High CPU is often caused by:
- Infinite loops
- Excessive logging
- Heavy computations
- Poor SQL
- Frequent garbage collection
- Remove unused dependencies.
- Reduce component scanning.
- Use lazy initialization selectively.
- Disable unnecessary auto-configurations.
- Optimize bean initialization.
- Avoid heavy work in @PostConstruct.
- Consider Spring AOT/native image when appropriate.
Interview Tip: Large applications spend most startup time creating beans.
Use
@RestControllerAdvice
with
@ExceptionHandler
Return a consistent error object.
Benefits
- Reusable
- Cleaner controllers
- Consistent responses
Interview Tip: Never use try-catch in every controller.
Log every important business event.
Examples
- User Login
- Payment
- Order Creation
- Profile Update
Store
- User ID
- Timestamp
- Action
- IP Address
- Request ID
Use asynchronous logging (or messaging such as Kafka) to reduce request latency.
Interview Tip: Audit logs should be immutable and separate from application debug logs.
Use
- Redis
- @Cacheable
- Cache Aside Pattern
Flow
Request
β
Cache
β
Hit?
β
Yes
β
Return
β
No
β
Database
β
Cache
β
Return
Interview Tip: Evict or refresh the cache after updates to avoid stale data.
Common approaches
- Idempotency Key
- Unique Database Constraints
- Distributed Lock (Redis)
- Request Token
- Optimistic Locking (where applicable)
Payment Example
Client
β
Idempotency-Key
β
Server
β
Already Processed?
β
Return Previous Response
Interview Tip: Payment APIs usually use Idempotency Keys.
Options
- Optimistic Locking
- Pessimistic Locking
- Appropriate transaction isolation
- Retry on conflict (where suitable)
Interview Tip: Optimistic locking is generally preferred when conflicts are infrequent.
Optimistic Locking
Uses
@Version
private Long version;
If another transaction updates the record first
β
OptimisticLockException
Best for
- High-read
- Low-write contention
Pessimistic Locking
Locks the database row immediately.
@Lock(LockModeType.PESSIMISTIC_WRITE)
Best for
- Banking
- Inventory
- Financial systems
Difference
| Optimistic | Pessimistic |
|---|---|
| No lock until update | Locks row immediately |
| Better concurrency | Lower concurrency |
| Retry on conflict | Wait for lock |
Interview Tip: Optimistic locking is the default choice in most enterprise applications.
A scalable architecture includes:
- Horizontal scaling
- Load Balancer
- API Gateway
- Redis Cache
- Database indexing
- Asynchronous processing
- Kafka/RabbitMQ for background work
- CDN (where applicable)
- Rate Limiting
- Auto Scaling
Architecture
Load Balancer
β
API Gateway
β
Microservices
β
Redis
β
Database
Interview Tip: Scaling horizontally is usually preferred over scaling a single server vertically.
Approaches
- PUT for full updates
- DELETE for deletions
- Idempotency-Key for POST operations
- Database uniqueness constraints
Example
Idempotency-Key
β
Already Exists?
β
Yes
β
Return Previous Response
Interview Tip: Payment APIs almost always implement idempotency.
Use Spring Data Pageable.
Example
Page findAll(Pageable pageable);
Request
GET /users?page=0&size=20
Benefits
- Lower memory usage
- Faster responses
- Reduced database load
Interview Tip: Never return millions of records in a single response.
Never hardcode secrets.
Use
- Environment Variables
- Kubernetes Secrets
- HashiCorp Vault
- AWS Secrets Manager
- Azure Key Vault
- Google Secret Manager
Example
spring.datasource.password=${DB_PASSWORD}
Interview Tip: Production secrets should come from a secure secrets management solution, not from Git repositories.
Use
- OpenFeign
- Spring Cloud LoadBalancer
- Timeouts
- Retry
- Circuit Breaker (Resilience4j)
- Fallback methods
- Distributed tracing
Flow
Service A
β
Feign Client
β
Circuit Breaker
β
Service B
Interview Tip: Always configure connection/read timeouts and circuit breakers for external service calls.
Use
- Circuit Breaker
- Retry
- Time Limiter
- Bulkhead
- Fallback Method
Example
@CircuitBreaker(
name = "paymentService",
fallbackMethod = "fallback")
If the service repeatedly fails
β
Circuit opens
β
Fallback executes
Interview Tip: Resilience4j prevents cascading failures in microservices.
Use
- Correlation ID
- Trace ID
- OpenTelemetry
- Jaeger
- Zipkin
- Grafana Tempo
Flow
Gateway
β
Order Service
β
Payment Service
β
Inventory Service
All services log the same Trace ID.
Interview Tip: Correlation IDs make debugging distributed systems much easier.
Enable graceful shutdown.
server.shutdown=graceful
During shutdown
- Stop accepting new requests.
- Allow existing requests to complete.
- Close resources.
- Shut down the application.
Interview Tip: Graceful shutdown is essential for rolling deployments in Kubernetes.
Most common approach
/api/v1/users
/api/v2/users
Other options
- Header versioning
- Request parameter versioning
Best Practice
Keep old versions available until clients migrate.
Interview Tip: URI versioning is the most widely used approach because it is simple and explicit.
Steps
- Monitor heap usage (Actuator/JMX).
- Capture a heap dump (jmap or on OOM).
- Analyze with Eclipse MAT or VisualVM.
- Check for objects retained unexpectedly.
- Review caches, static collections, ThreadLocals, and unclosed resources.
- Review GC logs or Java Flight Recorder.
Interview Tip: Common causes of memory leaks include:
- Static collections
- Unbounded caches
- ThreadLocal misuse
- Unclosed resources
- Listener registrations that are never removed
A production strategy includes:
- Proper indexing
- Optimized SQL
- Eliminating N+1 queries
- Pagination
- Batch operations
- Connection pooling (HikariCP)
- Redis caching
- Read replicas (for read-heavy workloads)
- Database partitioning/sharding when necessary
- Continuous query monitoring and slow query analysis
Interview Tip: When asked:
“My Spring Boot application is slow. What would you check?”
Answer in this order:
- Application metrics (CPU, memory, response time using Actuator/Prometheus)
- Database performance (slow queries, indexes, N+1 problem)
- Connection pool (HikariCP utilization)
- Thread dumps & GC (high CPU, memory pressure)
- Caching opportunities (Redis/Caffeine)
- External service latency (Feign calls, timeouts, retries)
- Application logs and distributed traces (OpenTelemetry/Jaeger)
This structured troubleshooting approach demonstrates production experience and is highly valued in senior Spring Boot interviews.”,”role”,”assistant