TL;DR: Hire Spring Boot developers on evidence, not annotation trivia. Ask about a real upgrade and a real incident, give a design scenario, and have them review flawed code. In 2026 a strong candidate knows Boot 4 and Spring Security 7, and knows free support for Boot 3.5 ended on June 30.
Free fixes for Spring Boot 3.5 stopped on June 30, 2026, so many teams hiring now also need someone who can move them to Boot 4. That is a useful filter. A developer who has done the upgrade can name what broke.
One who has only read about it lists new features. The 25 questions below are for the interviewer: each says what to ask, what a strong answer includes, and the red flag to listen for.
- 1Code review beats quizzing. The five flawed snippets below hide the bugs that reach production: self-invocation, swallowed errors, open routes.
- 2Spring Boot 4.0 shipped on November 20, 2025, and 4.1 on June 10, 2026. Ask which one they have run in production.
- 3Spring Security 7 removed the
and()chain andauthorizeRequests, so old security configs no longer compile. - 4Spring AI reached 2.0 on June 12, 2026, built on Boot 4.1. Ask how they would put limits on model calls.
Experience Probes
Start with the candidate's own work. These questions are hard to fake, because the follow-ups go one level deeper than any tutorial.
1. Walk me through the last Spring Boot upgrade you did.
A strong answer names the versions, the order of work and what broke.
For Boot 3.5 to 4.x, that means Jackson 3 package changes, starters that must now be added by name (Flyway is the common one), removed @MockBean in tests, and Spring Security 7 config.
Good candidates mention the spring-boot-properties-migrator or the "classic" starters as a way to upgrade in steps.
Red flag: "We just bumped the version." Nobody upgrades a real service across a major release without something breaking.
2. Where does the business logic live in your current service?
A strong answer points to services or domain objects that can be tested without starting Spring, and controllers that only map HTTP to calls. They can say where transactions start, usually at the service method.
Red flag: logic inside controllers, or repositories called from controllers, with no reason given. Ask them to draw one request through the layers. Our Clean Architecture interview guide has deeper follow-ups.
3. Tell me about a production incident in a Spring service. How did you find the cause?
A strong answer has a timeline: the alert, the metric or trace that pointed somewhere, the fix, and what they changed afterwards.
Typical real causes: a connection pool exhausted by slow queries, a missing timeout on an HTTP client, an N+1 query after a data change, a memory leak in a cache with no size limit.
Red flag: only "we restarted it", or an incident where they cannot say how they knew the fix worked.
4. What does your test suite look like, and how long does it take?
A strong answer gives numbers: how many tests, how many minutes, and which kinds.
Expect plain unit tests for logic, slice tests such as @WebMvcTest for controllers, and a smaller set of @SpringBootTest runs against real databases in Testcontainers.
Red flag: every test is a @SpringBootTest, or tests run against H2 while production runs PostgreSQL. A 40-minute suite that nobody runs locally is a cost they should have noticed.
5. How do you keep secrets and environment settings out of the code?
A strong answer: settings come from environment variables or a secret store at runtime, bound to typed @ConfigurationProperties classes that fail at startup if a value is missing. The same image runs in every environment.
Red flag: passwords in application-prod.yml in Git, or one build per environment.
6. Why Spring Boot for your last service, and not Quarkus or Micronaut?
A strong answer weighs real factors: the team's experience, the libraries they needed, startup time and memory limits, and support.
They know Spring has answers for fast startup too, such as the JVM AOT cache on Java 25 and GraalVM native images.
Red flag: "Spring is the standard" with nothing else. The question tests judgement, not loyalty.
Design Scenarios
Give each scenario out loud and let the candidate ask questions first. Good candidates ask about volumes and failure cases before they design.

7. A client retries POST /orders after a timeout. How do you stop a double charge?
A strong answer uses an idempotency key. The client sends a unique key with the request. The service stores it with a unique database constraint in the same transaction as the order.
A retry with the same key returns the first result instead of creating a second order.
Seniors add detail: what happens if the first request is still running, how long keys are kept, and that the payment provider needs its own idempotency key too.
Red flag: "check if an order exists first" with no constraint. Two concurrent requests both pass that check.
8. A partner API sometimes takes 30 seconds. How do you keep your service responsive?
A strong answer starts with a timeout on the client, well under the caller's own timeout. Then a limit on concurrent calls so a slow partner cannot use up every thread or connection.
Spring Framework 7's @ConcurrencyLimit does this in one annotation; Resilience4j adds a circuit breaker. Retries only for safe operations, with backoff and jitter.
The best answers ask whether the call must be synchronous at all. Often the order can be accepted and checked in the background.
Red flag: retries without timeouts, which turns one slow partner into a flood of requests.
9. After an order is saved, you must send an email and publish an event. Where does that code go?
A strong answer keeps both out of the database transaction, so a rollback never sends an email for an order that does not exist. A @TransactionalEventListener runs after commit.
If losing the event is not acceptable, they use an outbox table written in the same transaction, or Spring Modulith's event publication registry, which stores events and retries them.
Red flag: sending the Kafka message inside the transaction and assuming both succeed together.
10. A nightly job must process 2 million rows. How would you build it?
A strong answer uses Spring Batch with chunks: read, process and write a few hundred rows per transaction, so a failure at row 1.5 million restarts from the last chunk, not from zero.
They think about paging queries, skipping bad rows, and running two instances safely.
Red flag: one findAll() into memory and one huge transaction.
11. When would you add caching, and what can go wrong?
A strong answer adds a cache only after measuring a slow, repeated read. Then they pick local (Caffeine) or shared (Redis) by how many instances run and how stale the data may be.
They name the problems: stale data after writes, no size limit, cache keys that miss a parameter, and @Cacheable ignored on self-calls.
Red flag: "cache everything" with no plan for eviction or invalidation.
12. How would you split a large Spring Boot monolith?
A strong answer does not start with services. It starts with boundaries inside the monolith: packages or modules per business area, no shared entities between them, and tests that fail when a module reaches into another.
Only then does a module with its own scaling or release needs move out. Our DDD interview guide covers the boundary questions in depth.
Red flag: one microservice per table, or a plan that splits the code but keeps one shared database.
Code Review Exercises
Show each snippet and ask: "What would you change before this merges?" Count what they find and how they rank it. Each one compiles against Spring Boot 4.1; we checked.
13. What is wrong with this invoice service?
@Service
public class InvoiceService {
@Autowired private InvoiceRepository invoices;
@Autowired private PaymentClient payments;
public void settle(long id) {
try {
markPaid(id);
} catch (Exception e) {
log.warn("settle failed");
}
}
@Transactional
private void markPaid(long id) {
Invoice inv = invoices.findById(id).get();
payments.charge(inv.total());
inv.setStatus(PAID);
}
}
What they should find, most serious first:
@Transactionaldoes nothing here. The method is private and called throughthis, so the proxy never sees it. The status change is never saved, but the customer is charged.- The catch hides every failure, with no stack trace.
- The charge runs before the status change. A retry charges again.
.get()on an emptyOptionalthrows a vague error; field injection makes the class hard to test.
Someone who finds only the field injection is reading for style, not bugs.
14. What is risky about returning this entity from a controller?
@GetMapping("/customers/{id}")
Customer get(@PathVariable long id) {
return customers.findById(id).orElseThrow();
}
What they should find: the JPA entity becomes the API. Every new column, such as a password hash, is published.
Lazy associations either fire extra queries during JSON writing (Boot keeps open-in-view on by default) or fail once it is turned off. Bidirectional links can loop. And a missing customer returns 500 instead of 404.
- Every new column is public
- Lazy fields load during JSON writing
- Missing row returns 500
- Only the fields the client needs
- Queries run in the service, inside a transaction
- Missing row mapped to 404
15. What happens under load with this order method?
@Transactional
public Order place(OrderRequest req) {
Order order = orders.save(Order.from(req));
FraudResult result = restClient.post().uri("/check").body(req)
.retrieve().body(FraudResult.class);
if (!result.ok()) throw new FraudException();
return order;
}
What they should find: the fraud call runs inside the transaction, so each request holds a database connection while it waits on the network.
With a pool of 10 and a slow fraud service, the 11th order waits for a connection, and then so does every other endpoint. There is also no timeout on the client.
A strong candidate moves the call before the transaction starts and sets a timeout.
16. Why might this welcome email never be sent asynchronously?
public void register(User user) {
sendWelcomeEmail(user);
}
@Async
public void sendWelcomeEmail(User user) {
mailer.sendWelcome(user);
}
What they should find: it is a self-call, so @Async is skipped and the email runs on the request thread. @EnableAsync must also be present.
Once it does run async, an exception from a void method only reaches the async exception handler, so failures need logging or a retry. Passing an entity to another thread can also trip over lazy fields.
17. Which endpoints does this security config leave open?
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/**").authenticated()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().permitAll())
.csrf(csrf -> csrf.disable());
What they should find: rules match in order and the first match wins. /api/admin/** also matches /api/**, so any logged-in user reaches admin routes. anyRequest().permitAll() opens everything else, including Actuator endpoints on the same port.
Turning off CSRF is fine for a token-only API, but not if the app uses session cookies.
The fix: specific rules first, and anyRequest().authenticated() or denyAll() last.
Practical Tasks
18. What should a 45-minute build task look like, and how do you score it?
Ask for one endpoint with input validation and error handling, for example "create a booking, reject overlapping dates". Score it on:
- Validation with Bean Validation annotations, and errors returned as problem details, not stack traces.
- A service layer that holds the overlap rule, with a test for it.
- A database constraint or lock for the overlap, not just a check in code.
- Clear names and small methods.
Finishing matters less than the order they work in. Strong candidates write the rule and its test first.
19. Ask them to test the endpoint they built. What separates levels?
A mid-level developer writes a @SpringBootTest for everything. A senior tests the rule in a plain unit test, the controller with @WebMvcTest and a @MockitoBean service, and the overlap constraint against a real database.
They also test the failure path: the 400 for bad input and the 409 for a clash.
The same gap shows across the whole loop. Use this grid to set the bar for the level you are hiring.

20. Give them a service that fails to start. What do you watch for?
Break something common: a component outside the scanned package, a missing starter after a Boot 4 upgrade, or two beans of the same type. Watch how they read the error.
Strong candidates read the failure analysis Boot prints, then use the conditions report (--debug) to see which auto-configuration did not apply.
Red flag: changing annotations at random until it starts.
21. Why ask a candidate to review a real pull request from your team?
Because it shows how they will work on day one. Pick a merged PR of 200 to 400 lines with a known issue that was found later. Give them 30 minutes.
Strong reviewers ask what the change is for, find the real risk, and phrase comments so the author can act on them. It also shows how they handle code they did not write, which is most of the job.
What Changed Recently
22. Our services run Spring Boot 3.5. What would you do first?
A strong answer starts with the facts. According to Spring's support table, free fixes for 3.5 ended on June 30, 2026.
Then a plan, as the 4.0 migration guide suggests: move to the latest 3.5.x, clear every deprecation warning, then upgrade. Upgrade one low-risk service first and write down what broke.
Boot 4 still runs on Java 17, so the JDK can wait if it must.
Red flag: "upgrade everything in one go," or not knowing that 3.5 is out of free support.
23. This security config was written for Spring Security 5. What breaks on Spring Security 7?
Show a config that extends WebSecurityConfigurerAdapter and chains .and(). A strong answer knows the adapter went away in Security 6.
Security 7's What's New page lists the rest: and() and authorizeRequests are removed, AntPathRequestMatcher gave way to PathPatternRequestMatcher, and the OAuth 2.0 password grant is gone.
The fix is a SecurityFilterChain bean written with lambdas. Bonus points for knowing Security 7 added multi-factor authentication support.
24. Spring Batch in Boot 4 no longer stores job data in your database by default. Does that matter?
It matters for restarts. The 4.0 migration guide says Spring Batch 6 can run in memory, and the plain spring-boot-starter-batch now uses that mode. Existing jobs stop writing metadata to your database after the upgrade.
A strong answer connects this to question 10: without the job repository, a failed job cannot restart from its last chunk. Jobs that need restarts or run on several instances should use spring-boot-starter-batch-jdbc.
25. We want an LLM feature in a Spring service. What would you use?
A strong answer names Spring AI, which reached 1.0 on May 20, 2025 and 2.0 on June 12, 2026, built on Boot 4.1. It gives one ChatClient API across model providers, plus tool calling, structured output and vector store support.
Then the engineering: timeouts and cost limits on model calls, no personal data in prompts without a reason, and tests that do not call a paid model on every run.
Red flag: treating the model call like any other API, with no plan for slow, wrong or expensive answers.
Signs of a Strong Candidate
- They find the self-invocation bug in question 13 without a hint, and explain why the charge still happens.
- They ask about data volume, concurrency and failure before designing anything.
- They put timeouts on every remote call and keep network calls out of transactions.
- They name what a Boot 4 upgrade touched in their own code, not in a blog post.
- They test rules in plain unit tests and databases in Testcontainers, and know why.
Hiring Spring Boot Developers
Candidates preparing for these interviews can use our 35 Spring Boot interview questions, which cover the technical answers in depth.
Second Talent matches you with pre-vetted Java and Spring Boot developers across Asia, screened with exercises like these.
Our Java developer cost guide shows rates by country. Tell us about the role and we send a shortlist within 24 hours.






