Java, Spring Boot, AWS & Microservices Interview Questions – Top 35 Questions and Answers for Senior Developers


Senior backend interviews are no longer limited to Java syntax or Spring Boot annotations. Interviewers increasingly expect developers to understand Java internals, Spring Boot behavior, database performance, distributed systems, Kafka, AWS architecture, resilience, observability, and production troubleshooting.

This guide covers 35 Java, Spring Boot, AWS and Microservices interview questions with practical answers. It moves from core Java and concurrency to Spring Boot, JPA, security, microservices, Kafka, AWS and a complete scalable e-commerce system design.

These questions are especially useful for Senior Java Developers, Senior Backend Developers, Spring Boot Developers, Microservices Developers and Software Architects preparing for technical interviews.

1. How does HashMap work internally in Java?

HashMap stores key-value entries in an internal bucket array. The key's hash is used to determine the bucket where the entry should be stored.

When multiple keys map to the same bucket, Java handles collisions using linked nodes and, under suitable conditions, can transform a long bucket chain into a balanced tree structure.

HashMap uses both hashCode() and equals() to locate the correct key. Its average lookup complexity is O(1), although collisions can affect performance.

When the number of entries crosses the resize threshold, the internal table grows and entries are redistributed.

Interview tip: If an object is used as a HashMap key, its equals() and hashCode() implementations must follow their contract.

2. What is the difference between HashMap and ConcurrentHashMap?

HashMap ConcurrentHashMap
Not designed for concurrent modification Designed for concurrent access
Allows null key and null values Does not allow null keys or values
External synchronization may be required Provides concurrency control internally

ConcurrentHashMap is useful when multiple threads need to read and update shared map data without synchronizing the entire map around every operation.

It is commonly used for shared in-memory state where concurrent reads and updates are required.

3. How does Java handle multithreading and concurrency?

Java provides threads, synchronization, locks, atomic classes, concurrent collections, executor frameworks and higher-level APIs such as CompletableFuture.

For server applications, I would normally avoid creating unmanaged threads for every request or task. ExecutorService and appropriately configured application-managed executors provide better control over concurrency.

Shared mutable state requires appropriate synchronization or atomic operations to prevent race conditions and establish safe visibility.

Modern Java applications can also use virtual threads for suitable high-concurrency, I/O-bound workloads, while CPU-bound work still requires careful consideration of available processors and workload characteristics.

4. What is the difference between synchronized, volatile, and AtomicInteger?

  • synchronized: Provides mutual exclusion and memory-visibility guarantees around the synchronized region.
  • volatile: Provides visibility and ordering guarantees for a variable, but does not make compound operations such as increment atomic.
  • AtomicInteger: Provides atomic operations using concurrency mechanisms such as compare-and-set.

For example, count++ is not made thread-safe merely by declaring count volatile because the increment consists of multiple steps.

If multiple operations need to happen as one atomic unit, synchronization or an appropriate locking strategy may be required.

5. How do Java Streams work internally?

A Stream represents a pipeline over a data source. Intermediate operations such as filter() and map() are generally lazy. Processing begins when a terminal operation such as collect(), count() or forEach() is invoked.

Source
   |
   v
Intermediate Operations
   |
   v
Terminal Operation

Streams can make data-processing code more expressive, but they are not automatically faster than traditional loops.

Parallel streams also require careful consideration of workload, shared state and execution behavior. Using parallelStream() does not automatically improve application performance.

6. How would you troubleshoot high CPU usage in a Java application?

I would first confirm the CPU spike and identify which process and threads are consuming CPU.

  1. Check host or container CPU metrics.
  2. Identify the Java process.
  3. Capture thread information or thread dumps.
  4. Map high-CPU native thread IDs to Java thread IDs.
  5. Inspect the corresponding stack traces.
  6. Use profiling or Java Flight Recorder when necessary.

Common causes include tight loops, excessive serialization, inefficient algorithms, excessive logging, thread contention, garbage collection or unexpectedly high request volume.

The important point is to identify the actual CPU-consuming code before changing JVM or Kubernetes resource settings.

7. How would you investigate a Java memory leak?

I would first distinguish a genuine memory leak from normal heap growth or a legitimate increase in workload.

I would examine heap usage and garbage-collection behavior. If memory continues growing after collections, I would capture a heap dump and analyze retained objects and GC roots.

Common causes include:

  • Static collections
  • Unbounded caches
  • ThreadLocal misuse
  • Listeners that are never removed
  • Retained session data
  • Unexpectedly large object graphs

Heap analysis tools and Java Flight Recorder can help identify what is retaining memory.

8. How does Spring Boot auto-configuration work?

Spring Boot evaluates the classpath, configuration properties and conditional rules and creates appropriate beans when the required conditions are satisfied.

Auto-configuration is conditional rather than blindly creating every possible bean.

For example, when database-related dependencies and configuration are present, Spring Boot can configure appropriate infrastructure automatically.

Developers can override auto-configuration by defining their own beans or changing configuration.

Interview point: Auto-configuration is one of the main reasons Spring Boot applications can be started with relatively little explicit configuration.

9. How does Spring Boot handle dependency injection?

Spring's IoC container creates and manages beans and injects dependencies between them.

Constructor injection is generally preferred because dependencies are explicit and required dependencies can be enforced when the object is created.

@Service
public class OrderService {

    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

Spring discovers the bean and supplies it to the constructor when creating the OrderService.

Constructor injection also makes unit testing easier because dependencies can be passed directly into the class.

10. How does @Transactional work internally?

@Transactional is implemented through Spring's transaction infrastructure, commonly using proxies around the target bean.

When a transactional method is invoked through the appropriate proxy, Spring starts or joins a transaction according to the configured propagation behavior.

The transaction is committed on successful completion or rolled back according to the configured rollback rules when an applicable exception occurs.

The proxy model is important because direct self-invocation inside the same object can bypass the transactional proxy.

Caller
  |
  v
Spring Proxy
  |
  +---- Start / Join Transaction
  |
  v
Target Method
  |
  v
Commit / Rollback

11. Why might @Transactional fail to roll back a transaction?

Several situations can cause unexpected rollback behavior.

  • The exception does not match the configured rollback rules.
  • The exception is caught and not propagated as expected.
  • The method is invoked through self-invocation and bypasses the transactional proxy.
  • The database operation is not participating in the expected transaction.
  • Transaction propagation is different from what the developer assumed.
  • The transaction boundary does not cover the operation that actually failed.

When investigating the issue, inspect the exception type, transaction boundaries, proxying, propagation and actual database behavior.

12. How would you optimize a slow Spring Boot API?

I would first identify where the latency is coming from instead of immediately adding more CPU or caching.

I would inspect:

  • p95 and p99 latency
  • Database query time
  • Number of database queries
  • Connection-pool wait time
  • Downstream service latency
  • Serialization and payload size
  • CPU and garbage collection
  • Thread-pool saturation

Distributed tracing is particularly useful when the API calls multiple dependencies.

A typical investigation might reveal:

API Latency: 4.8 seconds

Database:       3.5 sec
Payment API:    0.9 sec
Serialization:  0.2 sec
Application:    0.2 sec

In this case, increasing the application's CPU would not solve the primary bottleneck.

13. How would you troubleshoot HikariCP connection pool exhaustion?

I would inspect active, idle and pending connections along with connection acquisition time.

Possible causes include:

  • Slow queries
  • Long-running transactions
  • Connection leaks
  • Insufficient pool sizing
  • Downstream waits while holding a database connection
  • Sudden traffic increases

Increasing the pool size blindly can simply move the bottleneck to the database.

I would first identify why connections are being held for too long.

A useful investigation is:

Application
     |
     v
HikariCP
     |
     +---- Active Connections
     |
     +---- Pending Requests
     |
     v
Database

14. How would you solve an N+1 query problem in Spring Data JPA?

N+1 occurs when an initial query retrieves N entities and additional queries are executed while accessing related data.

For example:

SELECT * FROM orders;

SELECT * FROM customer WHERE id = 1;
SELECT * FROM customer WHERE id = 2;
SELECT * FROM customer WHERE id = 3;
...
SELECT * FROM customer WHERE id = N;

Depending on the use case, solutions include:

  • JOIN FETCH
  • Entity graphs
  • DTO projections
  • Batch fetching
  • Explicit query design

Simply changing everything to eager loading can create a different performance problem. The solution should match the API's actual data requirements.

15. How would you secure a Spring Boot REST API using JWT?

A typical design uses an authorization server or identity provider to issue JWT access tokens. The Spring Boot API acts as a resource server and validates the token.

Validation should cover relevant properties such as:

  • Signature
  • Issuer
  • Audience
  • Expiration
  • Authorities or scopes

Authorization rules should be enforced at the API boundary and, where appropriate, at the service or method level.

Client
  |
  | JWT Access Token
  v
API Gateway
  |
  v
Spring Boot Resource Server
  |
  +---- Validate Token
  |
  +---- Check Authorities
  |
  v
Business Logic

16. How would you implement OAuth2 authentication in Spring Boot?

First identify the OAuth2 role of the application.

A browser application performing user login may act as an OAuth2 client, while a backend API commonly acts as a resource server.

The authorization server or identity provider handles authentication and token issuance. The resource server validates access tokens and enforces authorization.

OAuth2 provides authorization and delegated access mechanisms, while OpenID Connect adds an identity layer for user authentication.

17. How would you design communication between microservices?

I would use synchronous communication when an immediate response is required and asynchronous messaging when work can be decoupled.

Client
  |
  v
Order Service
  |
  +---- REST / gRPC ----> Product Service
  |
  +---- Kafka Event ----> Notification Service

Every synchronous dependency should have a timeout, and critical calls may require circuit breakers, retries and bulkheads.

The choice should be driven by business requirements and failure characteristics.

18. REST vs Kafka — when would you choose each?

REST Kafka
Immediate request-response Asynchronous processing
Simple queries and commands Event-driven workflows
Caller needs an immediate result Multiple consumers can react independently
Simple interaction model Useful for decoupling and buffering workloads

For example, retrieving product information may naturally be synchronous.

Sending an OrderCreated event to Notification and Analytics services may be better handled asynchronously.

19. How would you prevent cascading failures between microservices?

I would combine:

  • Timeouts
  • Bounded retries
  • Circuit breakers
  • Bulkheads
  • Rate limiting
  • Graceful degradation
  • Asynchronous processing where appropriate

For example, if a Recommendation Service is unavailable, the Product Service should ideally still return product information rather than failing the entire request.

Product Request
      |
      +---- Product Service → Success
      |
      +---- Recommendation → Failure
                              |
                              v
                         Degraded Response

20. How would you implement Retry, Circuit Breaker, and Bulkhead?

Each mechanism solves a different problem.

  • Retry: Retry suitable transient failures with a bounded count and exponential backoff with jitter.
  • Circuit Breaker: Stop calling a dependency after repeated failures and periodically allow test calls to determine recovery.
  • Bulkhead: Isolate resources so one slow dependency cannot consume all threads or connections.

Retries should never be unlimited.

Retrying non-idempotent operations without protection can create duplicate business effects.

For example:

Request
   |
   v
Payment Service
   |
   X Timeout
   |
 Retry?
   |
   +---- Must be idempotent
   |
   v
Payment Provider

21. How would you design idempotent APIs in microservices?

I would use an idempotency key for operations where duplicate execution has business consequences.

POST /orders

Idempotency-Key: order-request-123

The service stores the key and the outcome.

If the same request arrives again, the service returns the existing result instead of creating another order.

This is particularly important for:

  • Payments
  • Orders
  • Reservations
  • Bookings
  • Other externally visible operations

22. How would you handle distributed transactions using the Saga pattern?

A Saga breaks a distributed business transaction into local transactions.

Order Created
     |
     v
Payment Completed
     |
     v
Inventory Reserved
     |
     v
Order Confirmed

If inventory reservation fails after payment succeeds, a compensating action can refund or cancel the payment.

Sagas can be implemented using:

  • Choreography: Services react to events.
  • Orchestration: A coordinator controls the workflow.

For complex workflows, orchestration can make the overall state transitions easier to understand and monitor.

23. How would you maintain data consistency between microservices?

Each service should own its data and expose business operations through APIs or events rather than allowing other services to directly modify its tables.

For database changes that must reliably produce an event, the Transactional Outbox Pattern can be used.

Local Transaction
      |
      +---- Update Business Data
      |
      +---- Write Outbox Event
                   |
                   v
              Event Publisher
                   |
                   v
                 Kafka

Eventual consistency is often acceptable for derived data, notifications and search indexes, while critical business invariants should be explicitly protected.

24. How would you handle duplicate Kafka messages?

I would assume that consumers can see duplicate events and make the business operation idempotent.

Event ID: EVT-1001

First delivery
      |
      v
Process Event
      |
      v
Save EVT-1001

Second delivery
      |
      v
Detect EVT-1001
      |
      v
Skip Duplicate Effect

A consumer can persist the event ID or business idempotency key.

Database uniqueness constraints can provide another layer of protection.

The key principle is that duplicate delivery should not result in duplicate business effects.

25. How would you troubleshoot increasing Kafka consumer lag?

Consumer lag means consumers are not keeping up with the messages being produced.

I would check:

  • Consumer throughput
  • Partition count
  • Number of consumer instances
  • Processing latency
  • Database latency
  • Downstream dependency latency
  • Consumer errors
  • Consumer rebalances
  • CPU and memory
  • Message size

If processing is CPU or I/O bound, scaling consumers may help, provided the topic has enough partitions.

If the bottleneck is a database, simply adding consumers can increase database pressure instead of solving the root problem.

A typical investigation might look like:

Kafka
  |
  +---- Partition 0 → Consumer 1
  |
  +---- Partition 1 → Consumer 2
  |
  +---- Partition 2 → Consumer 3

Lag Increasing
      |
      v
Check Consumer Throughput
      |
      v
Check Processing Dependency
      |
      v
Scale or Fix Bottleneck

26. How would you design service discovery in a microservices architecture?

In Kubernetes, Services and DNS can provide service discovery.

order-service
payment-service
inventory-service

Applications communicate with logical service names rather than individual pod IP addresses.

In other environments, a dedicated service registry can be used.

The architecture should also account for instance health, load balancing and service lifecycle.

27. How would you design an API Gateway for microservices?

The API Gateway provides a controlled entry point into the backend.

Common responsibilities include:

  • Routing
  • Authentication integration
  • Rate limiting
  • Request correlation
  • TLS termination
  • API version management
  • Sometimes request aggregation
                    API Gateway
                         |
          +--------------+--------------+
          |              |              |
          v              v              v
      Product          Order         Customer
      Service          Service        Service

Business logic should generally remain in the services rather than accumulating inside the gateway.

28. How would you deploy Spring Boot microservices on AWS?

I would choose the AWS compute platform based on operational requirements.

Users
  |
Route 53
  |
Load Balancer
  |
ECS / EKS
  |
Spring Boot Microservices
  |
+-----------+-------------+
|           |             |
RDS     ElastiCache      Kafka

Container images can be stored in Amazon ECR.

Application configuration and secrets should be managed using appropriate AWS services rather than hard-coded into container images.

CloudWatch, application metrics and distributed tracing can provide operational visibility.

29. ECS vs EKS — when would you choose each for Java microservices?

ECS EKS
AWS-managed container orchestration Managed Kubernetes control plane
Typically simpler operational model Kubernetes ecosystem and APIs
Good when Kubernetes-specific capabilities are not required Useful when the organization standardizes on Kubernetes

The decision should consider:

  • Team expertise
  • Operational complexity
  • Existing platform standards
  • Portability requirements
  • Kubernetes ecosystem requirements

30. How would you design high availability across AWS Availability Zones?

I would avoid placing critical application capacity in a single Availability Zone.

                  Load Balancer
                   /        \
                  /          \
               AZ-A          AZ-B
                |              |
          App Instances   App Instances
                \              /
                 \            /
                  Shared Data

Application instances should be distributed across multiple Availability Zones behind a load balancer.

Stateful dependencies such as databases also need an appropriate high-availability strategy.

High availability is not just about running two application instances. The database, cache, messaging and network layers also need to be considered.

31. How would you use AWS RDS for a highly available Spring Boot application?

I would use an appropriate RDS high-availability configuration and ensure that the application can handle database failover without relying on a fixed database instance address.

The application should also use sensible connection-pool settings, timeouts and controlled retry behavior.

Database HA does not eliminate application-level failures.

Connection pools, transactions, slow queries, locks and database resource utilization still need to be monitored.

32. How would you use ElastiCache to improve microservice performance?

ElastiCache can reduce repeated reads against the primary database for suitable workloads.

A common cache-aside flow is:

Request
   |
   v
Check Cache
  /     \
Hit     Miss
 |        |
Return   Database
            |
            v
          Cache
            |
            v
          Return

The design should define:

  • TTL
  • Invalidation strategy
  • Cache-aside behavior
  • Cache stampede protection
  • Behavior when the cache is unavailable

A cache should improve a known workload problem rather than hide inefficient database queries.

33. How would you monitor Java microservices using CloudWatch, metrics, and distributed tracing?

I would monitor both infrastructure and application-level signals.

Important metrics include:

  • Request rate
  • Error rate
  • p95 and p99 latency
  • CPU
  • Memory
  • JVM heap
  • Garbage collection
  • Database connection pool usage
  • Kafka lag
  • Container restarts
  • Downstream dependency latency

Logs provide detailed events, metrics provide trends and alerts, and distributed tracing shows how a request travels across services.

The goal is to correlate these signals during an incident rather than investigating each system in isolation.

Request
   |
   v
API Gateway
   |
   v
Order Service
   |
   +---- Trace
   |
   +---- Logs
   |
   +---- Metrics
   |
   v
Payment Service
   |
   v
Database

34. A production microservice suddenly becomes slow. How would you troubleshoot Java, Spring Boot, AWS, database, and network issues?

I would follow a structured investigation rather than immediately changing configuration.

Step 1: Confirm the symptom

Check request rate, p50, p95 and p99 latency and error rate.

Step 2: Check infrastructure

Inspect CPU, memory, container restarts, network metrics and scaling events.

Step 3: Check the JVM

Look for garbage-collection pressure, thread contention, blocked threads and unusual CPU usage.

Step 4: Check Spring Boot

Inspect thread pools, request processing, connection pools and downstream client metrics.

Step 5: Check the database

Look for slow queries, lock contention, connection-pool exhaustion, increased query volume and changes in execution plans.

Step 6: Check dependencies

Use distributed traces to identify whether another microservice or external API is responsible for the latency.

Step 7: Check AWS and network changes

Review deployment events, load balancer behavior, scaling events, security and network changes and infrastructure alarms.

The key is to correlate the timeline and verify hypotheses using metrics, logs and traces.

For example, if latency increased immediately after a deployment, I would compare the new deployment against the previous version rather than assuming that the database is responsible.

35. Design a highly scalable e-commerce system using Java, Spring Boot, Microservices, Kafka, AWS, caching, and a relational database. How would you handle failures, traffic spikes, and data consistency?

A production-oriented architecture could look like this:

                         Users
                           |
                           v
                    Route 53 / CDN
                           |
                           v
                    Load Balancer
                           |
                           v
                     API Gateway
                           |
       +-------------------+-------------------+
       |          |         |        |          |
       v          v         v        v          v
    Product    Customer    Cart    Order     Search
       |                    |        |
       |                    |        +------+
       |                    |               |
       v                    v               v
    Redis                 Redis          Kafka
                                         / | \
                                        /  |  \
                                       v   v   v
                                  Payment Inventory
                                     |       |
                                     +---+---+
                                         |
                                         v
                                        RDS

Kafka → Notification / Analytics / Other Consumers

Handling traffic spikes

  • Horizontally scale stateless Spring Boot services.
  • Load balance across instances and Availability Zones.
  • Use Redis for suitable read-heavy workloads.
  • Apply rate limiting at the edge.
  • Use Kafka to buffer asynchronous workloads.
  • Optimize database queries and connection pools.

Handling service failures

Use timeouts, circuit breakers, bounded retries and bulkheads for synchronous dependencies.

Non-critical functionality should degrade gracefully.

For example, a recommendation failure should not necessarily prevent checkout.

Handling payment failures

Payment operations should be idempotent.

The system should maintain explicit payment states and reconcile uncertain outcomes with the payment provider rather than blindly retrying a potentially completed payment.

Handling data consistency

Each service owns its data.

Cross-service workflows use events and Saga-style compensation where required.

Handling duplicate Kafka messages

Consumers should be idempotent using event IDs, business keys and database constraints where appropriate.

Handling database failures

The relational database should have an appropriate high-availability configuration.

Application services should use connection timeouts, pool limits and controlled retry behavior.

Handling observability

Metrics, structured logs and distributed traces should be correlated using request and trace identifiers.

Handling deployments

Use rolling or similarly controlled deployments, readiness checks, graceful shutdown and backward-compatible database migrations.

Senior-level answer: The architecture is not complete until failure scenarios are designed. Explain not only how a successful order works, but also what happens when payment fails, inventory is unavailable, Kafka delivers a duplicate event, Redis is unavailable, traffic suddenly increases, or the database becomes slow.

What Interviewers Look For in Senior Java Backend Candidates

At senior level, naming a technology is not enough.

A strong answer explains why the technology is needed, what trade-offs it introduces, and how the system behaves when something fails.

For example, saying "I will use Kafka" is only the beginning.

A strong candidate should explain:

  • Why Kafka is required
  • Which events are produced
  • Which services consume them
  • How duplicate messages are handled
  • How retries work
  • How failed processing is recovered
  • How data consistency is maintained

Common Mistakes in Java and Microservices Interviews

  • Explaining definitions without production behavior.
  • Ignoring JVM internals when troubleshooting performance.
  • Increasing database connection pools without finding the root cause.
  • Using retries without considering idempotency.
  • Using Kafka without explaining duplicate-message handling.
  • Putting business logic into an API Gateway.
  • Assuming microservices automatically provide scalability.
  • Ignoring database and network bottlenecks.
  • Designing only the happy path.
  • Ignoring observability and recovery.

Key Takeaways

  • Understand Java internals, not just syntax.
  • Know how Spring manages beans and transactions.
  • Troubleshoot performance using evidence from metrics, dumps and traces.
  • Treat database connections as a finite resource.
  • Use synchronous and asynchronous communication deliberately.
  • Make important microservice operations idempotent.
  • Design for duplicate Kafka messages.
  • Use timeouts, retries, circuit breakers and bulkheads appropriately.
  • Use AWS services based on workload and operational requirements.
  • Design high availability across Availability Zones.
  • Build observability into the system.
  • Always explain failure and recovery paths in system design interviews.

Frequently Asked Questions

Are these questions suitable for senior Java developers?

Yes. They cover Java internals, Spring Boot, databases, microservices, Kafka, AWS, observability and system design.

Should I memorize these answers?

No. Use them as a framework. In a real interview, explain the reasoning behind your design and adapt the answer to the constraints given by the interviewer.

Should I use Kafka for every microservice interaction?

No. Kafka is valuable for asynchronous and event-driven workflows, but synchronous REST or gRPC can be simpler when an immediate response is required.

What is the most important microservices interview concept?

Failure handling. A strong design explains what happens when dependencies become slow, messages are duplicated, databases fail, traffic spikes, or services restart.

What should I mention in an AWS microservices system design?

Discuss compute, networking, load balancing, Availability Zones, database availability, caching, messaging, observability, security, scaling and deployment strategy.

Conclusion

Senior Java backend interviews increasingly test the complete engineering lifecycle rather than isolated framework knowledge.

You should be able to move from Java internals to Spring Boot behavior, from database performance to microservices resilience, and from application code to AWS infrastructure and production troubleshooting.

The strongest answers are not the ones that mention the most technologies. They are the ones that explain the trade-offs, failure modes, scalability limits and recovery strategies behind each decision.

Related LogicBrace Guides

  • Microservices System Design Interview Questions
  • Microservices Failure Scenarios – Senior Interview Questions and Answers
  • Spring Boot Production Issues – Real-World Scenarios and Solutions
  • Java Concurrency & Multithreading Interview Questions
  • Java Memory Leaks – Senior Interview Questions and Answers
  • Java API Performance Optimization – Senior Interview Questions
  • Spring Boot Observability – Senior Interview Questions
  • Kubernetes Troubleshooting for Java Developers
Java Spring Boot AWS and Microservices Interview Questions – Top 35

Post a Comment

0 Comments

Close Menu