Spring BootBy Experience Levelintermediate
Updated:

Spring Boot Interview Questions for 3 Years Experience

7 min read

The Spring Boot questions a 3-year developer must own — transactions, JPA performance, caching, async, actuator and design trade-offs — with answers and code.

TL;DR – Quick Answer

At 3 years of Spring Boot, interviews move from what annotations do to how you use them under pressure: transaction propagation and rollback rules, fixing the N+1 problem, caching, async and scheduling, actuator and monitoring, and defending REST and layering decisions. You are expected to reason about performance, failures and trade-offs, and to back every answer with something you have debugged in production.

On This Page

At three years, a Spring Boot interview stops rewarding definitions and starts rewarding judgment under failure. This set covers what a mid-level developer must own — transaction propagation and rollback rules, the N+1 problem, caching, async work, actuator and design trade-offs — each with a spoken answer, code, and the follow-up that separates real production experience from tutorial knowledge.

Why interviewers raise the bar at 3 years

Three years means you have shipped features, fixed production bugs and reviewed other people's code. The interviewer is checking for that scar tissue: have you seen a transaction fail to roll back, a lazy load explode into 200 queries, or a cache serve stale data?

So the questions target behaviour under stress, not definitions. Anyone can annotate a method @Transactional; a 3-year developer knows why it silently does nothing when called from within the same class. That awareness is the filter.

Expect three themes: data-access performance and transactions, cross-cutting features (caching, async, scheduling, actuator), and design reasoning. If JPA internals feel shaky, revisit the Spring Data JPA tutorial before rehearsing. These build on the 2-years experience set.

How to answer at 3 years

Lead with the mechanism, then a failure mode, then how you would detect or fix it. "Here is what it does; here is how it bites; here is how I caught it" is the shape of a senior answer.

Anchor answers in something you debugged. "We saw N+1 in the logs, added a JOIN FETCH, and query count dropped from 200 to 2" beats any definition. Interviewers at this level are listening for production stories.

Q1. How does @Transactional propagation work?

Propagation controls how a transactional method behaves relative to an existing transaction. REQUIRED (default) joins the caller's transaction or starts one; REQUIRES_NEW suspends the caller's and runs an independent transaction that commits or rolls back on its own.

REQUIRES_NEW matters when you must persist something even if the outer transaction fails — an audit log, for instance. NESTED uses savepoints where supported.

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void writeAuditLog(AuditEntry e) {
    auditRepo.save(e); // commits independently of the caller
}

Interview note: Follow-up: "if the outer transaction rolls back, is the REQUIRES_NEW audit still saved?" Yes — it committed in its own transaction, independent of the caller.

Q2. Why might @Transactional silently do nothing?

Because Spring applies @Transactional through a proxy. If you call a transactional method from another method in the same class, the call does not go through the proxy, so no transaction starts. Self-invocation bypasses AOP.

public void process() {
    save(); // internal call - proxy NOT involved, @Transactional ignored
}
@Transactional
public void save() { /* ... */ }

The fixes: move the transactional method to another bean, or inject a reference to the proxy. This is one of the most reliable 3-year traps.

Interview note: Trap: "does making the method private help?" No — @Transactional on a private or self-invoked method is ignored because the proxy cannot intercept it.

Q3. When does a transaction roll back, and how do you change it?

By default Spring rolls back on unchecked exceptions (RuntimeException, Error) but commits on checked exceptions. To roll back on a checked exception, set rollbackFor.

@Transactional(rollbackFor = IOException.class)
public void importFile() throws IOException { /* ... */ }

Many production bugs come from a checked exception being thrown, caught upstream, and the transaction committing partial changes because nobody configured rollbackFor.

Interview note: Follow-up: "you caught the exception inside the transactional method and logged it — does it roll back?" No — if you swallow it, Spring never sees it and commits.

Q4. What is the N+1 problem and how do you fix it?

Loading a list of entities with a lazy association fires one query for the list plus one per row to load the association — N+1 queries. Fix it with JOIN FETCH, an entity graph, or batch fetching.

@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.status = ?1")
List<Order> findWithItems(String status);

The JOIN FETCH pulls orders and their items in a single query. Detecting N+1 usually starts with enabling SQL logging and seeing the query count spike.

Interview note: Trap: "does making the association EAGER fix N+1?" Not really — global EAGER causes its own problems and can still issue extra queries; targeted JOIN FETCH per use case is the right tool.

Q5. What is the difference between FetchType.LAZY and EAGER?

LAZY loads an association only when you access it; EAGER loads it immediately with the parent. LAZY is the sensible default for collections because it avoids pulling data you may not use — but it requires an open session when you access it.

The classic failure is LazyInitializationException: you access a lazy field after the transaction closed. The fix is to fetch what you need inside the transaction, not to make everything EAGER.

Interview note: Follow-up: "why not just make everything EAGER to avoid lazy exceptions?" Because it loads huge object graphs and reintroduces N+1; you would trade one bug for worse performance.

Q6. How does caching work in Spring Boot?

Enable it with @EnableCaching and annotate methods with @Cacheable, @CachePut and @CacheEvict. The result of a @Cacheable method is stored by key; the next call with the same key returns the cached value without executing the method.

@Cacheable("products")
public Product findById(Long id) { return repo.findById(id).orElseThrow(); }

@CacheEvict(value = "products", key = "#p.id")
public void update(Product p) { repo.save(p); }

The hard part interviewers probe is invalidation — keeping the cache consistent with the database on updates.

Interview note: Trap: "why does the cache still work if you call the method from within the same class?" It usually does not — like @Transactional, caching is proxy-based and self-invocation bypasses it.

Q7. How do you run work asynchronously?

Annotate a method with @Async and enable it with @EnableAsync. Spring runs the method on a separate thread pool and returns immediately, optionally giving you a CompletableFuture for the result.

@Async
public CompletableFuture<Report> generate(Long id) {
    return CompletableFuture.completedFuture(build(id));
}

You should also configure a bounded TaskExecutor rather than relying on the default unbounded pool, and know that @Async is proxy-based too.

Interview note: Follow-up: "what happens to exceptions in a void @Async method?" They are swallowed by the executor unless you set an AsyncUncaughtExceptionHandler or return a Future.

Q8. What does Spring Boot Actuator give you?

Actuator exposes production-ready endpoints — health, metrics, info, env, mappings — over HTTP or JMX. /actuator/health feeds readiness and liveness probes; metrics feed monitoring systems like Prometheus.

At three years you should connect this to operations: a Kubernetes liveness probe hitting /actuator/health/liveness, or Micrometer publishing request timings. It shows you have run apps, not just built them.

Interview note: Trap: "should all actuator endpoints be public?" No — most expose sensitive data; secure them and expose only what monitoring needs.

Q9. How do you design a clean layered REST service?

Keep controllers thin (mapping, validation, status codes), put business logic in services, and confine persistence to repositories. Use DTOs at the boundary so entities never leak into the API, and map between them explicitly.

This separation is what makes code testable and changeable. A 3-year candidate is expected to justify why an entity should not be returned directly — versioning, lazy fields, and exposure of internal structure.

@GetMapping("/{id}")
public OrderResponse get(@PathVariable Long id) {
    return mapper.toResponse(service.findById(id)); // DTO, not entity
}

Review the REST API design tutorial to see the layered structure in full.

Interview note: Follow-up: "why not return the JPA entity directly?" Lazy loading, accidental field exposure, and coupling your API contract to your database schema.

Q10. How do bean lifecycle callbacks work?

Spring creates a bean, injects dependencies, then calls initialization callbacks (@PostConstruct or InitializingBean), and on shutdown calls destruction callbacks (@PreDestroy or DisposableBean). You use them to set up and release resources.

Knowing the order helps you place cache warm-ups or connection setup correctly. See the bean lifecycle guide for the full sequence.

Interview note: Trap: "when does @PostConstruct run relative to constructor injection?" After the constructor and dependency injection complete, so all dependencies are available.

Q11. How do you manage configuration across environments securely?

Use profiles for environment-specific files and @ConfigurationProperties to bind grouped settings type-safely. Keep secrets out of the repo — inject them via environment variables or a secrets manager, not application.properties.

@ConfigurationProperties(prefix = "payment")
public record PaymentProps(String apiUrl, int timeoutMs) {}

At three years, mention externalized secrets and per-environment overrides — it shows deployment awareness.

Interview note: Follow-up: "why prefer @ConfigurationProperties over many @Value fields?" Type safety, grouping, validation, and easier testing of a single config object.

Q12. How do you diagnose a slow Spring Boot endpoint?

Reproduce it, enable SQL logging to catch N+1 and missing indexes, use actuator metrics or a profiler to find the hot path, and check for blocking calls or unbounded thread pools. Fix the biggest contributor first, then re-measure.

The point interviewers want is method: measure before you optimize. Guessing and adding caches blindly often hides the real problem.

Interview note: Trap: "the endpoint is slow, so you add @Cacheable — good idea?" Only if reads dominate and data is stable; otherwise you mask an N+1 or a missing index and serve stale data.

How to prepare

Take one project you know and answer these questions against its real code: where does a transaction span, where could N+1 hide, what would you cache and how would you invalidate it. Concrete recall beats memorized definitions at this level.

Split prep 40% data-access and transactions, 30% cross-cutting concerns, 30% design reasoning. Then benchmark yourself against the 5-years experience set to see where architecture questions begin, and drop back to the earlier set to confirm the basics are automatic. The Java Full Stack with AI course covers these production concerns with the same interview-first approach.

Frequently Asked Questions

How is a 3-year Spring Boot interview harder than a 2-year one?
At 2 years you explain how features work. At 3 years you explain how they behave when things go wrong: what rolls back, why a page load fired 200 queries, how caching invalidates, and how you chose between two designs. Interviewers expect production-grade judgment, not just correct definitions.
What is the N+1 problem and how do you fix it?
N+1 happens when loading a list of entities triggers one query for the list and one more per row to load a lazy association, producing N+1 queries. You fix it with a JOIN FETCH query, an entity graph, or batch fetching. Interviewers ask it because it is the most common JPA performance bug in real projects.
How does @Transactional propagation work?
Propagation decides how a transactional method behaves when called within an existing transaction. REQUIRED, the default, joins the current transaction or starts one. REQUIRES_NEW suspends the current one and starts an independent transaction. Knowing the difference matters for logging and partial-commit scenarios.
What transaction pitfalls do interviewers test at 3 years?
The big one is that @Transactional only works through the Spring proxy, so calling a transactional method from another method in the same class bypasses it. The second is that, by default, transactions roll back on unchecked exceptions but not checked ones unless you configure rollbackFor.
Should I know Spring Boot Actuator at 3 years?
Yes. You should be able to explain health checks, metrics, and how actuator endpoints feed monitoring and readiness or liveness probes in a deployment. It is a strong signal that you have run applications in production, not just built them locally.

Want to Build Your Career in Java Full Stack with AI?

Join CodeBegun and train with working industry engineers — Explore the Program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 15 July 2026 LinkedIn
Chat with us