Spring Boot · Java Backend Interview Q&A

Spring Boot Interview Questions & Answers: 60 Questions with Examples

From IoC and bean lifecycle to auto-configuration internals, JPA performance, the @Transactional traps that cause production bugs, Spring Security 6 and microservice resilience, with code for every tricky answer.

✍️ Pranjal Jain, Ex-Microsoft · IIT Kanpur 📅 10 October 2026 ⏱ 22 min read
Illustration of a container automatically wiring together building blocks, a database and a security shield
TL;DR
  • Spring Boot interviews for 1-6 years of experience revolve around DI and bean lifecycle, auto-configuration, JPA performance, @Transactional semantics, Spring Security and microservice patterns.
  • The questions that separate candidates are about proxies: why self-invocation skips @Transactional, why private methods are not advised, why a prototype bean inside a singleton is not fresh.
  • Know the N+1 problem cold, plus JOIN FETCH, @EntityGraph and why open-in-view hides it.
  • Default rollback is on unchecked exceptions only. Know REQUIRED vs REQUIRES_NEW with a real use case.
  • Be current: Boot 3 needs Java 17+ and the jakarta.* namespace; Spring Security 6 uses a SecurityFilterChain bean, not WebSecurityConfigurerAdapter.

Java with Spring Boot is the default backend stack at a large share of Indian product companies and GCCs: PhonePe, Paytm, Flipkart teams, banks' technology centres, and most fintech startups. That makes Spring Boot the topic where interviewers have the deepest bench of follow-ups. This guide gives 60 questions with answers you can say in an interview, plus the code that proves you have actually debugged these things.

Core Java topics (collections, JVM, concurrency) are covered separately in Java interview questions and multithreading interview questions. Here we stay on the framework.

How Spring Boot Gets Tested in Backend Interviews

Spring questions rarely arrive as a standalone round. They show up in three places:

Pattern 1

Resume deep dive

"You built the order service in Spring Boot. How did you handle transactions across the payment call?" Every claim on your resume is a door the interviewer will walk through.

Pattern 2

Rapid-fire fundamentals

Scopes, annotations, lifecycle, auto-config. Short answers, but each can trigger a "why" follow-up.

Pattern 3

Debugging scenarios

"This @Transactional method doesn't roll back." "This endpoint fires 101 queries." The best-prepared candidates have seen these bugs.

Version awareness matters. Spring Boot 3.x (Spring Framework 6) is the baseline most teams run in 2026, and Spring Boot 4 (Spring Framework 7) arrived in late 2025, so many services are mid-migration. Mentioning javax to jakarta or the removal of WebSecurityConfigurerAdapter signals you work on current code.

IoC and Dependency Injection Questions (Q1-10)

Q1. What is Inversion of Control?

Normally, an object creates its own dependencies (new PaymentGateway()). With IoC, a container creates objects and supplies their dependencies, so control of object construction is inverted. The benefit is loose coupling: OrderService depends on a PaymentGateway interface, and the container decides whether that is Razorpay, a stub, or a mock in tests.

Q2. Dependency Injection vs IoC?

IoC is the principle; DI is the most common way to implement it. Spring's container (the ApplicationContext) is the IoC container, and it performs DI through constructors, setters or fields.

Q3. Constructor, setter or field injection: which and why?

Java
@Service
public class OrderService {
    private final OrderRepository orders;
    private final PaymentGateway payments;

    // Single constructor: @Autowired is optional since Spring 4.3
    public OrderService(OrderRepository orders, PaymentGateway payments) {
        this.orders = orders;
        this.payments = payments;
    }
}

Prefer constructor injection: fields can be final, the class is testable with plain new, missing dependencies fail at startup, and a constructor with eight parameters is an honest signal that the class does too much. Use setter injection for genuinely optional dependencies. Avoid field injection outside tests.

Q4. BeanFactory vs ApplicationContext?

BeanFactory is the minimal container interface with lazy bean creation. ApplicationContext extends it with eager singleton creation at startup, event publishing, internationalisation, environment and profile support, and automatic registration of BeanPostProcessors. In Spring Boot you always use an ApplicationContext.

Q5. @Component vs @Bean?

@Component (and its stereotypes) goes on your class and is discovered by component scanning. @Bean goes on a method in a @Configuration class and returns an instance you construct yourself, which is how you register third-party classes you cannot annotate (an ObjectMapper, an S3 client) or need custom construction logic.

Q6. @Component, @Service, @Repository, @Controller: any real difference?

All are @Component specialisations picked up by scanning. @Repository adds behaviour: a post-processor translates persistence exceptions into Spring's DataAccessException hierarchy. @Controller marks web handlers; @RestController = @Controller + @ResponseBody. @Service is purely semantic.

Q7. Two beans implement the same interface. How does Spring choose?

Startup fails with NoUniqueBeanDefinitionException unless you disambiguate: mark one @Primary as the default, use @Qualifier("razorpay") at the injection point, or inject all of them as List<PaymentGateway> or Map<String, PaymentGateway> (keyed by bean name), which is a neat way to implement a strategy pattern.

Java: strategy via Map injection
@Service
public class PaymentRouter {
    private final Map<String, PaymentGateway> gateways;
    public PaymentRouter(Map<String, PaymentGateway> gateways) { this.gateways = gateways; }

    public PaymentResult pay(String provider, Payment p) {
        PaymentGateway g = gateways.get(provider);   // "razorpay", "payu", ...
        if (g == null) throw new IllegalArgumentException("unknown provider " + provider);
        return g.charge(p);
    }
}

Q8. How does Spring handle circular dependencies?

With constructor injection, A needing B needing A cannot be built, and startup fails with BeanCurrentlyInCreationException. Historically Spring resolved setter/field cycles using early references, but since Spring Boot 2.6 circular references are prohibited by default (spring.main.allow-circular-references=false). The right fix is design: extract the shared logic into a third bean, or use events. @Lazy on one injection point is a workaround, not a fix.

Q9. What is component scanning and what does its default base package mean?

@ComponentScan scans the package of the annotated class and all sub-packages. Because @SpringBootApplication includes it, a bean in com.acme.util is invisible if the main class lives in com.acme.app. Keep the main class in the root package.

Q10. @Value vs @ConfigurationProperties?

@Value("${payment.timeout-ms}") injects single values and supports SpEL. @ConfigurationProperties(prefix = "payment") binds a whole group into a typed object (a record works well), supports relaxed binding (timeout-ms, TIMEOUT_MS), validation with @Validated, and IDE metadata. Use it for anything with more than one or two settings.

Java
@ConfigurationProperties(prefix = "payment")
@Validated
public record PaymentProperties(@NotBlank String baseUrl,
                                @Min(100) int timeoutMs,
                                int maxRetries) {}

// enable with @EnableConfigurationProperties(PaymentProperties.class)
// or @ConfigurationPropertiesScan on the main class

Bean Scopes and Bean Lifecycle Questions (Q11-18)

Q11. List the bean scopes.

ScopeInstancesTypical use
singleton (default)One per ApplicationContextStateless services, repositories
prototypeNew one each time the bean is requestedStateful helpers, builders
requestOne per HTTP requestPer-request context holders
sessionOne per HTTP sessionServer-side session data (rare in stateless APIs)
applicationOne per ServletContextRare
websocketOne per WebSocket sessionSTOMP messaging

Q12. Is a singleton bean thread-safe?

No. Singleton is about how many instances exist, not about concurrency. One instance serves every request thread, so any mutable instance field is a race condition. Keep singletons stateless; if you need state, use local variables, thread-safe structures (ConcurrentHashMap, AtomicLong) or an external store.

Q13. Spring singleton vs the GoF Singleton pattern?

The GoF singleton is one instance per class loader, enforced by a private constructor. A Spring singleton is one instance per container per bean definition: you can define two beans of the same class, and you can still construct it with new in tests.

Q14. A prototype bean is injected into a singleton. What happens?

The prototype is created once, when the singleton is created, and reused forever, which defeats the scope. Fixes:

Java
@Service
public class ReportService {
    private final ObjectProvider<ReportBuilder> builders;   // ReportBuilder is @Scope("prototype")
    public ReportService(ObjectProvider<ReportBuilder> builders) { this.builders = builders; }

    public Report generate(Long id) {
        ReportBuilder b = builders.getObject();   // fresh instance on every call
        return b.forAccount(id).build();
    }
}

Alternatives: a @Lookup method, or a scoped proxy (@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)). Request-scoped beans injected into singletons use the scoped-proxy approach automatically when declared with @RequestScope.

Q15. Walk through the bean lifecycle.

  1. Instantiate via constructor (constructor injection happens here).
  2. Populate properties: setter and field injection.
  3. Aware callbacks: BeanNameAware, ApplicationContextAware, and so on.
  4. BeanPostProcessor.postProcessBeforeInitialization.
  5. Init callbacks: @PostConstruct, then InitializingBean.afterPropertiesSet(), then a custom initMethod.
  6. BeanPostProcessor.postProcessAfterInitialization: this is where AOP proxies (transactions, @Async, caching) are created and swapped in.
  7. In use.
  8. Destroy on context shutdown: @PreDestroy, DisposableBean.destroy(), custom destroyMethod. Prototype beans do not get destroy callbacks; the container does not track them.

Q16. What is a BeanPostProcessor vs a BeanFactoryPostProcessor?

A BeanFactoryPostProcessor runs before any beans are created and can modify bean definitions (for example, resolving ${...} placeholders). A BeanPostProcessor runs around each bean's initialisation and can modify or wrap the instance. Proxy creation for AOP is a BeanPostProcessor.

Q17. How do you run code at startup?

@PostConstruct runs per bean after injection, but the rest of the context may not be ready. CommandLineRunner/ApplicationRunner run once after the context has started. @EventListener(ApplicationReadyEvent.class) runs when the app is ready to serve traffic, the best place for cache warm-ups.

Q18. What is @Lazy?

It delays creating a singleton until first use. Faster startup, but configuration errors surface at the first request instead of at boot. spring.main.lazy-initialization=true makes everything lazy; useful in dev, risky in production.

Spring Boot Auto-Configuration and Starters (Q19-27)

Q19. What does @SpringBootApplication combine?

@SpringBootConfiguration (a @Configuration), @EnableAutoConfiguration, and @ComponentScan on the current package.

Q20. How does auto-configuration work internally?

@EnableAutoConfiguration imports every class listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports across the classpath (Boot 2.x used spring.factories; Boot 3 dropped it for auto-configuration). Each auto-configuration class is a @AutoConfiguration guarded by conditions:

Java: a simplified auto-configuration
@AutoConfiguration
@ConditionalOnClass(DataSource.class)                    // JDBC on the classpath?
@EnableConfigurationProperties(DataSourceProperties.class)
public class MyDataSourceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(DataSource.class)          // user didn't define one
    @ConditionalOnProperty(prefix = "spring.datasource", name = "url")
    public DataSource dataSource(DataSourceProperties props) {
        return props.initializeDataSourceBuilder().build();
    }
}

The key design idea is back-off: @ConditionalOnMissingBean means anything you define wins over the default.

Q21. How do you see which auto-configurations applied?

Start with --debug (or debug=true) to print the condition evaluation report, listing positive and negative matches with reasons. With Actuator, /actuator/conditions exposes the same data.

Q22. How do you disable a specific auto-configuration?

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) or the property spring.autoconfigure.exclude. A typical case: a service that has JDBC on its classpath transitively but no database.

Q23. What is a starter?

A dependency descriptor that pulls in a coherent set of libraries with compatible versions: spring-boot-starter-web brings Spring MVC, Jackson, validation support and embedded Tomcat. Versions are managed by the Boot BOM (via the parent POM or the dependency-management plugin), so you rarely specify versions yourself.

Q24. How would you write a custom starter?

Two modules by convention: an -autoconfigure module with @AutoConfiguration classes, @ConfigurationProperties and the AutoConfiguration.imports file; and a thin -starter module that depends on it plus the libraries. Companies do this for shared concerns like an internal audit-logging client or a standard tracing setup across 50 microservices.

Q25. What is the property source precedence?

Higher wins, abbreviated: command-line arguments, then SPRING_APPLICATION_JSON, OS environment variables, Java system properties, profile-specific application-{profile}.yml, then application.yml, then @PropertySource and defaults. Profile-specific files outside the jar beat those inside it. The practical rule: defaults in the jar, environment-specific values from env vars or a config server, secrets from a secret manager, never committed.

Q26. What are profiles?

Named sets of configuration and beans, activated with spring.profiles.active=prod. @Profile("dev") on a bean registers it only in that profile, such as an in-memory payment stub for local development.

Q27. What does Actuator give you?

Production endpoints: /health (with liveness and readiness groups used by Kubernetes probes), /metrics and /prometheus via Micrometer, /info, /env, /loggers (change log levels at runtime), /threaddump, /heapdump. Only health is exposed over HTTP by default in Boot 3; expose others deliberately and secure them, because /env and /heapdump can leak secrets.

Web Layer: REST Controllers, Validation and Errors (Q28-34)

Q28. How does a request reach your controller?

Embedded Tomcat accepts the connection and runs the servlet filter chain (where Spring Security lives), then DispatcherServlet asks HandlerMapping for the matching controller method, HandlerAdapter invokes it with arguments resolved by argument resolvers (path variables, @RequestBody via Jackson), and the return value is serialised by an HttpMessageConverter.

Q29. @RequestParam vs @PathVariable vs @RequestBody?

@PathVariable binds a URI segment (/orders/{id}), @RequestParam binds query or form parameters (?status=PAID), @RequestBody deserialises the body. Identifiers in the path, filters in the query, payloads in the body.

Q30. How do you validate input?

Java
public record CreateOrderRequest(
        @NotNull Long userId,
        @NotEmpty List<@Valid LineItem> items,
        @Positive BigDecimal amount) {}

@PostMapping("/orders")
public ResponseEntity<OrderDto> create(@Valid @RequestBody CreateOrderRequest req) {
    OrderDto created = orderService.create(req);
    return ResponseEntity.created(URI.create("/orders/" + created.id())).body(created);
}

A failed @Valid on a request body throws MethodArgumentNotValidException, which Boot turns into a 400. Use spring-boot-starter-validation; it is no longer included in the web starter.

Q31. How do you handle exceptions globally?

Java
@RestControllerAdvice
public class ApiExceptionHandler {

    @ExceptionHandler(OrderNotFoundException.class)
    public ProblemDetail notFound(OrderNotFoundException ex) {
        ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
        pd.setTitle("Order not found");
        return pd;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ProblemDetail invalid(MethodArgumentNotValidException ex) {
        ProblemDetail pd = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
        pd.setProperty("errors", ex.getBindingResult().getFieldErrors().stream()
                .map(e -> e.getField() + ": " + e.getDefaultMessage()).toList());
        return pd;
    }
}

ProblemDetail (Spring 6) implements the standard problem-details JSON format (RFC 9457, which superseded RFC 7807), so clients get a consistent error shape.

Q32. Spring MVC vs Spring WebFlux?

MVC is servlet-based, one thread per request, blocking I/O, simplest to reason about and debug. WebFlux is reactive (Project Reactor on Netty), a small number of event-loop threads, non-blocking end to end. WebFlux only pays off if every hop (DB driver, HTTP clients) is non-blocking. Since Java 21, virtual threads (spring.threads.virtual.enabled=true in Boot 3.2+) give MVC much of the concurrency benefit with ordinary blocking code, which is why many teams now choose MVC plus virtual threads over WebFlux.

Q33. How do you make an HTTP call to another service?

RestClient (Spring 6.1+) is the modern synchronous fluent client; WebClient is the reactive one; RestTemplate is in maintenance mode. Declarative HTTP interfaces (@HttpExchange) or OpenFeign generate clients from an interface. Whatever you use, set connect and read timeouts; the default can be infinite, and a hung dependency then exhausts your Tomcat threads.

Q34. How do you test each layer?

AnnotationLoadsUse for
none (plain JUnit + Mockito)NothingService logic; fastest
@WebMvcTestMVC slice: controllers, advice, filtersRequest mapping, validation, status codes with MockMvc
@DataJpaTestJPA slice, transactional, rolls back per testRepository queries; pair with Testcontainers for real Postgres
@SpringBootTestFull contextIntegration tests, few of them

In Boot 3.4+, @MockBean is deprecated in favour of @MockitoBean from Spring Framework.

Spring Data JPA and Hibernate Questions (Q35-43)

Q35. JPA vs Hibernate vs Spring Data JPA?

JPA (now Jakarta Persistence) is the specification. Hibernate is the most used implementation and Boot's default. Spring Data JPA is a layer above that generates repository implementations from interfaces and method names.

Q36. Explain the N+1 problem with an example and fixes.

Java
@Entity
public class Order {
    @Id @GeneratedValue Long id;
    @ManyToOne(fetch = FetchType.LAZY) Customer customer;
    @OneToMany(mappedBy = "order") List<OrderItem> items;   // LAZY by default
}

List<Order> orders = orderRepository.findByStatus(Status.PAID);   // 1 query
for (Order o : orders) {
    total += o.getItems().size();       // +1 query per order -> 100 orders = 101 queries
}

Fixes, in order of preference:

// 1. Fetch join for this use case
@Query("select distinct o from Order o join fetch o.items where o.status = :status")
List<Order> findPaidWithItems(@Param("status") Status status);

// 2. Entity graph on a derived query
@EntityGraph(attributePaths = {"items", "customer"})
List<Order> findByStatus(Status status);

// 3. Batch fetching: loads lazy collections for many parents in one IN query
//    spring.jpa.properties.hibernate.default_batch_fetch_size=50

Caveat interviewers like: fetch-joining a collection together with pagination makes Hibernate paginate in memory (it logs a warning). For paged lists, fetch IDs page-wise first, then fetch-join by those IDs, or rely on batch fetching. Or project straight into a DTO when you only need a few columns.

Q37. Default fetch types?

@ManyToOne and @OneToOne are EAGER by default; @OneToMany and @ManyToMany are LAZY. Common advice is to set every association to LAZY explicitly and fetch per use case, because eager associations cascade into surprise joins and extra queries everywhere.

Q38. What is LazyInitializationException?

Accessing a lazy association after the persistence context (session) has closed, typically in a controller or during JSON serialisation. Do not "fix" it by making associations EAGER. Fetch what you need inside the transactional service method and return a DTO.

Q39. What is spring.jpa.open-in-view and should you disable it?

Open Session in View keeps the persistence context open for the whole web request, so lazy loading works in controllers and views. Boot enables it by default and logs a warning. The cost: DB connections can be held longer, and lazy queries fire from the web layer, hiding N+1 problems. Most production teams set it to false and fetch explicitly.

Q40. What is the persistence context and dirty checking?

The persistence context is the first-level cache of managed entities within a transaction: loading the same ID twice returns the same object without a second query. At flush or commit, Hibernate compares managed entities with their snapshot and issues UPDATEs for changed fields. That is why this works without calling save:

@Transactional
public void rename(Long id, String name) {
    Customer c = customerRepository.findById(id).orElseThrow();
    c.setName(name);    // UPDATE issued at commit by dirty checking
}

Q41. save() vs saveAndFlush(), and when is the INSERT actually sent?

save() makes a new entity managed (persist) or merges a detached one; the SQL typically waits until flush (at commit, or before a query that needs it). saveAndFlush() forces the SQL immediately, useful when you need a DB constraint violation to surface inside the method. With GenerationType.IDENTITY, Hibernate must INSERT immediately to learn the ID, which also disables JDBC insert batching; SEQUENCE allows batching.

Q42. Optimistic vs pessimistic locking in JPA?

Optimistic: add a @Version field; UPDATEs include WHERE version = ?, and a concurrent change throws OptimisticLockException for you to retry. Best when conflicts are rare. Pessimistic: @Lock(LockModeType.PESSIMISTIC_WRITE) on a repository query issues SELECT ... FOR UPDATE; best for hot rows like a wallet balance or seat inventory. The database side is covered in ACID and isolation levels.

Q43. Derived queries, @Query and projections?

Derived queries parse the method name (findByStatusAndCreatedAtAfter). Use @Query with JPQL or nativeQuery = true when names get long or you need joins. For read-heavy endpoints, return interface or record projections so only needed columns are selected and no entities are managed. Paginate with Pageable; note that Page runs an extra count query, and Slice avoids it.

@Transactional Interview Questions (Q44-49)

Q44. How does @Transactional work?

Spring wraps the bean in a proxy (JDK dynamic proxy for interfaces, CGLIB subclass otherwise). The proxy's interceptor asks the PlatformTransactionManager to begin or join a transaction, binds the connection to the current thread, calls your method, then commits or rolls back based on the outcome.

Q45. Why does @Transactional sometimes do nothing?

Java: the self-invocation trap
@Service
public class TransferService {
    public void transferBatch(List<Transfer> ts) {
        for (Transfer t : ts) transfer(t);      // this.transfer(): bypasses the proxy!
    }

    @Transactional
    public void transfer(Transfer t) { /* debit + credit */ }
}

Causes to list: self-invocation (above); the method is private or final (proxies cannot intercept it; Spring 6 also supports protected and package-private methods for class-based proxies, but not private); the class is not a Spring bean (created with new); the exception is checked (Q46); the exception is caught inside the method and swallowed; or the work runs on another thread (@Async, CompletableFuture) which does not see the thread-bound transaction.

Q46. What does rollback happen on?

By default, RuntimeException and Error only. A checked IOException commits. Use @Transactional(rollbackFor = Exception.class) if your domain uses checked exceptions.

Q47. Explain propagation with a real use case.

PropagationBehaviourUse case
REQUIRED (default)Join existing, or start newMost service methods
REQUIRES_NEWSuspend outer, start an independent oneWrite an audit log that must persist even if the business transaction rolls back
NESTEDSavepoint within the outer transaction (JDBC)Try an optional step; roll back just that step on failure
SUPPORTSJoin if exists, else run non-transactionallyRead helpers
MANDATORYMust already be in one, else exceptionRepository-level methods that must never run alone
NOT_SUPPORTEDSuspend any existing transactionLong external call that should not hold a connection
NEVERException if a transaction existsRare

A sharp follow-up: inner REQUIRED method throws, outer catches the exception and continues. Result: UnexpectedRollbackException at commit, because the inner failure marked the shared transaction rollback-only.

Q48. Should you call a payment gateway inside @Transactional?

No. A slow external call holds a DB connection for its whole duration; with a 10-connection Hikari pool and a gateway taking 5 seconds, ten concurrent payments starve the entire service. And if the gateway succeeds but the commit fails, money moved with no record. Keep transactions short: write a PENDING row and commit, call the gateway outside, then update status in a second transaction, with a reconciliation job or outbox for failures. This is the pattern behind the payment system design.

Q49. What does readOnly = true do?

It hints the persistence provider to skip dirty checking and snapshots (Hibernate sets flush mode to manual), saving memory and CPU on large reads, and can route to a read replica if you configure a routing data source. It does not by itself stop writes in every database.

Spring Security Interview Questions (Q50-54)

Q50. How does Spring Security plug into a request?

As servlet filters. DelegatingFilterProxy hands off to FilterChainProxy, which picks a SecurityFilterChain matching the request and runs its filters: CORS, CSRF, authentication (bearer token, form login, basic), exception translation, and finally authorisation. The authenticated principal lives in the SecurityContextHolder (thread-local by default).

Q51. Configure a stateless JWT-secured API in Spring Security 6.

Java
@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain api(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())                 // stateless API, no cookies
            .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/actuator/health/**", "/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated())
            .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()));
        return http.build();
    }

    @Bean
    PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
}

Configure the issuer with spring.security.oauth2.resourceserver.jwt.issuer-uri. Note the lambda DSL and the absence of WebSecurityConfigurerAdapter, which was removed in Spring Security 6.

Q52. Is disabling CSRF safe?

For a stateless API authenticated by a bearer token in the Authorization header, yes: CSRF exploits the browser automatically attaching cookies, and a header token is not attached automatically. If your SPA uses cookie sessions, keep CSRF protection on.

Q53. Authentication vs authorisation, and method security?

Authentication establishes who you are (401 if it fails); authorisation decides what you may do (403). URL rules live in the filter chain; fine-grained rules use @PreAuthorize("hasRole('ADMIN') or #userId == authentication.name") on service methods, enabled by @EnableMethodSecurity.

Q54. How should passwords be stored?

Hashed with an adaptive, salted algorithm: BCrypt, SCrypt or Argon2, via PasswordEncoder. DelegatingPasswordEncoder prefixes hashes with {bcrypt} so you can migrate algorithms later. Never MD5 or SHA-256 alone; they are too fast to resist brute force.

Spring Boot Microservices Questions (Q55-60)

Q55. Which Spring Cloud pieces do you use for microservices?

Spring Cloud Gateway (routing, auth, rate limiting at the edge), Spring Cloud Config (central config), service discovery (Eureka or Kubernetes services), OpenFeign or HTTP interfaces for clients, and Resilience4j for circuit breakers, retries and bulkheads. On Kubernetes, many teams drop Eureka and Config Server in favour of K8s Services and ConfigMaps/Secrets.

Q56. Implement a circuit breaker.

Java (Resilience4j annotations)
@Service
public class InventoryClient {
    private final RestClient rest;
    public InventoryClient(RestClient.Builder b) { this.rest = b.baseUrl("http://inventory").build(); }

    @CircuitBreaker(name = "inventory", fallbackMethod = "assumeUnknown")
    @Retry(name = "inventory")
    public StockLevel stock(String sku) {
        return rest.get().uri("/stock/{sku}", sku).retrieve().body(StockLevel.class);
    }

    private StockLevel assumeUnknown(String sku, Throwable t) {
        return StockLevel.unknown(sku);   // degrade: show "check availability" instead of failing checkout
    }
}

Explain the states (closed, open, half-open), what opens it (failure rate or slow-call rate over a sliding window), and why retries need backoff, jitter and idempotency. Deeper treatment in circuit breaker and retry patterns.

Q57. How do you trace a request across services?

Micrometer Tracing (which replaced Spring Cloud Sleuth in Boot 3) propagates trace and span IDs in headers (W3C traceparent), adds them to the logging MDC, and exports spans to Zipkin, Jaeger or an OpenTelemetry collector.

Q58. How do you keep data consistent across services without distributed transactions?

Each service owns its database. Use the saga pattern (a sequence of local transactions with compensating actions) and the transactional outbox (write the event to an outbox table in the same local transaction, and a relay publishes it to Kafka) so state change and event can never diverge. See saga pattern explained.

Q59. How do you make a Spring Boot app production-ready on Kubernetes?

  • Liveness and readiness probes on /actuator/health/liveness and /readiness.
  • server.shutdown=graceful plus spring.lifecycle.timeout-per-shutdown-phase so in-flight requests finish on SIGTERM.
  • JVM container awareness: set -XX:MaxRAMPercentage=75 rather than a hard -Xmx that ignores the pod limit.
  • Tune the Hikari pool (default max 10) against the DB's connection limit times the number of pods.
  • Layered jars or Buildpacks (./mvnw spring-boot:build-image) for smaller, cache-friendly images.

Q60. How do you reduce Spring Boot startup time and memory?

Remove unused starters, exclude unneeded auto-configurations, avoid heavy work in @PostConstruct, and use class data sharing (CDS). For extreme cases (serverless, scale-to-zero), GraalVM native images compiled with Spring AOT start in tens of milliseconds and use far less memory, at the cost of long builds and restrictions on reflection.

How to Prepare for Spring Boot Interviews

The cheapest way to make these answers stick is to reproduce the bugs. Build one small service (orders and customers on Postgres) and deliberately:

  1. Trigger N+1. Turn on spring.jpa.show-sql or use a statement counter, load 100 orders with items, count queries, then fix with JOIN FETCH and an entity graph.
  2. Break @Transactional. Call a transactional method from the same class, throw a checked exception, catch-and-swallow inside a REQUIRED inner method. Observe each outcome.
  3. Read the condition report. Run with --debug and explain why DataSourceAutoConfiguration matched.
  4. Secure it. Add a JWT resource server, role rules and a @PreAuthorize check.
  5. Add resilience. Call a deliberately slow second service with a timeout and a circuit breaker; watch it open.
💡
Answer framing that worksFor every "what is X" question, add one line of "where it bites in production". "@Transactional is proxy-based, so self-invocation silently skips it; I've seen audit writes lost that way" is far stronger than a textbook definition. For the design patterns that sit underneath Spring (proxy, template method, factory, strategy), see top 10 design patterns for interviews.

For experienced roles (4+ years), expect the conversation to move from annotations to architecture: how many services, how they communicate, what happens when Kafka is down. Pair this guide with microservices interview questions and practise explaining one of your own services end to end, from controller to database and back, including failure modes.

Frequently Asked Questions

What is the difference between Spring and Spring Boot?▾
Spring Framework provides the core container, dependency injection, transactions, MVC and data access. Spring Boot sits on top and removes setup work: starter dependencies, auto-configuration based on the classpath, an embedded server so the app runs as a plain jar, externalised configuration and production features through Actuator. Boot does not replace Spring; it configures it.
Why does @Transactional not work when I call the method from the same class?▾
Spring implements @Transactional with a proxy that wraps the bean. A call from one method to another inside the same object uses this, not the proxy, so the transactional advice never runs. Move the method to another bean, inject the bean's own proxy, or use programmatic transactions with TransactionTemplate.
What is the N+1 problem in JPA and how do you fix it?▾
The N+1 problem happens when loading N parent entities triggers one query for the list and then one extra query per parent to fetch a lazy association, for N+1 queries total. Fix it with a JOIN FETCH query, an @EntityGraph on the repository method, or Hibernate batch fetching, and verify by logging SQL or counting statements in tests.
What are the bean scopes in Spring?▾
Singleton (one instance per container, the default), prototype (a new instance every time it is requested), and the web-aware scopes request, session, application and websocket. A prototype injected into a singleton is created only once, so use ObjectProvider, a @Lookup method or a scoped proxy when you need a fresh instance each time.
How does Spring Boot auto-configuration work?▾
@SpringBootApplication includes @EnableAutoConfiguration, which loads the auto-configuration classes listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports inside each starter jar. Each class is guarded by conditions such as @ConditionalOnClass and @ConditionalOnMissingBean, so it only applies when the relevant library is present and you have not defined your own bean. Run with --debug to see the condition evaluation report.
Does @Transactional roll back on checked exceptions?▾
No. By default Spring rolls back only on unchecked exceptions (RuntimeException and its subclasses) and Errors. A checked exception commits the transaction unless you declare rollbackFor = Exception.class or the specific exception type.
Is constructor injection better than field injection?▾
Yes, in almost all cases. Constructor injection makes dependencies explicit and final, lets you build the object in unit tests without a Spring context, fails fast if a dependency is missing, and surfaces circular dependencies at startup. Field injection with @Autowired hides dependencies and needs reflection to test.

Crack Java Backend Interviews

Prepflix's program covers Spring Boot, databases and system design alongside DSA, with mock interviews modelled on Indian product-company backend loops.

Explore the Prepflix Course →
Pranjal Jain
Pranjal Jain

Ex-Microsoft SDE · IIT Kanpur · Founder of Prepflix. Helps engineers crack startup and product company interviews across India.