Skip to content

Java Technical Lead Interview Questions & Answers

40 questions for Java Technical Lead interviews — 23 medium, 17 hard.

About the Java Technical Lead role

A technical lead owns the technical direction of a team building Java and React applications. The role includes breaking down requirements, estimating work, choosing frameworks and patterns, ensuring code quality, coordinating with QA, DevOps and product, and resolving critical incidents. Leads still write code but spend more time on architecture, reviews and unblocking the team. They also track delivery risks, run design reviews and help team members grow through feedback and pairing.

Microservices architecture Technical planning Stakeholder communication Incident management Code quality standards
Solved for this roleStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

Your React app gets 403 Forbidden on POST requests to Spring Boot, but GET works. What is the likely cause?

Save to ▾
Show answer
With Spring Security enabled, CSRF protection is on by default and blocks POST, PUT and DELETE that lack a CSRF token, while GET is allowed. For a stateless JWT API, disable CSRF in the SecurityFilterChain. If you use session cookies, keep CSRF and send the token with CookieCsrfTokenRepository. Also check CORS, because a rejected preflight OPTIONS request or a missing role in authorization rules can produce the same symptom.
02

Database passwords and API keys are committed in application.properties. How do you fix this?

Save to ▾
Show answer
Remove the secrets from the repository, rotate the exposed credentials immediately, and clean the history if needed. Replace values with placeholders such as ${DB_PASSWORD} and supply them through environment variables, Kubernetes Secrets or a vault like HashiCorp Vault or a cloud secrets manager. Add a pre-commit secret scanner, keep local values in an ignored file, and give each environment its own credentials with least privilege.
03

What is Spring Boot Actuator used for?

Save to ▾
Show answer
Actuator adds production-ready endpoints for monitoring and management, such as /actuator/health, /actuator/info, /actuator/metrics and /actuator/prometheus. Kubernetes uses health liveness and readiness groups for probes. Metrics are collected through Micrometer and can be exported to Prometheus, Datadog or other systems. Only expose the endpoints you need with management.endpoints.web.exposure.include and secure them, because endpoints like env or heapdump can leak sensitive data.
04

Users must upload files up to 200 MB. How do you design the upload API?

Save to ▾
Show answer
Avoid streaming large files through the application server. Generate a pre-signed URL for object storage like S3 or Azure Blob so the browser uploads directly, then the client calls the API to confirm and save the metadata. If uploads must go through Spring, raise spring.servlet.multipart.max-file-size, stream the input to storage instead of loading it into memory, validate type and size, and scan files for malware before use.
05

What is the difference between a clustered and a non-clustered index?

Save to ▾
Show answer
A clustered index defines the physical order of rows, so the table data itself is stored in the index and there can be only one. In MySQL InnoDB the primary key is the clustered index. A non-clustered or secondary index is a separate structure holding the indexed columns and a pointer, or the primary key in InnoDB, to the row. That is why a short primary key keeps every secondary index smaller.
06

How does Spring Boot auto-configuration work internally?

Save to ▾
Show answer
Spring Boot reads candidate configuration classes listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports inside starter jars. Each class is guarded by conditions such as @ConditionalOnClass, @ConditionalOnMissingBean and @ConditionalOnProperty, so beans are created only when the right library is present and you have not defined your own. You can inspect the decisions with the --debug flag or the Actuator conditions endpoint and exclude classes with exclude attributes.
07

What are window functions and how are they different from GROUP BY?

Save to ▾
Show answer
Window functions compute a value over a set of related rows while keeping every row in the result, unlike GROUP BY which collapses rows into one per group. They use the OVER clause with optional PARTITION BY and ORDER BY. Examples are ROW_NUMBER, RANK, DENSE_RANK, LAG, LEAD and running SUM. For instance, you can show each employee with their department's average salary in the same row.
08

Mentoring: how would you help a junior developer who keeps pushing untested Spring code?

Save to ▾
Show answer
Situation: a junior on my team often broke the build with untested changes. Task: help him improve without demotivating him. Action: I paired with him for a few sessions to write JUnit and Mockito tests for his own features, shared a short checklist and set up a CI rule that blocks merges without passing tests. Result: within a month his pull requests passed review faster, and he later helped another new joiner.
09

How does @Transactional work, and why does calling it from the same class not work?

Save to ▾
Show answer
Spring wraps the bean in a proxy. When an external caller invokes a @Transactional method, the proxy starts a transaction, calls the method and commits, or rolls back on a RuntimeException or Error. If a method in the same class calls another @Transactional method through this, the call skips the proxy, so the annotation is ignored. Fix it by moving the method to another bean or restructuring the boundary. The annotation also has no effect on private methods.
10

Write code that runs tasks in parallel using ExecutorService and collects results.

Core JavaMedium
Save to ▾
Show answer
ExecutorService pool = Executors.newFixedThreadPool(4); try { List<Callable<Integer>> tasks = List.of( () -> fetchCount("orders"), () -> fetchCount("users")); List<Future<Integer>> results = pool.invokeAll(tasks); for (Future<Integer> f : results) { System.out.println(f.get()); } } finally { pool.shutdown(); } // On Java 21 you can use Executors.newVirtualThreadPerTaskExecutor() // for I/O-bound tasks.
11

Find the top 3 highest-paid employees in each department.

Save to ▾
Show answer
SELECT department_id, name, salary FROM ( SELECT department_id, name, salary, DENSE_RANK() OVER ( PARTITION BY department_id ORDER BY salary DESC) AS rnk FROM employees ) ranked WHERE rnk <= 3 ORDER BY department_id, rnk; -- DENSE_RANK keeps ties; use ROW_NUMBER for exactly 3 rows.
12

Call another microservice from Spring Boot using RestClient with a timeout.

Save to ▾
Show answer
@Bean RestClient inventoryClient(RestClient.Builder builder) { var factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(2000); factory.setReadTimeout(3000); return builder.baseUrl("http://inventory-service") .requestFactory(factory).build(); } public StockDto getStock(String sku) { return inventoryClient.get() .uri("/api/stock/{sku}", sku) .retrieve() .body(StockDto.class); } // RestClient (Boot 3.2+) replaces RestTemplate for new code; // use WebClient for reactive stacks.
13

Explain transaction isolation levels and the problems each one prevents.

Save to ▾
Show answer
Read Uncommitted allows dirty reads. Read Committed, the default in PostgreSQL, Oracle and SQL Server, prevents dirty reads but allows non-repeatable reads. Repeatable Read, the default in MySQL InnoDB, keeps rows read stable within a transaction, and InnoDB also blocks most phantoms with gap locks. Serializable prevents all anomalies but reduces concurrency. Higher isolation means more locking or retries, so choose per use case and set it with @Transactional(isolation = ...).
14

Tell me about a production incident you handled.

Save to ▾
Show answer
Situation: after a release, our login API started returning 500 errors at peak time. Task: as the on-call developer I had to restore service fast. Action: I checked logs and metrics, found the new connection pool settings were too small, rolled back the config and informed stakeholders. Then I led the root cause review and added a load test to the pipeline. Result: service recovered in 20 minutes and the issue never repeated.
15

Write a controller slice test with @WebMvcTest and MockMvc.

Save to ▾
Show answer
@WebMvcTest(ProductController.class) class ProductControllerTest { @Autowired MockMvc mvc; @MockitoBean ProductService service; // @MockBean before Boot 3.4 @Test void returnsProduct() throws Exception { when(service.getProduct(1L)).thenReturn(new ProductDto(1L, "Pen", 20.0)); mvc.perform(get("/api/products/1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("Pen")); } }
16

Why is constructor injection preferred over field injection?

Save to ▾
Show answer
Constructor injection makes dependencies explicit and lets fields be final, so the object is always fully initialised and immutable. It allows plain unit tests without Spring or reflection, because you can pass mocks to the constructor. A long constructor also signals that a class has too many responsibilities. Field injection with @Autowired hides dependencies and needs a container or reflection in tests. With a single constructor, @Autowired is not even needed.
17

Your @Transactional method threw an exception but the data was still saved. Why?

Save to ▾
Show answer
By default Spring rolls back only on unchecked exceptions and Errors, so a checked exception such as IOException commits the transaction. Use @Transactional(rollbackFor = Exception.class) or wrap it in a runtime exception. Other causes are catching the exception inside the method, calling the method from the same class so the proxy is bypassed, a non-public method, or a table engine that does not support transactions such as MyISAM.
18

You are designing a new feature. When would you choose a relational database and when a NoSQL database?

Save to ▾
Show answer
Choose a relational database like PostgreSQL or MySQL when data is structured, relationships matter and you need transactions and joins, such as orders, payments and inventory. Choose NoSQL when you need a flexible schema or huge horizontal scale for simple access patterns: MongoDB for documents, Redis for caching and sessions, Cassandra for high-write time series and Elasticsearch for search. Many systems use both, with SQL as the source of truth.
19

What changed when moving from Spring Boot 2 to Spring Boot 3?

Save to ▾
Show answer
Spring Boot 3 requires Java 17 or later and is built on Spring Framework 6. The biggest migration task is the switch from javax.* to jakarta.* packages for persistence, validation and servlet APIs. Spring Security 6 removed WebSecurityConfigurerAdapter in favour of SecurityFilterChain beans. Boot 3 also supports GraalVM native images, Micrometer observation and tracing, and from 3.2 the RestClient and virtual thread support.
20

Under load, requests fail with a connection timeout from HikariCP. What do you check?

Save to ▾
Show answer
This means all pool connections are busy. Check for long-running queries, transactions held open during remote calls, and connection leaks from code that never closes resources; set leakDetectionThreshold to find them. Compare maximumPoolSize with the database's max connections across all instances, since a bigger pool is not always better. Monitor Hikari metrics through Actuator, fix slow queries and keep @Transactional boundaries short.
21

A downstream service is slow, and your API threads are all stuck waiting. What do you do?

Save to ▾
Show answer
Set connection and read timeouts on every client call, because the defaults can wait far too long. Add a Resilience4j circuit breaker with a fallback and a bulkhead to limit concurrent calls to that service, plus retries only with backoff and only for idempotent requests. Consider caching the downstream data or making the call asynchronous through a queue. Monitor latency percentiles and thread pool usage with Micrometer to confirm the fix.
22

How does column order matter in a composite index?

Save to ▾
Show answer
A composite B-tree index on (customer_id, status, created_at) is sorted by the first column, then the second, and so on. It can serve queries filtering on customer_id, on customer_id and status, or all three, following the leftmost prefix rule, but it cannot efficiently serve a filter on status alone. Put equality columns first and range or sort columns last. A covering index includes all selected columns so the table need not be read.
23

How do you use EXPLAIN to analyse a slow query?

Save to ▾
Show answer
EXPLAIN ANALYZE SELECT o.id, o.total FROM orders o WHERE o.customer_id = 42 AND o.status = 'PAID' ORDER BY o.created_at DESC LIMIT 20; -- Look for: Seq Scan / type=ALL (full scan), large 'rows' estimates, -- 'Using filesort' or a Sort node, and actual time per step. -- Fix with: CREATE INDEX ix_orders_cust_status_date -- ON orders (customer_id, status, created_at DESC);
24

Your application fails at startup with a circular dependency error between two services. What do you do?

Save to ▾
Show answer
Spring Boot 2.6 and later forbid circular references by default. The real fix is design: two services depending on each other usually means a responsibility is in the wrong place. Extract the shared logic into a third bean, or use an application event so one service notifies the other without a direct reference. Using @Lazy or allowing circular references in properties hides the problem and should only be a temporary workaround.
25

Describe a time you improved the performance of an application.

Save to ▾
Show answer
Situation: our dashboard API took eight seconds and users complained. Task: I was asked to bring it under one second. Action: using SQL logs and a profiler, I found N+1 queries and a missing index. I rewrote the query with a DTO projection, added a composite index and cached reference data with a short expiry. Result: response time dropped to about 400 milliseconds, and I added the query-count check to our test suite.
26

Bind custom properties from application.yml into a type-safe class.

Save to ▾
Show answer
# application.yml app: payment: timeout-ms: 3000 retry-count: 2 @ConfigurationProperties(prefix = "app.payment") @Validated public record PaymentProperties( @Min(500) int timeoutMs, @Max(5) int retryCount) {} @SpringBootApplication @EnableConfigurationProperties(PaymentProperties.class) public class App { } // Relaxed binding maps timeout-ms to timeoutMs automatically.
27

A search query that used to take milliseconds now takes 10 seconds as data grew. How do you troubleshoot?

Save to ▾
Show answer
Get the exact SQL from logs or the slow query log and run EXPLAIN ANALYZE to see whether it does a full scan, a bad join order or a big sort. Check for missing or unused indexes, functions on indexed columns, implicit type conversions and outdated statistics. Add the right composite index, rewrite the query, select fewer columns and paginate. For text search, use a full-text index or a search engine instead of LIKE '%term%'.
28

What is the circuit breaker pattern and how is it implemented in Spring?

Save to ▾
Show answer
A circuit breaker stops calling a failing downstream service so failures do not cascade. It is closed during normal operation, opens when the failure rate crosses a threshold, returns a fallback immediately while open, and moves to half-open after a wait to test recovery. In Spring Boot it is implemented with Resilience4j using @CircuitBreaker(name = "payment", fallbackMethod = "fallback"), usually combined with timeouts, retries with backoff and bulkheads.
29

An order service and a payment service have separate databases. How do you keep data consistent when placing an order?

Save to ▾
Show answer
Avoid distributed two-phase commit. Use the saga pattern: each service performs a local transaction and publishes an event, and failures trigger compensating actions, such as cancelling the order if payment fails. Use the transactional outbox pattern so the database write and the event are saved atomically, then a relay publishes to Kafka or RabbitMQ. Make consumers idempotent because events can be delivered more than once.
30

How do profiles and application.yml work in Spring Boot?

Save to ▾
Show answer
Common settings go in application.yml, and environment-specific values go in files like application-dev.yml or application-prod.yml. You activate a profile with spring.profiles.active=prod, an environment variable SPRING_PROFILES_ACTIVE or a command-line argument. Profile files override the default values. Beans can also be limited with @Profile("dev"). Environment variables and command-line arguments have higher priority than files, which is useful in Docker and Kubernetes.
31

Your application logs show database deadlock errors during peak hours. How do you resolve them?

Save to ▾
Show answer
A deadlock happens when two transactions lock rows in opposite order and wait for each other; the database kills one. Read the deadlock report, such as SHOW ENGINE INNODB STATUS, to find the statements. Fix by updating rows in a consistent order, keeping transactions short, avoiding user interaction or remote calls inside transactions and adding indexes so updates lock fewer rows. Also add a retry for the deadlock error because occasional ones are normal.
32

Configure Spring Security 6 for a stateless JWT-secured REST API.

Save to ▾
Show answer
@Configuration @EnableMethodSecurity public class SecurityConfig { @Bean SecurityFilterChain api(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .cors(Customizer.withDefaults()) .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/**", "/actuator/health").permitAll() .requestMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN") .anyRequest().authenticated()) .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults())); return http.build(); } }
33

How does the Spring Security filter chain process a request?

Save to ▾
Show answer
Every request passes through a DelegatingFilterProxy into a FilterChainProxy, which picks the matching SecurityFilterChain. Filters run in order: CORS, CSRF, authentication filters such as BearerTokenAuthenticationFilter, exception translation and finally the authorization filter. Authentication filters build an Authentication object, validate it through the AuthenticationManager and store it in the SecurityContextHolder. The authorization filter then checks rules such as hasRole("ADMIN") before the controller runs.
34

Explain the database design of a project you have worked on.

Save to ▾
Show answer
In my e-commerce project I designed tables for users, addresses, products, categories, orders, order_items and payments. Orders had a foreign key to users, and order_items linked orders and products with quantity and price at purchase time, so later price changes did not affect old orders. I added unique constraints on email and SKU, indexes on order status and date, and used Flyway for version-controlled changes.
35

What is CORS and how do you configure it for a React frontend?

Save to ▾
Show answer
CORS is a browser rule that blocks JavaScript from calling a different origin unless the server allows it with response headers like Access-Control-Allow-Origin. A React app on localhost:5173 calling an API on localhost:8080 is cross-origin. In Spring, define a CorsConfigurationSource bean with the allowed origins, methods and headers, and enable http.cors() in the security chain so preflight OPTIONS requests pass. Never use a wildcard origin together with credentials.
36

Write global exception handling for a REST API in Spring Boot.

Save to ▾
Show answer
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ProblemDetail handleNotFound(ResourceNotFoundException ex) { return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) public ProblemDetail handleValidation(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; } }
37

A user's JWT is stolen and you need to invalidate it before expiry. How would you design for this?

Save to ▾
Show answer
Pure JWTs cannot be revoked, so keep access tokens short-lived, around 10 to 15 minutes, and use refresh tokens stored server-side and rotated on each use. On logout or theft, revoke the refresh token. For immediate blocking, keep a denylist of token IDs or a per-user token version in Redis and check it in the filter. Send refresh tokens in HttpOnly, Secure, SameSite cookies to reduce theft through XSS.
38

What bean scopes does Spring support?

Save to ▾
Show answer
singleton is the default: one instance per application context. prototype creates a new instance every time the bean is requested. Web applications also have request, session and application scopes, and websocket scope. Singleton beans must be stateless or thread-safe because many requests share them. If a singleton needs a prototype or request-scoped bean, inject an ObjectProvider or use a scoped proxy so each use gets the correct instance.
39

A Spring Boot service takes nearly a minute to start. How would you speed it up?

Save to ▾
Show answer
Measure first with the startup Actuator endpoint or ApplicationStartup to see which beans are slow. Common causes are heavy component scanning, eager database or remote calls in @PostConstruct, Hibernate validating a large schema and unneeded auto-configurations. Narrow scan packages, defer work with lazy initialisation or ApplicationReadyEvent, exclude unused starters and use Class Data Sharing. For serverless workloads, consider GraalVM native images or CRaC.
40

Find employees who earn more than their managers.

Save to ▾
Show answer
SELECT e.name AS employee, e.salary, m.name AS manager, m.salary AS manager_salary FROM employees e JOIN employees m ON e.manager_id = m.id WHERE e.salary > m.salary; -- A self join treats the same table as two roles.

Frequently asked questions

What does a Java Technical Lead do?

A technical lead owns the technical direction of a team building Java and React applications. The role includes breaking down requirements, estimating work, choosing frameworks and patterns, ensuring code quality, coordinating with QA, DevOps and product, and resolving critical incidents. Leads still write code but spend more time on architecture, reviews and unblocking the team. They also track delivery risks, run design reviews and help team members grow through feedback and pairing.

Which skills are tested in a Java Technical Lead interview?

Expect questions on Microservices architecture, Technical planning, Stakeholder communication, Incident management, Code quality standards. Most rounds also ask you to explain a project and solve one practical problem live.

How do I prepare for a Java Technical Lead interview?

Revise REST APIs, Security and Microservices, Spring Boot, SQL and Databases first using the topic sheets, practise the questions on this page aloud, then do one full mock interview to practise timing.