Skip to content

Scenario-Based Java Full Stack with React Interview Questions

45 questions with answers. Real-work situations — broken dashboards, flaky tests, unclear requirements — and how a strong java full stack developer would handle them.

How to approach these questions

Clarify the situation, list likely causes, say how you would check each one, then give the fix and how you would stop it happening again.

Solved — scenario-basedStart 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 Spring Boot service crashes with OutOfMemoryError: Java heap space in production. How do you investigate?

Save to ▾
Show answer
First capture evidence: enable -XX:+HeapDumpOnOutOfMemoryError and check GC logs and container memory limits. Open the heap dump in Eclipse MAT or VisualVM and look at the dominator tree for the largest retained objects. Common causes are unbounded caches, loading full tables into lists, static collections that keep growing and large file reads. Fix the leak, add pagination or streaming, set a sensible -Xmx below the container limit and add memory alerts.
02

CPU is at 100 percent and requests are hanging. How would you find the cause in a Java application?

Save to ▾
Show answer
Take several thread dumps a few seconds apart using jstack, jcmd Thread.print or the Actuator threaddump endpoint. Threads stuck in the same RUNNABLE frame point to a hot loop or heavy regex, while threads BLOCKED on each other's locks show a deadlock, which jstack reports directly. Match native thread IDs from top -H to the dump. Profilers such as async-profiler or Java Flight Recorder confirm hot methods before you fix the code.
03

Your code has frequent NullPointerExceptions from repository lookups. How would you redesign it?

Core JavaMedium
Save to ▾
Show answer
Return Optional from lookup methods so callers must handle the missing case, for example findById(id).orElseThrow(). Validate inputs at the API boundary with Bean Validation, initialise collections to empty lists instead of null and use Objects.requireNonNull in constructors. Java 17 helpful NPE messages show which variable was null, which speeds debugging. Do not use Optional for fields or method parameters; it is meant for return values.
04

You need a thread-safe singleton for a configuration loader. How do you implement it?

Core JavaMedium
Save to ▾
Show answer
The simplest safe options are an enum singleton or the holder idiom. With the holder idiom, a private static nested class holds the instance, and the JVM's class loading guarantees lazy, thread-safe initialisation without synchronization. Double-checked locking also works but needs a volatile field. In a Spring application you usually do not write singletons at all, because beans are singleton-scoped by default and the container manages them.
05

A report job builds a large string with + inside a loop and is very slow. What do you change?

Save to ▾
Show answer
Each + inside a loop creates a new String and copies the old content, giving roughly O(n squared) work. Replace it with one StringBuilder created before the loop, optionally with an initial capacity, and call append inside the loop. For joining collections, use String.join or Collectors.joining. For very large output, write directly to a BufferedWriter or stream instead of holding everything in memory.
06

Users in different countries see wrong order times. How do you handle dates and time zones in Java?

Core JavaMedium
Save to ▾
Show answer
Store timestamps in UTC using Instant or OffsetDateTime, and map them to TIMESTAMP WITH TIME ZONE or a UTC timestamp column. Convert to the user's zone only when displaying, using ZonedDateTime with ZoneId such as Asia/Kolkata. Avoid java.util.Date and SimpleDateFormat, which are mutable and not thread-safe. Use DateTimeFormatter, send ISO-8601 strings in JSON and set hibernate.jdbc.time_zone to UTC.
07

You get ConcurrentModificationException while removing items from a list inside a for-each loop. How do you fix it?

Save to ▾
Show answer
The for-each loop uses a fail-fast iterator, and calling list.remove changes the modification count. Use list.removeIf(item -> item.isExpired()), which is clean and efficient, or use an explicit Iterator and call iterator.remove(). Another option is to collect the items to keep into a new list with a stream filter. If several threads modify the list, use a concurrent collection instead.
08

An object put into a HashMap cannot be found later even though it looks equal. What could be wrong?

Save to ▾
Show answer
Most likely a field used in hashCode was changed after insertion, so the object now hashes to a different bucket and get looks in the wrong place. It can also happen when equals is overridden without hashCode. Fix it by using immutable keys, such as records, Strings or IDs, and by basing equals and hashCode on fields that never change. Never mutate an object while it is a key in a hash-based collection.
09

You need to store unique usernames and always display them in alphabetical order. Which collection do you pick?

Save to ▾
Show answer
A TreeSet fits because it rejects duplicates and keeps elements sorted using natural order or a Comparator, with O(log n) add and lookup. Use String.CASE_INSENSITIVE_ORDER as the comparator if Rahul and rahul should be treated as the same. If you only need sorting once at display time, a HashSet followed by sorting may be faster. For concurrent access, ConcurrentSkipListSet is the thread-safe sorted alternative.
10

A teammate replaced a simple for loop in a performance-critical path with a long stream pipeline. Is this a concern?

Save to ▾
Show answer
Streams are usually fine and readable, and the JIT optimises them well, but in very hot loops they can add allocation, boxing and lambda overhead. Check for boxing with Stream<Integer> instead of IntStream, and for repeated sorting or collecting. Measure with a JMH benchmark or profiler rather than guessing. Keep streams where readability matters and use a plain loop only where profiling proves a real bottleneck.
11

You are loading about five lakh records into an ArrayList and a HashMap and memory spikes during loading. What can you do?

Save to ▾
Show answer
Both collections resize by copying when they grow, which causes temporary memory spikes. Pre-size them, for example new ArrayList<>(500000) and HashMap with capacity of expected size divided by 0.75. Better still, avoid holding everything at once: process the data in batches or stream it from the database with pagination. Use primitive-friendly structures or IntStream where possible to avoid boxing overhead.
12

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.
13

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.
14

You need H2 for local development, MySQL for testing and PostgreSQL in production. How do you configure this?

Save to ▾
Show answer
Create application-dev.yml, application-test.yml and application-prod.yml, each with its own spring.datasource URL, username and driver. Keep shared settings in application.yml. Activate the right one with SPRING_PROFILES_ACTIVE in each environment. Read production credentials from environment variables, for example url: ${DB_URL}, instead of hard-coding them. For realistic integration tests, Testcontainers can start the same database engine used in production.
15

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.
16

The application fails with NoSuchBeanDefinitionException for a service. How do you debug it?

Save to ▾
Show answer
Check that the class has @Service or @Component, or is created by a @Bean method. Make sure it is inside the package of the main @SpringBootApplication class or a scanned sub-package. If there are several implementations, use @Qualifier or @Primary. Also check @Profile or @Conditional annotations that may disable it in the current environment. Running with --debug prints the condition report that shows why a bean was not created.
17

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.
18

A product listing page fires hundreds of SQL queries for one request. How do you fix it?

Save to ▾
Show answer
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.
19

Two admins edit the same product price at the same time and one change is silently lost. How do you prevent this?

Save to ▾
Show answer
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.
20

Inserting one lakh rows with saveAll takes many minutes. How do you speed it up?

Save to ▾
Show answer
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.
21

Returning an entity from a REST API causes infinite recursion in JSON. Why, and how do you fix it?

Save to ▾
Show answer
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.
22

The business wants deleted customers to be recoverable. How would you implement soft delete with JPA?

Save to ▾
Show answer
Add a deleted flag or deleted_at timestamp column. With Hibernate 6.4 and later you can annotate the entity with @SoftDelete, or use @SQLDelete to turn delete into an UPDATE and @SQLRestriction to filter deleted rows from queries. Unique constraints must account for deleted rows, for example a partial index on email where deleted is false. Provide an admin restore endpoint and a scheduled job to purge old records for data retention.
23

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.
24

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.
25

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.
26

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.
27

Your public API is being hit by too many requests from a few clients. How do you add rate limiting?

Save to ▾
Show answer
Apply rate limiting at the edge first, in the API gateway, Nginx or the cloud load balancer, keyed by API key, user ID or IP. In Spring Cloud Gateway use the Redis rate limiter, or inside a service use Bucket4j with a token bucket backed by Redis so limits work across instances. Return 429 Too Many Requests with a Retry-After header. Different plans or endpoints like login can have stricter limits.
28

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.
29

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%'.
30

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.
31

A security review found a login query built by string concatenation. What is the risk and the fix?

Save to ▾
Show answer
Concatenating user input into SQL allows SQL injection, where input like ' OR '1'='1 changes the query and can bypass login or dump data. Use parameterised queries: PreparedStatement with ? placeholders, Spring Data method queries, or @Query with named parameters, which send values separately from the SQL. Also validate input, use a database user with least privilege and never show raw SQL errors to users.
32

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.
33

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.
34

Paging through a large table with OFFSET becomes very slow on later pages. What is a better approach?

Save to ▾
Show answer
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.
35

Your component keeps re-rendering in an infinite loop after calling an API. What is wrong?

Save to ▾
Show answer
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.
36

A table showing 10,000 rows makes the page very slow. How would you improve it?

Save to ▾
Show answer
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.
37

Where should a React app store the JWT, and what are the trade-offs?

Save to ▾
Show answer
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.
38

In a search box, older API responses sometimes overwrite newer results. How do you fix this race condition?

Save to ▾
Show answer
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.
39

You are passing the same user prop through five levels of components. What would you do?

Save to ▾
Show answer
This is prop drilling, which makes intermediate components depend on data they do not use. For global, rarely changing data like the logged-in user or theme, create a context with a provider at the top and read it with useContext through a custom hook such as useAuth. Alternatively, use component composition, passing ready-made elements as children. For complex shared state, a store like Zustand or Redux Toolkit is suitable.
40

After calling setCount(count + 1), console.log(count) still shows the old value. Why?

Save to ▾
Show answer
State updates are scheduled, not applied immediately. The count variable in the current render is a constant snapshot, so logging right after setState shows the old value; the new value appears in the next render. React also batches multiple updates. When the next state depends on the previous one, use the updater form setCount(c => c + 1), which works correctly even when called several times. Use useEffect to react to the updated value.
41

Your React app's home page takes 6 seconds to load on mobile. How would you improve it?

Save to ▾
Show answer
Measure with Lighthouse and the browser Performance tab, and check Core Web Vitals such as LCP and INP. Then reduce JavaScript with route-based code splitting and removing heavy libraries, compress and lazy-load images using modern formats like WebP or AVIF with proper sizes, enable gzip or Brotli and long-term caching through a CDN, and avoid render-blocking resources. Server-side rendering or pre-rendering, for example with Next.js, can improve first paint further.
42

A security test shows a stored XSS vulnerability in a comments feature. How do you fix it?

Save to ▾
Show answer
Stored XSS happens when user input containing script is saved and later rendered as HTML. React escapes text by default, so look for dangerouslySetInnerHTML, direct innerHTML or unsafe URL attributes like javascript: links. If rich text is required, sanitise it with a library like DOMPurify, and validate on the server too. Add a Content Security Policy header and keep tokens out of JavaScript-readable storage to limit damage.
43

The layout looks fine on desktop but breaks on mobile with horizontal scrolling. How do you debug it?

Save to ▾
Show answer
Check that the page has the viewport meta tag. Use browser device mode to find the element wider than the screen, often fixed widths in pixels, large images, long words or tables. Replace fixed widths with max-width: 100 percent, flexible units and flex-wrap, add overflow-wrap for long text and wrap wide tables in a scrollable container. Build mobile-first with media queries that add complexity for larger screens.
44

Memory usage of a single-page app keeps growing the longer it stays open. What could cause this?

Save to ▾
Show answer
Common causes are event listeners, intervals or WebSocket subscriptions that are never removed when a component unmounts, growing global caches or arrays, and detached DOM nodes still referenced by JavaScript. In React, return cleanup functions from useEffect to remove listeners and clear timers. Use the Chrome DevTools Memory tab with heap snapshots to compare before and after navigation and find retained objects.
45

Your team is starting a new React project. Would you use Create React App or something else?

Save to ▾
Show answer
Create React App is deprecated and no longer recommended. For a single-page app backed by a Spring Boot API, Vite is the usual choice because of its fast dev server and optimised builds. If you need server-side rendering, SEO or file-based routing, a framework like Next.js or React Router in framework mode is recommended by the React team. Choose based on SEO needs, hosting and the team's experience.

Frequently asked questions

Why are scenario-based questions important?

They show how you think on real problems. Interviewers use them to separate people who memorised definitions from people who have done the work.

How should I answer them?

Clarify the situation, list likely causes, say how you would check each one, then give the fix and how you would stop it happening again.