Spring Boot Interview Questions and Answers
27 questions8 beginner · 13 intermediate · 6 advancedLast reviewed
This set is for Java developers preparing for backend roles that use Spring Boot, from first jobs to experienced engineers who are asked about transactions, JPA performance and production behaviour. Where versions matter the answers assume Spring Boot 3.x, which needs Java 17 or newer. Core language questions live in the Java interview set.
Practise by reading only the question, saying your answer aloud in about a minute, and then checking it against the model answer and the "what they are checking" line. Interviewers usually follow with "what happens under the hood", so try to explain the mechanism, not only the annotation. The Spring Boot course and the REST API course cover the same ground with hands-on projects.
1What is Spring Boot, and how is it different from the Spring Framework?Beginner
The Spring Framework is the core toolkit: dependency injection, AOP, transactions, MVC and data access. It is powerful but historically needed a lot of explicit configuration. Spring Boot sits on top of it and removes that setup work by providing opinionated defaults.
Boot gives you starter dependencies, auto-configuration that wires beans based on what is on the classpath, externalised configuration, an embedded server such as Tomcat so the app runs as a plain executable jar, and production features like Actuator. You are still using Spring underneath; Boot decides sensible defaults and gets out of the way when you define your own beans.
In short: Spring is the engine, Boot is the pre-assembled car.
What the interviewer is checking: Whether you can separate the framework from the convenience layer and name concrete things Boot adds.
Likely follow-up: Can you use Spring without Boot, and when would you?
2What does @SpringBootApplication actually do?Beginner
It is a convenience annotation that combines three others.
@SpringBootConfigurationmarks the class as a configuration source, so it can declare@Beanmethods.@EnableAutoConfigurationturns on Boot's auto-configuration.@ComponentScanscans the class's own package and all sub-packages for components such as@Component,@Serviceand@RestController.The scanning detail causes a common bug. If the main class sits in a deep package, or your beans live in a sibling package, they are never found and you get a "no qualifying bean" error. Keep the main class in the root package of the application, or list the base packages explicitly.
What the interviewer is checking: Knowledge of the three meta-annotations and the component-scan boundary.
Likely follow-up: How would you exclude one specific auto-configuration class?
3What are Spring Boot starters, and why do they exist?Beginner
A starter is a dependency descriptor that pulls in a curated, compatible set of libraries for one purpose. For example,
spring-boot-starter-webbrings Spring MVC, Jackson and an embedded Tomcat, andspring-boot-starter-data-jpabrings Hibernate and Spring Data JPA.They solve two problems: you do not hunt for the right list of artifacts, and you do not manage version compatibility between them, because Boot's parent POM or BOM fixes the versions. A starter has no code of its own to speak of; it works together with auto-configuration, which notices the libraries and configures them.
You can override a managed version if you really need to, but doing so takes on the compatibility risk yourself.
What the interviewer is checking: That you see starters and auto-configuration as two halves of the same mechanism.
Likely follow-up: How do you swap Tomcat for Jetty in a web application?
4Why is constructor injection preferred over field injection?Beginner
Dependency injection means a class receives its collaborators from the container instead of creating them. With constructor injection the dependencies are parameters, so the object can never exist half-wired. They can be
final, which makes the class easier to reason about, and the class can be unit tested with plainnewand mocks, with no Spring context.Field injection with
@Autowiredhides dependencies, forces reflection to test, and lets you accumulate a dozen dependencies without noticing. A long constructor is a useful warning that the class does too much.Since Spring 4.3, a class with a single constructor needs no
@Autowiredat all.java @Service public class AppointmentService { private final SlotRepository slots; private final NotificationClient notifier; public AppointmentService(SlotRepository slots, NotificationClient notifier) { this.slots = slots; this.notifier = notifier; } }What the interviewer is checking: Testability and design reasoning rather than "it is best practice".
Likely follow-up: When is setter injection still reasonable?
5What is the difference between @Component, @Service, @Repository and @Controller?Beginner
All four are stereotype annotations that register a class as a Spring bean during component scanning.
@Componentis the generic one; the others are specialisations that communicate the role of the class.@Servicemarks business logic and adds no behaviour.@Controllermarks a web layer class, and@RestControlleradds@ResponseBody, so return values are written to the response body.@Repositorymarks the data layer and has one real effect: exception translation, where persistence exceptions are converted into Spring'sDataAccessExceptionhierarchy.Technically you could use
@Componentfor everything, but the specific annotations make the layers readable, let tooling and AOP target them, and let you write pointcuts by layer.What the interviewer is checking: Whether you know that only some stereotypes add behaviour.
Likely follow-up: How does Spring decide which implementation to inject when two beans share an interface?
6What bean scopes does Spring support, and what happens if a prototype bean is injected into a singleton?Beginner
The default is
singleton: one instance per application context, shared by every caller, so it must be stateless or thread-safe.prototypecreates a new instance each time it is requested. In a web application there are alsorequest,session,applicationandwebsocketscopes.A singleton gets its dependencies injected once, at creation. If you inject a prototype bean into it, the singleton keeps that single instance forever, so you do not actually get a fresh object per use. To get a new one each time, inject an
ObjectProvider<T>and callgetObject(), or use a scoped proxy.Most beans should stay singletons; mutable per-user state belongs in a request object or session, not a field of a service.
What the interviewer is checking: Knowledge of scope-mismatch behaviour and the thread-safety implication of singletons.
Likely follow-up: Why is a mutable field on a singleton controller a bug waiting to happen?
7How do you build a simple REST endpoint, and what do @PathVariable, @RequestParam and @RequestBody bind?Beginner
Annotate a class with
@RestController, add a base@RequestMapping, and use@GetMapping,@PostMappingand friends on methods. Return an object, and Jackson serialises it to JSON.@PathVariablebinds a segment of the URL path, like the id in/clinics/7/slots.@RequestParambinds a query string or form parameter, such as?date=2025-03-01.@RequestBodydeserialises the JSON request body into an object. Wrap the return inResponseEntitywhen you need to control the status code or headers, for example 201 with a Location header on creation.Keep controllers thin: parse the request, call a service, shape the response.
java @RestController @RequestMapping("/clinics/{clinicId}/slots") public class SlotController { private final SlotService service; public SlotController(SlotService service) { this.service = service; } @GetMapping public List<SlotDto> list(@PathVariable Long clinicId, @RequestParam LocalDate date) { return service.freeSlots(clinicId, date); } @PostMapping public ResponseEntity<SlotDto> create(@PathVariable Long clinicId, @RequestBody @Valid CreateSlotRequest req) { SlotDto saved = service.create(clinicId, req); return ResponseEntity.status(HttpStatus.CREATED).body(saved); } }What the interviewer is checking: Fluency with the everyday annotations and awareness of correct status codes.
Likely follow-up: What is the difference between @Controller and @RestController?
8How do application.properties, application.yml and profiles work together?Beginner
Boot loads configuration from
application.propertiesorapplication.ymlon the classpath. Both formats map to the same keys; YAML is just a nested syntax. A profile gives you environment-specific overrides: setspring.profiles.active=prod, andapplication-prod.ymlis layered on top of the base file.Values can also come from environment variables, command-line arguments and external config files, which take priority over files packaged inside the jar. That ordering is what lets you build one artifact and promote it unchanged from test to production, supplying only the database URL and secrets from outside.
Never commit secrets into these files; read them from the environment or a secret manager.
What the interviewer is checking: Understanding of externalised configuration and the build-once, configure-per-environment idea.
Likely follow-up: How would you make a bean exist only in the dev profile?
9When do you use @Component and when @Bean?Intermediate
@Componentgoes on a class you own; component scanning detects it and creates the bean.@Beangoes on a method inside a@Configurationclass and registers whatever the method returns. Use@Beanfor classes you cannot annotate, such as a third-partyObjectMapperorRestClient, or when creating the object needs custom logic or conditions.A subtle difference: in a
@Configurationclass, which Spring proxies by default, calling one@Beanmethod from another returns the same singleton instead of constructing a second object. In a plain@Componentclass that interception does not happen, so such calls just create new instances.Rule: scanning for your own classes,
@Beanfor external types and explicit wiring.java @Configuration public class HttpConfig { @Bean public RestClient pricingClient(RestClient.Builder builder, @Value("${pricing.base-url}") String baseUrl) { return builder.baseUrl(baseUrl).build(); } }What the interviewer is checking: Whether you understand explicit versus scanned registration, not only that both create beans.
Likely follow-up: What does proxyBeanMethods = false change, and when is it worth using?
10How does Spring Boot auto-configuration decide what to set up?Intermediate
Libraries ship auto-configuration classes, and Boot discovers them through a list file inside each jar (in Boot 3 this is
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports).@EnableAutoConfigurationloads those classes, but each one is guarded by conditions such as@ConditionalOnClass,@ConditionalOnPropertyand@ConditionalOnMissingBean.For example, the DataSource configuration activates only when a database driver is on the classpath and you have not defined your own
DataSource. That last condition is the key design rule: auto-configuration backs off whenever you declare your own bean, so your explicit configuration always wins.To see what was applied and why, start with
--debugor open the Actuatorconditionsendpoint, which reports matched and unmatched conditions.What the interviewer is checking: Mechanical understanding of conditions and back-off behaviour instead of "it is magic".
Likely follow-up: How would you write your own auto-configuration for a shared internal library?
11What changed when moving from Spring Boot 2 to 3, and what usually breaks first?Intermediate
Boot 3 builds on Spring Framework 6 and requires Java 17 or newer. The most visible change is the move from
javax.*tojakarta.*packages for servlet, persistence and validation APIs, so imports likejavax.persistence.Entitybecomejakarta.persistence.Entity. Hibernate 6 and Spring Security 6 come with it.What breaks first: those imports, third-party libraries that still use
javax, security configuration written around the removedWebSecurityConfigurerAdapter(it is replaced by aSecurityFilterChainbean), and some Hibernate query behaviour changes. Boot 3 also adds improved observability through Micrometer and support for compiling to a native image.The safe path is to upgrade to the latest 2.7 first, fix deprecation warnings, then move to 3.x.
What the interviewer is checking: Practical migration experience and awareness of the jakarta namespace change.
Likely follow-up: How would you handle a dependency that has not moved to jakarta yet?
12How do you validate request input and return clean 400 responses?Intermediate
Add
spring-boot-starter-validation, annotate the request class with Bean Validation constraints such as@NotBlank,@Email,@Sizeor@Positive, and put@Validon the@RequestBodyparameter. If validation fails, Spring throwsMethodArgumentNotValidExceptionbefore your controller code runs, which maps to HTTP 400.The default error body is noisy, so handle that exception in a
@RestControllerAdviceand return field-level messages. For checks that need data, such as "slot not already booked", do those in the service layer, because annotations validate shape, not business state.Validate at the boundary and keep entities free from request-specific rules; use a separate request DTO per use case.
java public record BookingRequest( @NotNull Long slotId, @NotBlank @Size(max = 80) String patientName, @Email String contactEmail) { }What the interviewer is checking: Knowing where validation belongs and the difference between format checks and business rules.
Likely follow-up: How do you validate @RequestParam or @PathVariable values, not only request bodies?
13How do you handle exceptions globally and return a consistent error format?Intermediate
Create a class annotated with
@RestControllerAdviceand add@ExceptionHandlermethods, each mapping an exception type to a status code and body. It applies across all controllers, so error handling does not repeat in each one.Define your own domain exceptions, for example
SlotAlreadyBookedExceptionmapped to 409, rather than leakingIllegalStateExceptionmessages. Spring 6 adds theProblemDetailtype, which gives a standard problem-details JSON shape for errors, so clients get a predictable structure.Log server-side errors with a correlation id and return a generic message to the client; never return stack traces or SQL errors. Handle the most specific exceptions first and keep one fallback for unexpected ones.
java @RestControllerAdvice public class ApiExceptionHandler { @ExceptionHandler(SlotAlreadyBookedException.class) public ProblemDetail onConflict(SlotAlreadyBookedException ex) { ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getMessage()); pd.setTitle("Slot unavailable"); return pd; } }What the interviewer is checking: Clean error-handling design and awareness of what must not leak to clients.
Likely follow-up: How do you test that handler without starting the whole application?
14Compare @Value and @ConfigurationProperties. Which do you prefer for a group of settings?Intermediate
@Valueinjects a single property, which is fine for one-off values.@ConfigurationPropertiesbinds a whole prefix, such asbooking.*, into a typed object. I prefer it for groups of related settings.It gives relaxed binding (
max-retries,maxRetriesandMAX_RETRIESall map), type conversion for durations and lists, nested structures, IDE metadata, and validation by adding@Validatedwith constraints, so a bad configuration fails at startup rather than at the first request. In Boot 3 a record with a single constructor binds without extra annotations, though you still need to register the class, for example with@ConfigurationPropertiesScan.@Valuedoes support SpEL, which is its one advantage.java @ConfigurationProperties(prefix = "booking") @Validated public record BookingProperties( @Min(1) int maxDaysAhead, @NotNull Duration holdTime, List<String> blockedDates) { }What the interviewer is checking: Preference backed by concrete benefits, including fail-fast validation.
Likely follow-up: In what order do command-line arguments, environment variables and application.yml override each other?
15What is Spring Boot Actuator, and what would you expose in production?Intermediate
Actuator adds production-ready endpoints that expose the application's state:
health,info,metrics,loggers,env,threaddump,heapdumpand more. Metrics come through Micrometer, which can feed systems such as Prometheus.By default only
healthis exposed over HTTP, and you widen that withmanagement.endpoints.web.exposure.include. I would expose health, info and metrics, plus the liveness and readiness health groups if running on Kubernetes, and keep the sensitive ones such asenv,heapdumpandloggersoff the public network.Secure the management endpoints behind authentication, or run them on a separate management port reachable only internally. Also be careful that health details do not reveal connection strings.
What the interviewer is checking: Operational maturity and security awareness, not only knowing the endpoint names.
Likely follow-up: How would you add a custom health indicator for a downstream payment API?
16How does @Transactional work, and when does it roll back?Intermediate
Spring wraps the bean in a proxy. When a transactional method is called through the proxy, it begins a transaction (or joins the existing one, since the default propagation is
REQUIRED), runs your method, and commits on success.The default rollback rule surprises people: it rolls back for unchecked exceptions (
RuntimeExceptionandError) but commits for checked exceptions. To roll back on a checked one, use@Transactional(rollbackFor = Exception.class).Two more pitfalls: if you catch the exception inside the method and do not rethrow, the proxy sees a normal return and commits. And if an inner
REQUIREDmethod throws and marks the transaction rollback-only, an outer method that swallows that exception still ends with anUnexpectedRollbackException.What the interviewer is checking: Whether you know the proxy mechanism and the default rollback rules.
Likely follow-up: What does readOnly = true actually do?
17Why does a @Transactional method sometimes behave as if the annotation is not there?Intermediate
Because the transaction logic lives in the proxy, not in your class. When another bean calls your method, it goes through the proxy and the transaction starts. When a method in the same class calls another method on
this, it bypasses the proxy, so the second method's annotation is ignored. This is the self-invocation problem, and it equally affects@Asyncand@Cacheable.Other causes: the method is
private, orfinalin a class that needs a subclass proxy, or the bean was created withnewinstead of by Spring.Fixes: move the method to another bean, which is usually the cleanest design; or use
TransactionTemplatefor programmatic control; or inject the proxy into itself, which works but is a smell.java @Service public class RefundService { public void processBatch(List<Long> ids) { for (Long id : ids) { refundOne(id); // internal call: bypasses the proxy, no new transaction } } @Transactional(propagation = Propagation.REQUIRES_NEW) public void refundOne(Long id) { // intended to run in its own transaction per refund } }What the interviewer is checking: Understanding of proxy-based AOP, which explains a whole family of Spring bugs.
Likely follow-up: How would you restructure this so each refund really runs in its own transaction?
18Why shouldn't you return JPA entities directly from a controller? When do you use DTOs?Intermediate
An entity models a table and is tied to a persistence context. Returning it directly couples your public API to your schema: add a column and the JSON changes, expose a field like a password hash by accident, or hit infinite recursion on bidirectional relationships. Serialising a lazy association outside a transaction can also throw a lazy-loading error or trigger hidden queries.
A DTO is a plain object shaped for one use case. It lets the API evolve separately from the database, controls exactly which fields leave the system, and for read endpoints can be filled straight from a query projection, avoiding loading whole entities.
The cost is mapping code, which you can reduce with records and a mapper library. Request DTOs also stop clients from setting fields such as
idorroleby mass assignment.What the interviewer is checking: Layering discipline and awareness of security and performance consequences.
Likely follow-up: How would you fill a DTO directly from a Spring Data query?
19What is lazy loading, and why do you get LazyInitializationException?Intermediate
With lazy loading, Hibernate does not fetch an association until you access it. A lazy field holds a proxy or a collection wrapper, and the first access triggers a query. That only works while the persistence context, i.e. the session, is still open.
LazyInitializationExceptionoccurs when you touch the association after the session has closed, typically after the transactional service method returned and you accessappointment.getPatient().getName()in the controller or during serialisation. Defaults matter:@OneToManyis lazy, but@ManyToOneand@OneToOneare eager.The right fix is to load what you need inside the service, with a fetch join, an entity graph or a DTO projection. Making everything eager is the wrong fix. Spring Boot's
open-in-viewsetting, on by default, hides the exception but keeps a connection open during view rendering, so many teams turn it off.What the interviewer is checking: Whether you understand the session boundary and avoid fixing symptoms with eager fetching.
Likely follow-up: What are the trade-offs of keeping open-in-view enabled?
20What is the N+1 query problem in JPA, how do you spot it, and how do you fix it?Intermediate
You run one query to load N parents, then lazy access to each parent's association fires one extra query per parent, giving N+1 round trips. Loading 200 orders and printing their line items quietly turns into 201 queries.
Spot it by turning on SQL logging or Hibernate statistics in a test and counting statements, or from slow endpoints that scale with result size.
Fixes: a
JOIN FETCHquery or@EntityGraphto load parents and children together; batch fetching (@BatchSizeor Hibernate's default batch fetch size) to load children for many parents in a few queries; or a DTO projection that selects only needed columns. Beware that fetch-joining a collection together with pagination makes Hibernate page in memory, so for paged lists fetch the page of ids first, or use batching.java public interface OrderRepository extends JpaRepository<Order, Long> { // Without this, order.getLines() inside a loop fires one query per order @Query("select distinct o from Order o join fetch o.lines where o.status = :status") List<Order> findWithLines(@Param("status") OrderStatus status); }What the interviewer is checking: Practical JPA performance skill: detection and several remedies with their limits.
Likely follow-up: Why can join fetch on two collections at once cause trouble?
21Which test slices does Spring Boot offer, and when do you use @SpringBootTest instead?Intermediate
Slices load only part of the context, which makes tests fast.
@WebMvcTestloads the web layer, controllers, advice and JSON conversion, and you supply the services as mocks.@DataJpaTestloads repositories and an in-memory database by default, and rolls back after each test. There are also slices for JSON and for REST clients.@SpringBootTeststarts the whole application context, so it is slower, and I reserve it for a few integration tests that prove the wiring, configuration and security work end to end. For repository tests that depend on database-specific SQL, use Testcontainers with the real database engine instead of H2.Pure unit tests with no Spring at all are the fastest, and constructor injection makes them easy.
java @WebMvcTest(SlotController.class) class SlotControllerTest { @Autowired MockMvc mvc; @MockitoBean SlotService service; // @MockBean in older 3.x releases @Test void returnsFreeSlots() throws Exception { when(service.freeSlots(7L, LocalDate.of(2025, 3, 1))).thenReturn(List.of()); mvc.perform(get("/clinics/7/slots").param("date", "2025-03-01")) .andExpect(status().isOk()); } }What the interviewer is checking: A sensible test pyramid and knowledge of what each annotation loads.
Likely follow-up: Why can an H2-based repository test pass while production fails?
22How do you secure a Spring Boot 3 REST API? Outline the configuration and its defaults.Advanced
Adding Spring Security locks everything down by default, with basic or form login and a generated password. In Spring Security 6 you configure it by declaring a
SecurityFilterChainbean using the lambda DSL, sinceWebSecurityConfigurerAdapteris gone. UseauthorizeHttpRequestswithrequestMatchersfor URL rules, and method security such as@PreAuthorizefor finer checks.For a stateless API, use token authentication, either a JWT validated by the resource-server support or opaque tokens, and set session creation to stateless. Store passwords with
BCryptPasswordEncoderor the delegating encoder. CSRF protection is on by default; it is reasonable to disable it only for APIs that authenticate with headers rather than cookies.Add CORS rules deliberately, and never trust client-supplied roles. The JWT authentication course covers token handling in depth.
java @Configuration @EnableMethodSecurity public class SecurityConfig { @Bean SecurityFilterChain api(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) // stateless, header-token API only .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/actuator/health").permitAll() .requestMatchers(HttpMethod.GET, "/clinics/**").hasAnyRole("PATIENT", "STAFF") .anyRequest().authenticated()) .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults())); return http.build(); } }What the interviewer is checking: Up-to-date security configuration knowledge and the reasoning behind each choice, especially CSRF.
Likely follow-up: How does the security filter chain relate to servlet filters and the DispatcherServlet?
23Explain REQUIRED versus REQUIRES_NEW propagation. When is REQUIRES_NEW dangerous?Advanced
REQUIRED, the default, joins an existing transaction or starts one if none exists, so the outer and inner methods commit or roll back together.REQUIRES_NEWsuspends the current transaction and starts an independent one on a separate database connection, committing or rolling back on its own.It is useful for work that must persist even if the caller fails, like writing an audit record or a failed-attempt counter.
The dangers: it needs a second connection while the first is held, so under load a small pool can be exhausted with every thread waiting for a connection it cannot get, a deadlock of sorts. The new transaction cannot see uncommitted changes from the suspended one, and it can block on rows the outer transaction has locked. Also remember it only works when the call crosses a proxy boundary. Use it sparingly and keep those inner transactions short.
What the interviewer is checking: Depth beyond definitions: connection-pool consequences and visibility rules.
Likely follow-up: How does the isolation level interact with this, and what is the database default you rely on?
24Two users book the last slot at the same moment. How do you prevent a double booking with JPA?Advanced
A check-then-insert in application code is a race: both transactions read "free" and both write. There are three layers of defence.
First, a database unique constraint on the slot id, which is the only truly reliable guard; the loser gets a constraint violation that you translate to a 409. Second, optimistic locking: add a
@Versionfield to the slot entity, and Hibernate includes the version in the update's where clause, so the second writer updates zero rows and gets an optimistic-locking exception to retry or report. Third, pessimistic locking with@Lock(PESSIMISTIC_WRITE)orselect ... for update, which blocks the second user, useful when conflicts are frequent.Optimistic locking suits low contention; pessimistic suits hot rows. Either way, the database is the final arbiter.
java @Entity public class Slot { @Id @GeneratedValue private Long id; @Version private long version; // incremented on every update; stale writers fail private boolean booked; // getters / setters omitted }What the interviewer is checking: Concurrency design with data stores, and whether you trust the database instead of in-memory checks.
Likely follow-up: How would you retry on optimistic-lock failure without retrying on real business errors?
25How does Spring create proxies for AOP, and what limits does that impose?Advanced
Cross-cutting features such as
@Transactional,@Async,@Cacheableand method security are applied by wrapping the target bean in a proxy that runs extra logic before and after the real call. Spring can use a JDK dynamic proxy, which implements the bean's interfaces, or a CGLIB proxy, which subclasses the bean's class. Spring Boot defaults to CGLIB.The limits follow from this. Only calls that go through the proxy are intercepted, so self-invocation is not. A CGLIB proxy cannot override
finalclasses orfinalmethods, and private methods are never advised. Code that casts a bean to its concrete class may fail with a JDK proxy.If you need to advise internal calls, use AspectJ weaving instead, or restructure so the advised method lives on a different bean.
What the interviewer is checking: Understanding of the mechanism behind many annotations, and its boundaries.
Likely follow-up: Where in the bean lifecycle are these proxies created?
26The app fails with a circular dependency or "no qualifying bean". How do you debug it?Advanced
For "no qualifying bean", I first check whether the class is actually scanned: is it annotated, and is it inside the main class's package tree? Then I check conditions, for example a
@ConditionalOnPropertyor an active profile that excludes it. Running with--debugprints the conditions evaluation report, and the Actuatorbeansandconditionsendpoints show what was registered. Two candidates for one type is the opposite error, solved with@Primaryor@Qualifier.Circular dependencies, where A needs B and B needs A, fail at startup with constructor injection, and since Boot 2.6 they are prohibited by default even for setter or field injection. Do not turn the allowing flag on as the fix; break the cycle by extracting the shared logic into a third bean, or by publishing an application event instead of calling directly.
What the interviewer is checking: A systematic debugging approach and design instinct about cycles.
Likely follow-up: What is the difference between @Primary and @Qualifier?
27Your service calls three downstream APIs. How do you make a Spring Boot service resilient to their failures?Advanced
Start with timeouts on every outbound call, because the default of waiting forever ties up threads. Then add bounded retries with backoff and jitter, only for idempotent operations or with idempotency keys, since retrying a payment can double-charge. Add a circuit breaker so a failing dependency is skipped quickly instead of consuming resources, and a bulkhead or separate pool so one slow API cannot starve the others.
Libraries such as Resilience4j integrate with Spring Boot through annotations and configuration, and Actuator and Micrometer expose breaker state. Define a fallback that is honest: a cached value, a degraded response, or a clear 503.
Finally, test the failure modes, not only the happy path. See the microservices course for these patterns in context.
What the interviewer is checking: Production thinking about failure: timeouts, retries, idempotency and isolation.
Likely follow-up: How do you decide the retry count and timeout values so retries don't amplify an outage?
Fill the gaps with a free course
If one of these Spring Boot answers felt shaky, these 3 courses cover the same ground step by step: Spring Boot, Microservices Architecture, REST API Development.
More interview questions
- Java
- Python
- JavaScript
- React
- Node.js
- C++
- Data Structures & Algorithms
- SQL & Databases
- System Design
- DevOps
- AWS & Cloud
- Security
- Generative AI & LLMs
- Machine Learning
- Behavioral & HR
Practising Spring Boot for a real opening? Upload your resume to see which open jobs list Spring Boot skills you already have, or browse open roles.