Senior Java Full Stack Engineer Interview Questions & Answers
40 questions for Senior Java Full Stack Engineer interviews — 21 medium, 19 hard.
About the Senior Java Full Stack Engineer role
A senior full stack engineer designs features and services, reviews code, mentors juniors and handles production issues. They make decisions about API contracts, database design, caching, security and frontend architecture, and they balance delivery speed with quality. Interviews include system design, performance troubleshooting and behavioural questions about ownership and leadership. They also plan releases, set coding standards and guide the team on testing, observability and deployment practices so that features stay reliable after launch.
System design Performance tuning Security best practices Mentoring CI/CD and Docker
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
How do indexes improve performance, and when can they hurt?
An index, usually a B-tree, lets the database find rows without scanning the whole table, which speeds up WHERE, JOIN and ORDER BY on indexed columns. Indexes cost disk space and slow down INSERT, UPDATE and DELETE because each index must also be updated. They help little on low-selectivity columns like a boolean flag. Functions on the column, such as WHERE LOWER(email) = ?, or a leading wildcard in LIKE also prevent normal index use.
02
Call another microservice from Spring Boot using RestClient with a timeout.
mappedBy marks the inverse side and names the field on the other entity that owns the relationship. The owning side, usually the @ManyToOne with the foreign key column, is the one Hibernate uses to write the join column. For example, Order has @OneToMany(mappedBy = "order") and OrderItem has @ManyToOne @JoinColumn(name = "order_id"). Always update both sides in helper methods such as addItem to keep the object graph consistent.
04
Implement pagination and sorting for a product list API.
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.
07
Build a dynamic search with optional filters using JPA Specifications.
With OFFSET 500000, the database still reads and discards half a million rows. Use keyset or seek pagination instead: remember the last seen sort key and query WHERE (created_at, id) < (:lastDate, :lastId) ORDER BY created_at DESC, id DESC LIMIT 20, backed by a matching index. This is fast at any depth and stable when new rows arrive. The trade-off is no direct jump to page N, which suits infinite scroll and APIs.
09
Two admins edit the same product price at the same time and one change is silently lost. How do you prevent this?
This is a lost update. Add a @Version column for optimistic locking, send the version to the frontend with the entity, and include it in the update request. If the version no longer matches, Hibernate throws an optimistic lock exception, and the API returns HTTP 409 Conflict so the user can reload and retry. For short, high-contention operations like stock decrement, use a pessimistic lock or an atomic UPDATE with a condition.
10
What causes LazyInitializationException and how do you fix it properly?
It occurs when a lazy association is accessed after the persistence context has closed, for example in a controller or during JSON serialisation outside the transaction. The proper fix is to fetch the data inside the service transaction using JOIN FETCH or @EntityGraph and map it to a DTO. Avoid enabling spring.jpa.open-in-view as a crutch, and avoid switching associations to eager, because both hide performance problems.
11
Add the JWT to every API call and handle 401 responses using an Axios interceptor.
The first-level cache is the persistence context itself. It is enabled by default and scoped to a session or transaction, so loading the same entity twice returns the same object without a second query. The second-level cache is optional and shared across sessions, configured with a provider like Ehcache or Infinispan through JCache. It suits read-mostly reference data. In clustered systems many teams prefer an explicit Redis cache at the service layer instead.
13
What is the difference between persist and merge, and between save and saveAndFlush?
persist makes a new entity managed and assigns its ID; it fails for detached entities. merge copies the state of a detached entity onto a managed copy and returns that copy. Spring Data save calls persist for new entities and merge otherwise. saveAndFlush also calls flush, pushing pending SQL to the database immediately, which helps when you need a constraint error or trigger result now. The commit still happens at the end of the transaction.
Bidirectional relationships, such as Order having items and each item referencing its order, make Jackson serialise back and forth endlessly, leading to StackOverflowError. The cleanest fix is to return DTOs instead of entities, so you control exactly what is exposed. Quick fixes include @JsonManagedReference with @JsonBackReference or @JsonIgnore on one side. DTOs also stop lazy loading during serialisation and avoid leaking internal fields.
16
What is the difference between lazy and eager fetching?
Lazy fetching loads an association only when it is first accessed, using a proxy. Eager fetching loads it immediately with the parent. By default, @OneToMany and @ManyToMany are lazy, while @ManyToOne and @OneToOne are eager. Best practice is to make all associations lazy and fetch what each use case needs with JOIN FETCH or entity graphs, because eager loading often pulls large object graphs and causes extra queries.
17
What is the difference between controlled and uncontrolled components?
In a controlled component, form input values live in React state and change through onChange, so React is the single source of truth, which makes validation and conditional UI easy. In an uncontrolled component, the DOM keeps the value and you read it through a ref when needed, which needs less code and suits simple forms or file inputs. Libraries like React Hook Form use uncontrolled inputs for better performance in large forms.
18
Describe a time you improved the performance of an application.
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.
19
What triggers a re-render in React, and how does reconciliation decide what to update?
A component re-renders when its state changes, its parent re-renders, or a context it uses changes. Props changing is not itself the trigger; parent re-render is. During reconciliation React compares element types: a different type at the same position destroys and recreates the subtree, while the same type updates props. Keys identify list children. React.memo skips a child re-render when its props are shallowly equal.
20
How does column order matter in a composite index?
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.
21
What roles do an API gateway and service discovery play in microservices?
An API gateway, such as Spring Cloud Gateway, is the single entry point for clients. It handles routing, authentication, rate limiting, CORS and request logging. Service discovery lets services find each other without hard-coded addresses: with Eureka or Consul, services register themselves, and clients look them up. On Kubernetes, built-in Services and DNS usually replace a separate discovery server, and an ingress or gateway handles external traffic.
22
What is CORS and how do you configure it for a React frontend?
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.
23
In a search box, older API responses sometimes overwrite newer results. How do you fix this race condition?
Each keystroke starts a request, and responses can arrive out of order. Debounce the input by about 300 milliseconds so fewer requests are sent. In the effect, cancel the previous request with AbortController in the cleanup function, or keep an ignore flag so stale responses are discarded. Libraries like TanStack Query handle this automatically by keying queries on the search term and ignoring outdated results.
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);
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.
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.
27
Inserting one lakh rows with saveAll takes many minutes. How do you speed it up?
Enable JDBC batching with hibernate.jdbc.batch_size of 50 or so, plus order_inserts and order_updates. IDENTITY ID generation disables insert batching in Hibernate, so use a SEQUENCE generator with an allocation size on PostgreSQL or Oracle. Flush and clear the persistence context every batch to keep memory low. For very large loads, use JdbcTemplate batchUpdate or the database's bulk loader like COPY or LOAD DATA, which is much faster than ORM.
28
An order service and a payment service have separate databases. How do you keep data consistent when placing an order?
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.
29
A table showing 10,000 rows makes the page very slow. How would you improve it?
Rendering thousands of DOM nodes is costly. Use server-side pagination or infinite scroll so the API returns only one page. If all rows must be scrollable, use list virtualization with a library like TanStack Virtual or react-window, which renders only visible rows. Memoize row components with React.memo, keep stable keys, avoid inline heavy calculations, and debounce filters. Profile with React DevTools Profiler to confirm which components are slow.
30
Mentoring: how would you help a junior developer who keeps pushing untested Spring code?
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.
31
A product listing page fires hundreds of SQL queries for one request. How do you fix it?
Enable SQL logging or Hibernate statistics to confirm it is the N+1 problem, usually from lazy associations accessed while mapping entities to JSON. Fetch the required associations in one query with JOIN FETCH or @EntityGraph, or select a DTO projection with only the needed columns. For collections combined with pagination, page the parent IDs first and then fetch children with an IN query, or use batch fetch size. Add a test that asserts the query count.
32
Your component keeps re-rendering in an infinite loop after calling an API. What is wrong?
Usually useEffect sets state and has a dependency that changes on every render, or has no dependency array at all. A common case is an object or function created inside the component and listed as a dependency, so it is new each time. Fix it by using a correct dependency array, moving the object outside the component, or memoizing it with useMemo or useCallback. Also check that you are not calling setState directly during render.
33
Where should a React app store the JWT, and what are the trade-offs?
localStorage is simple but any XSS script can read it. In-memory storage is safer but is lost on refresh. The commonly recommended pattern is a short-lived access token kept in memory and a refresh token in an HttpOnly, Secure, SameSite cookie that JavaScript cannot read, used to get new access tokens. Cookies need CSRF protection for state-changing calls. Whatever you choose, prevent XSS with proper escaping and a Content Security Policy.
34
Explain transaction isolation levels and the problems each one prevents.
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 = ...).
35
Users must upload files up to 200 MB. How do you design the upload API?
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.
36
A search query that used to take milliseconds now takes 10 seconds as data grew. How do you troubleshoot?
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%'.
37
Write a Flyway migration to add a column and index to an existing table.
-- src/main/resources/db/migration/V3__add_sku_to_products.sql
ALTER TABLE products ADD COLUMN sku VARCHAR(40);
UPDATE products SET sku = CONCAT('SKU-', id) WHERE sku IS NULL;
ALTER TABLE products ALTER COLUMN sku SET NOT NULL;
CREATE UNIQUE INDEX ux_products_sku ON products (sku);
# application.yml
# spring.jpa.hibernate.ddl-auto: validate
# Flyway runs pending V-scripts in order at startup.
Add a numeric or timestamp field annotated with @Version. Hibernate includes it in the UPDATE where clause and increments it. If another transaction already changed the row, no rows match, and an OptimisticLockException is thrown. This prevents lost updates without holding database locks, which suits web apps with low conflict. The API can return HTTP 409 and ask the user to reload. Pessimistic locking with SELECT FOR UPDATE suits high-conflict cases like seat booking.
40
A user's JWT is stolen and you need to invalidate it before expiry. How would you design for this?
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.
Frequently asked questions
What does a Senior Java Full Stack Engineer do?
A senior full stack engineer designs features and services, reviews code, mentors juniors and handles production issues. They make decisions about API contracts, database design, caching, security and frontend architecture, and they balance delivery speed with quality. Interviews include system design, performance troubleshooting and behavioural questions about ownership and leadership. They also plan releases, set coding standards and guide the team on testing, observability and deployment practices so that features stay reliable after launch.
Which skills are tested in a Senior Java Full Stack Engineer interview?
Expect questions on System design, Performance tuning, Security best practices, Mentoring, CI/CD and Docker. Most rounds also ask you to explain a project and solve one practical problem live.
How do I prepare for a Senior Java Full Stack Engineer interview?
Revise REST APIs, Security and Microservices, JPA and Hibernate, React Frontend, SQL and Databases first using the topic sheets, practise the questions on this page aloud, then do one full mock interview to practise timing.