Senior Java, Spring Boot, microservices and AWS interview questions 19 questions in 6 chapters

  1. 01JVM and concurrency4 questions
  2. 02Spring internals4 questions
  3. 03Distributed data and Kafka4 questions
  4. 04Resilience and gateway
  5. 05AWS5 questions
  6. 06Sources

JVM and concurrency

  • 1.1 CPU is high but request volume is flat. How do you investigate? Hard 1 min

    First I find which threads are burning CPU. I take a few thread dumps a few seconds apart and look for the same stacks running, then record a short Java Flight Recorder profile to see hot methods and GC activity. With flat traffic the usual causes are GC thrashing as the heap fills, a busy loop or retry storm, a regex or serialization hot spot, or a background job.

    Read the full answer
  • 1.2 How is ConcurrentHashMap thread-safe, and where does it stop helping? Medium 1 min

    Reads usually don't block, and writes lock only a small part of the table, so many threads work at once. Each single call is atomic, and compute, computeIfAbsent and merge are atomic per key. But check-then-act across two calls can still race, so I use putIfAbsent or compute instead. Size and iteration are only estimates during writes, and null keys or values are not allowed.

    Read the full answer
  • 1.3 How do you build a highly concurrent app without running out of platform threads? Medium 1 min

    For blocking network and disk work I use virtual threads, which are final in Java 21. They are cheap, so one per request or task is fine, and when they block on that work they release the carrier thread. I don't pool them. Instead, I limit scarce resources like database connections with the connection pool or a semaphore, not with the thread count.

    Read the full answer
  • 1.4 How do ThreadLocal, static collections and lingering references cause memory retention? Medium 1 min

    A ThreadLocal value lives as long as its thread, and pool threads never die, so a value I forget to remove stays forever and can even leak into the next request. Static maps and caches without eviction grow without limit, and listeners that are never unregistered keep objects alive. I confirm it with a heap dump and look at what holds the biggest retained size.

    Read the full answer

Spring internals

  • 2.1 Walk through Spring bean lifecycle internals, custom init and post-processing. Medium 1 min

    Spring creates the instance, injects dependencies, and calls Aware callbacks. Then bean post-processors run their before-initialization step, followed by init callbacks in order: PostConstruct, afterPropertiesSet, then a custom init method. After that the after-initialization step runs, and that is where AOP proxies are created. On shutdown it calls PreDestroy, then destroy, then a custom destroy method.

    Read the full answer
  • 2.2 An exception was thrown but the transaction still committed. Why? Medium 1 min

    There are three usual causes. By default Spring rolls back only on unchecked exceptions and errors, so a checked exception still commits unless I set rollbackFor. Second, the exception was caught inside the method and never rethrown. Third, self-invocation: calling a transactional method from the same class skips the proxy, so no transaction is started for that call.

    Read the full answer
  • 2.3 How do you handle dynamic authorization when permissions change at runtime across services? Hard 1 min

    I keep tokens short-lived with only identity and coarse roles, and every service validates the JWT as a resource server. Fine-grained checks happen at call time, using method security that calls a permission bean. That bean reads current permissions from a central service with a short cache, so a change takes effect within the cache lifetime instead of waiting for the token to expire.

    Read the full answer
  • 2.4 Latency spikes now and then, and you suspect connection pool exhaustion. What do you do? Medium 1 min

    I check the pool metrics first: pending threads and connection acquire time. If threads wait for connections, I look for long transactions holding them, like slow queries or remote HTTP calls inside a transaction. A bigger pool is rarely the fix, because small pools usually perform better. I set a connection timeout so callers fail fast and enable leak detection to log connections held too long.

    Read the full answer

Distributed data and Kafka

  • 3.1 A business transaction spans multiple databases. How do you keep it consistent? Hard 1 min

    I avoid distributed two-phase commit across services and use a saga instead. It is a chain of local transactions, coordinated by events or by an orchestrator, and if a step fails, compensating transactions undo the earlier steps. The cost is that there is no isolation, so others can see in-between states. I handle that with explicit statuses like pending and with idempotent steps.

    Read the full answer
  • 3.2 How do you evolve Kafka message schemas with many consumer versions? Medium 1 min

    I use a schema registry with a compatibility mode. Backward, the default, means new consumers can read old data, so consumers upgrade first. Forward means old consumers can read new data, so producers upgrade first. Full means both, and the transitive variants check against all past versions. Safe changes are adding optional fields with defaults. I never rename or reuse a field.

    Read the full answer
  • 3.3 How do you publish events reliably when you update the DB and send to Kafka? Medium 1 min

    Writing to the database and Kafka as two separate steps can fail halfway. So I use the transactional outbox: the business row and an outbox row are written in one database transaction, and a relay using polling or change data capture publishes the outbox rows to Kafka. Delivery is at least once, so consumers deduplicate by event ID, and the idempotent producer stops duplicate writes on retry.

    Read the full answer
  • 3.4 Kafka consumer lag keeps rising, but CPU and DB look normal. Why? Hard 1 min

    When CPU and the database look fine, the consumer is usually waiting rather than working. Common causes are a hot partition from a skewed key, rebalances because processing takes longer than the max poll interval, slow synchronous calls to another service, or tiny fetch batches. I check lag per partition with the consumer groups tool and the consumer lag metrics before changing anything.

    Read the full answer

Resilience and gateway

  • 4.1 How do you stop an unstable shared downstream from causing cascading failures? Medium 1 min

    I put a timeout on every remote call so threads never hang. A circuit breaker fails fast once the error rate crosses a threshold, and a bulkhead caps concurrent calls so one dependency can't take every thread. I retry only idempotent calls, with capped backoff and jitter, because retries add load to a struggling service. And I add a fallback, like cached data or a degraded response.

    Read the full answer
  • 4.2 What is your API gateway strategy for auth, rate limiting, routing and tenant isolation? Hard 1 min

    The gateway, for example Spring Cloud Gateway or AWS API Gateway, validates the token, routes by path or host, and rate-limits per client or tenant. For tenant isolation I put the tenant ID in the token and give each tenant its own limit, so one noisy tenant can't starve others. Each service still checks tenant access itself, because the gateway should not be the only defense.

    Read the full answer

AWS

  • 5.1 How do you run Spring Boot highly available on AWS across multiple AZs? Medium 1 min

    I run at least two instances spread across availability zones behind an Application Load Balancer, which health-checks targets and only routes to healthy ones. The database uses RDS Multi-AZ, so a standby in another zone takes over on failure. The app stays stateless, with sessions in Redis or in tokens, so any instance can serve any request and recovery is automatic.

    Read the full answer
  • 5.2 ECS, EKS, Lambda or EC2 for Java workloads: how do you choose? Medium 1 min

    ECS on Fargate is my default for running containers without managing servers. EKS makes sense when the team needs Kubernetes features or portability and can operate it. Lambda fits spiky, short, event-driven work, and SnapStart helps with Java cold starts, but there is a fifteen-minute limit. EC2 is for special needs, like a tuned JVM, special hardware, or licensing.

    Read the full answer
  • 5.3 How do services get AWS permissions without embedded credentials? Easy 1 min

    I use IAM roles, never access keys in code or config. On ECS, a task role gives containers temporary credentials. On EKS, Pod Identity or IAM roles for service accounts map a Kubernetes service account to an IAM role. The AWS SDK picks up these credentials automatically. Each service gets its own least-privilege role, so a compromised service can only reach what it really needs.

    Read the full answer
  • 5.4 How do you design event-driven flows with SQS, SNS, EventBridge and Lambda? Medium 1 min

    SQS is a queue for work items, with a visibility timeout and a dead-letter queue for messages that keep failing. SNS is publish and subscribe, and SNS feeding several SQS queues gives each subscriber its own buffer. EventBridge is an event bus with content-based routing rules between many services. Lambda can consume SQS in batches. Delivery is at least once, so every handler must be idempotent.

    Read the full answer
  • 5.5 How do you deploy with zero downtime when the DB change is backward-incompatible? Hard 1 min

    I split the change into expand, migrate and contract. First I add the new column or table and keep the old one. Then I deploy code that writes to both, backfill the data, and switch reads to the new structure. Only in a later release do I drop the old column. During a rolling update both versions run together, so every step must work with both.

    Read the full answer

Sources