Java + Spring Boot + Microservices — Top Interview Questions (2026)
On this page
- 1. Round structure (2026)
- 2. Top 30 CORE JAVA questions
- Snippets that earn extra points
- 3. Top 25 SPRING / SPRING BOOT questions
- Snippets
- 4. Top 20 MICROSERVICES questions
- Snippets
- 5. Top 15 KAFKA & DATA-PIPELINE questions
- 6. Hibernate & PostgreSQL “make-or-break”
- 7. “Tricky” / trap questions
- 8. Using Sanjay’s experience as concrete examples
- 9. Sources
- Appendix — 10-minute pre-interview warm-up
Audience: Sanjay Naik — 3.5 yrs Java/Spring Boot @ Jio Platforms Ltd (ex-Karkinos Health). This is the round where your prod depth shows. Most non-FAANG tier-1s (Atlassian, Adobe, Microsoft, healthtech: Verily / Tempus / Oscar) weight this round heavily. Treat it as a “do not lose” round.
1. Round structure (2026)
| Slot | Duration | What it looks like |
|---|---|---|
| Language + framework Q&A | ~30 min | Rapid-fire: JVM internals, concurrency, Spring DI, AOP, @Transactional, JPA gotchas. Interviewer probes 2-3 levels deep — “why,” then “what breaks.” |
| Small service / debug | ~25-30 min | Design a slim REST service (rate limiter, URL shortener, notification fan-out, idempotent payment endpoint) or debug a broken Spring snippet (circular dep, lost transaction, N+1, race condition). |
| Wrap / questions | ~5 min | Your turn — ask about on-call, deploy cadence, observability stack. |
Where this round matters how much:
| Company tier | Weight of Java/Spring round |
|---|---|
| Amazon, Walmart, Meta | Secondary signal — DSA + LP/system-design dominate. Java round is correctness + idioms, not depth. |
| Microsoft, Atlassian, Adobe | Primary signal alongside DSA. Expect framework depth. |
| Healthtech (Verily, Tempus, Oscar, Babylon) | Primary — production Java/Spring experience is what they’re buying. Your CDC/Kafka work is gold here. |
| Indian tier-1 (Razorpay, Swiggy, Flipkart, Zerodha, PhonePe) | Primary — often the longest round. |
Default playbook per question: (1) one-line definition, (2) “how it works under the hood,” (3) trade-off / when not to use it, (4) drop a 1-line example from Jio/Karkinos. That fourth bullet is what separates 3.5-yr SDE-II candidates from 6-yr seniors.
2. Top 30 CORE JAVA questions
| # | Question | Difficulty | Topic | Asked at |
|---|---|---|---|---|
| 1 | Walk me through the JVM memory model — heap, stack, metaspace, code cache. | Med | JVM | Microsoft, Atlassian, Razorpay |
| 2 | Difference between G1, ZGC, and Shenandoah on JDK 21 — when do you pick which? | Hard | GC | Adobe, Stripe, Oscar |
| 3 | What is the String pool? new String("x") == "x".intern() — true or false? |
Easy | Strings | Almost everywhere |
| 4 | What makes a class truly immutable? List the 5 rules. | Med | OOP | Atlassian, Tempus |
| 5 | The equals / hashCode contract — what breaks if you override one and not the other? |
Easy | Collections | Universal |
| 6 | HashMap internals — load factor, treeify threshold (8), resize cost. |
Med | Collections | Universal |
| 7 | ConcurrentHashMap vs Hashtable vs Collections.synchronizedMap — internals + perf. |
Med | Concurrency | Microsoft, Flipkart |
| 8 | volatile vs synchronized vs ReentrantLock — what guarantees does each give? |
Hard | Concurrency | Atlassian, Adobe |
| 9 | What is CAS? Walk through AtomicInteger.incrementAndGet(). |
Hard | Concurrency | Microsoft, Razorpay |
| 10 | ThreadLocal — when do you use it, and what’s the leak risk in app servers? |
Med | Concurrency | Adobe, Verily |
| 11 | ExecutorService types — fixed vs cached vs scheduled vs single. When does cached blow up? |
Med | Concurrency | Walmart, PhonePe |
| 12 | ForkJoinPool — work-stealing, common pool, when to avoid it. |
Hard | Concurrency | Microsoft, Stripe |
| 13 | CompletableFuture chaining — thenApply vs thenCompose vs thenCombine. |
Med | Async | Atlassian, Swiggy |
| 14 | Streams — lazy evaluation, terminal vs intermediate, parallelStream gotchas. |
Med | Streams | Universal |
| 15 | Optional vs null — when to return Optional and when not to. |
Easy | Idioms | Universal |
| 16 | Sealed classes, records, pattern matching for switch (JDK 21) — give an example. |
Med | JDK 21 | Microsoft, Oracle, Adobe |
| 17 | Virtual threads (Project Loom, JDK 21) — what problem do they solve over platform threads? | Hard | JDK 21 | Atlassian, Stripe, Oscar |
| 18 | Reflection cost — why is it slow, and how does method-handle / LambdaMetafactory help? |
Hard | JVM | Microsoft, Adobe |
| 19 | ClassLoader hierarchy — bootstrap → platform → app. Parent-delegation model. | Med | JVM | Microsoft |
| 20 | Generics + type erasure — why can’t you do new T() or instanceof T? |
Med | Language | Atlassian |
| 21 | Checked vs unchecked exceptions — when do you wrap a checked into a runtime? | Easy | Idioms | Universal |
| 22 | try-with-resources — what does AutoCloseable add vs Closeable? Suppressed exceptions? |
Med | Idioms | Adobe |
| 23 | Java serialization — why do we prefer JSON / protobuf in 2026? | Easy | Idioms | Microsoft, Verily |
| 24 | Custom annotation — write @Retryable and how would you process it? |
Med | Meta | Razorpay |
| 25 | SOLID applied in Java — give one real violation you’ve seen and how you fixed it. | Med | Design | Atlassian |
| 26 | == vs .equals() on Integer boxed values — 127 vs 128 puzzle. |
Easy | Trap | Universal |
| 27 | What is a “memory leak” in Java if there’s GC? Give 3 ways to leak. | Med | JVM | Microsoft |
| 28 | finalize() vs Cleaner vs PhantomReference — which is preferred in 2026? |
Hard | JVM | Adobe |
| 29 | Compare synchronized block vs synchronized method — which monitor is locked? |
Easy | Concurrency | Walmart |
| 30 | Java module system (JPMS) — module-info.java. Why did it never catch on? |
Med | JDK 9+ | Microsoft, Oracle |
Snippets that earn extra points
equals / hashCode (record auto-implements both — show you know):
public record Patient(UUID id, String mrn) {
// equals & hashCode auto-generated from all components — JDK 16+
}
Virtual threads:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i ->
executor.submit(() -> blockingDbCall(i)));
} // 10k virtual threads, ~few MB heap — not 10k OS threads
CompletableFuture — thenCompose flattens:
CompletableFuture<User> u = fetchUser(id);
CompletableFuture<Order> o = u.thenCompose(this::fetchLastOrder); // not thenApply
CAS-style retry:
AtomicReference<State> ref = new AtomicReference<>(initial);
State cur, next;
do {
cur = ref.get();
next = mutate(cur);
} while (!ref.compareAndSet(cur, next));
3. Top 25 SPRING / SPRING BOOT questions
| # | Question | Difficulty | Topic | Asked at |
|---|---|---|---|---|
| 1 | Explain IoC + DI like I’m new — then go three layers deeper. | Easy | Core | Universal |
| 2 | BeanFactory vs ApplicationContext — when do you ever touch BeanFactory? |
Med | Core | Microsoft |
| 3 | Bean scopes — singleton, prototype, request, session, application, websocket. | Med | Core | Adobe, Razorpay |
| 4 | @Component vs @Bean vs @Configuration — when do you pick which? |
Easy | Core | Universal |
| 5 | @Autowired resolution order — by type, then by @Qualifier, then by name. |
Med | DI | Universal |
| 6 | How do you break a circular dependency? List 4 ways. | Med | DI | Atlassian, Microsoft |
| 7 | AOP proxy types — JDK dynamic proxy vs CGLIB — when does Spring pick which? | Hard | AOP | Atlassian, Adobe |
| 8 | @Transactional propagation levels — REQUIRED vs REQUIRES_NEW vs NESTED. |
Hard | Tx | Microsoft, Razorpay, Tempus |
| 9 | @Transactional isolation — READ_COMMITTED vs REPEATABLE_READ. |
Hard | Tx | Adobe, Stripe |
| 10 | Rollback rules — why doesn’t @Transactional roll back on checked exceptions by default? |
Med | Tx | Universal |
| 11 | Self-invocation gotcha — why does calling a @Transactional method from within the same class not start a transaction? |
Hard | Tx, Trap | Atlassian, Microsoft, Razorpay |
| 12 | Spring Data JPA N+1 — how do you detect it, how do you fix it? | Hard | JPA | Universal |
| 13 | Hibernate L1 vs L2 cache — when have you actually enabled L2? | Med | JPA | Adobe |
| 14 | Optimistic (@Version) vs pessimistic (PESSIMISTIC_WRITE) locking — when which? |
Med | JPA | Stripe, Razorpay |
| 15 | How does Spring Boot auto-configuration actually work? Walk through @EnableAutoConfiguration → AutoConfiguration.imports. |
Hard | Boot | Microsoft, Atlassian |
| 16 | Profiles — how do you load application-dev-int.yml vs application-prod.yml? |
Easy | Boot | Universal |
| 17 | Actuator — which endpoints are safe to expose in prod? | Easy | Boot | Adobe, Verily |
| 18 | Write a custom starter — what files matter? (spring.factories legacy vs AutoConfiguration.imports for 3.x). |
Hard | Boot | Microsoft |
| 19 | Spring Security filter chain — order matters. Where does JWT slot in? | Hard | Security | Atlassian, Razorpay |
| 20 | JWT vs server-side session — trade-offs (revocation, size, rotation). | Med | Security | Universal |
| 21 | OAuth2 resource server — how does Spring validate the token? | Med | Security | Adobe, Oscar |
| 22 | WebFlux vs MVC — Mono/Flux, when to actually use WebFlux? | Med | Reactive | Stripe, Atlassian |
| 23 | Bean Validation (Jakarta) — @Valid vs @Validated, group sequences. |
Easy | Validation | Universal |
| 24 | Error handling — @ControllerAdvice + @ExceptionHandler + RFC 7807 problem details. |
Med | API | Atlassian, Verily |
| 25 | Testing — @SpringBootTest (full) vs @WebMvcTest (slice) vs @DataJpaTest + Testcontainers. |
Med | Test | Microsoft, Atlassian |
Snippets
Self-invocation trap:
@Service
class OrderService {
public void outer() {
inner(); // <-- this call bypasses the proxy. @Transactional NOT applied.
}
@Transactional
public void inner() { /* writes */ }
}
Fix: inject self (@Autowired private OrderService self;) and call self.inner(), or use AopContext.currentProxy(), or split into two beans.
Fixing N+1 with fetch join:
@Query("select p from Patient p join fetch p.treatmentPlans where p.org = :org")
List<Patient> findAllWithPlans(@Param("org") UUID org);
Or @EntityGraph(attributePaths = "treatmentPlans") on the repo method.
Auto-config — peek under the hood:
java -jar app.jar --debug
# prints positive + negative auto-configuration matches
@ControllerAdvice with problem details:
@RestControllerAdvice
class ApiExceptionHandler {
@ExceptionHandler(EntityNotFoundException.class)
ProblemDetail notFound(EntityNotFoundException e) {
return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());
}
}
Testcontainers slice — what real teams ship:
@SpringBootTest
@Testcontainers
class TreatmentPlanIT {
@Container static PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:16");
@DynamicPropertySource
static void props(DynamicPropertyRegistry r) {
r.add("spring.datasource.url", pg::getJdbcUrl);
}
}
4. Top 20 MICROSERVICES questions
| # | Question | Difficulty | Topic | Asked at |
|---|---|---|---|---|
| 1 | When not to do microservices — give 3 anti-cases. | Easy | Strategy | Atlassian, Verily |
| 2 | Walk me through a real monolith → MS migration you did. | Med | Strategy | Universal |
| 3 | Sync (REST/gRPC) vs async (Kafka/queues) — decision criteria. | Med | Comms | Razorpay, Stripe |
| 4 | REST vs gRPC vs GraphQL — pick one for service-to-service, one for mobile, one for analytics. | Med | API | Microsoft, Adobe |
| 5 | API Gateway pattern — what does it solve? (auth, rate-limit, routing, fan-out). You used Kong/Konga at Jio — lead with that. | Med | Pattern | Atlassian, Razorpay |
| 6 | Service discovery — Eureka vs Consul vs k8s-native DNS. | Med | Infra | Microsoft, PhonePe |
| 7 | Client-side vs server-side load balancing — Ribbon (deprecated) vs Spring Cloud LoadBalancer. | Med | Infra | Adobe |
| 8 | Circuit breaker (Resilience4j) — CLOSED → OPEN → HALF_OPEN. Walk through state transitions + config. | Hard | Resilience | Atlassian, Razorpay, Stripe |
| 9 | Bulkhead — semaphore vs thread-pool, what does it isolate? | Med | Resilience | Adobe |
| 10 | Retry with exponential backoff + jitter — why jitter? (thundering herd). | Med | Resilience | Microsoft, Stripe |
| 11 | Distributed tracing — Sleuth → Micrometer Tracing → Zipkin/Jaeger. How is trace-id propagated? | Hard | Observability | Atlassian, Adobe |
| 12 | Centralized logging — ELK / Loki, structured (JSON) logs, correlation-id pattern. | Med | Observability | Verily, Oscar |
| 13 | Saga pattern — choreography (event-driven) vs orchestration (central coordinator). Failure & compensation. | Hard | Distributed Tx | Razorpay, Stripe, Atlassian |
| 14 | Two-phase commit — why is it avoided in MS? (blocking coordinator, partition intolerance). | Med | Distributed Tx | Microsoft |
| 15 | Outbox pattern + CDC (Debezium) — what problem does it solve? Dual-write hazard. You shipped this at Jio — own this question. | Hard | Pattern | Atlassian, Stripe, Tempus |
| 16 | Event sourcing — when is it worth it? When is it overkill? | Hard | Pattern | Adobe, Razorpay |
| 17 | CQRS — separating read/write models. Eventual consistency window. | Med | Pattern | Microsoft, Stripe |
| 18 | Idempotency keys — how do you implement a POST /payments that is safe to retry? |
Hard | Pattern | Stripe, Razorpay, PhonePe |
| 19 | Health checks — liveness vs readiness vs startup probes. Why the distinction matters in k8s. | Med | Ops | Microsoft, Atlassian |
| 20 | Blue-green vs canary vs rolling — and how do you DB-migrate without downtime? | Hard | Ops | Adobe, Stripe |
Snippets
Resilience4j circuit breaker:
@CircuitBreaker(name = "mdmAdmin", fallbackMethod = "fallbackPatient")
@Retry(name = "mdmAdmin")
@Bulkhead(name = "mdmAdmin", type = Bulkhead.Type.SEMAPHORE)
public Patient fetch(UUID id) { return mdmClient.getPatient(id); }
private Patient fallbackPatient(UUID id, Throwable t) {
return cache.getOrDefault(id, Patient.empty());
}
resilience4j.circuitbreaker.instances.mdmAdmin:
slidingWindowSize: 20
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 5
Idempotent endpoint pattern:
@PostMapping("/payments")
public ResponseEntity<Payment> create(
@RequestHeader("Idempotency-Key") String key,
@RequestBody PaymentRequest req) {
return idempotencyStore.findResponse(key)
.map(ResponseEntity::ok)
.orElseGet(() -> {
Payment p = service.charge(req);
idempotencyStore.save(key, p, Duration.ofHours(24));
return ResponseEntity.ok(p);
});
}
Outbox + Debezium (the headline diagram):
[App tx] ──INSERT──► [orders + outbox] (same Postgres tx)
│
[Debezium WAL reader]
│
▼
[Kafka topic]
│
▼
[consumer services]
The dual-write hazard (write DB + publish Kafka, one of them fails) is eliminated because both writes are in one Postgres transaction, and Debezium replays the WAL.
5. Top 15 KAFKA & DATA-PIPELINE questions
| # | Question | Difficulty | Topic | Asked at |
|---|---|---|---|---|
| 1 | Kafka vs RabbitMQ vs SQS — log vs queue semantics, replay, ordering. | Med | Brokers | Atlassian, Stripe |
| 2 | Partitions and ordering — what guarantees ordering within a partition? | Med | Kafka | Razorpay, PhonePe |
| 3 | Consumer groups — rebalance triggers, sticky assignor, cooperative rebalance. | Hard | Kafka | Atlassian, Adobe |
| 4 | Exactly-once semantics — idempotent producer + transactional producer + isolation.level=read_committed. |
Hard | Kafka | Stripe, Microsoft |
| 5 | Idempotent producer — what does enable.idempotence=true actually do? (PID + seq). |
Hard | Kafka | Stripe |
| 6 | Transactional producer — initTransactions, beginTransaction, send, commitTransaction. |
Hard | Kafka | Atlassian |
| 7 | Log compaction vs retention — when to use which? Compaction’s “tombstone” message. | Med | Kafka | Adobe, Razorpay |
| 8 | Kafka Streams vs KSQL vs Flink — when to pick which? | Med | Streaming | Stripe |
| 9 | Debezium CDC architecture — connector → WAL → topic per table → SMTs. Your sub-3-sec lag story goes here. | Hard | CDC | Atlassian, Tempus, Stripe |
| 10 | Schema Registry — Avro / Protobuf, BACKWARD vs FORWARD vs FULL compatibility. | Med | Schema | Adobe, Verily |
| 11 | Replay strategy — how do you replay last 24 hours into a new consumer without double-processing? | Hard | Ops | Stripe, Atlassian |
| 12 | DLQ pattern — when does a message go to DLQ vs retry topic? Tiered retries. | Med | Pattern | Razorpay |
| 13 | Backpressure — how does a slow consumer affect producers? | Med | Kafka | Microsoft |
| 14 | acks=0 vs acks=1 vs acks=all — durability vs latency. |
Easy | Kafka | Universal |
| 15 | Why is consumer offset committed to a Kafka topic (__consumer_offsets) and not Zookeeper? |
Easy | Kafka | Adobe |
Kafka producer config that earns nods:
enable.idempotence=true
acks=all
max.in.flight.requests.per.connection=5
retries=Integer.MAX_VALUE
compression.type=zstd
linger.ms=10
batch.size=65536
6. Hibernate & PostgreSQL “make-or-break”
| # | Question | Why it matters |
|---|---|---|
| 1 | What is the N+1 query problem? Show me the SQL it produces. | Most common JPA bug — interviewers love it. |
| 2 | LazyInitializationException — root cause and 3 fixes. |
Open-session-in-view debate. |
| 3 | Fetch join (join fetch) vs @EntityGraph — when does which work? |
EntityGraph is preferred for repository methods. |
| 4 | hibernate.jdbc.batch_size + order_inserts + order_updates — why all three? |
Real perf knob in prod. |
| 5 | L1 (per-session) vs L2 (per-SessionFactory) cache — when have you enabled L2 in prod? |
Most people haven’t — be honest. |
| 6 | save vs persist vs merge vs saveAndFlush — semantic differences. |
Trap question. |
| 7 | Dirty checking — how does Hibernate know an entity changed? (snapshot at load). | Trips juniors. |
| 8 | EXPLAIN ANALYZE walkthrough — seq scan vs index scan vs bitmap heap scan. |
Postgres depth. |
| 9 | Index types — B-tree, Hash, GIN (full-text, jsonb), BRIN (time-series). | Healthtech & analytics. |
| 10 | Partitioning — RANGE (by date) vs LIST vs HASH. When does the planner do partition pruning? | Tempus, Verily — large datasets. |
| 11 | VACUUM vs autovacuum vs VACUUM FULL — bloat, freeze, wraparound. | Stripe, Razorpay love this. |
| 12 | MVCC — how does Postgres handle two concurrent updates to the same row? | Atlassian, Microsoft. |
| 13 | Isolation levels — READ COMMITTED (default) vs REPEATABLE READ vs SERIALIZABLE. Phantom reads in Postgres REPEATABLE READ? Trick: Postgres REPEATABLE READ already prevents phantoms via snapshot isolation. |
Trick question — most candidates miss it. |
| 14 | HikariCP — what’s maximumPoolSize set to, and how do you size it? (connections = ((core_count * 2) + effective_spindle_count)). |
Stripe, PhonePe. |
| 15 | Read replicas — how do you route reads in Spring? (AbstractRoutingDataSource or @Transactional(readOnly = true) + transparent routing). |
Adobe, Razorpay. |
Spot-the-N+1:
List<Patient> patients = patientRepo.findAll();
for (Patient p : patients) {
p.getTreatmentPlans().size(); // fires 1 query per patient — N+1
}
Fix with @EntityGraph(attributePaths = "treatmentPlans") on findAll.
7. “Tricky” / trap questions
These are the gotcha ones — interviewers ask them because the right answer requires knowing Spring’s proxy internals. Burn these in.
| # | Question | Answer in one line |
|---|---|---|
| 1 | Why does autowiring a prototype bean into a singleton break? | Singleton is constructed once → it holds the same prototype instance forever. Fix: ObjectProvider<T>, Provider<T> (JSR-330), or @Scope(proxyMode = TARGET_CLASS). |
| 2 | What happens when equals is overridden but hashCode is not? |
HashMap/HashSet lose the object — equals-equal objects land in different buckets. |
| 3 | Why does @Async on a @Transactional method “lose” the transaction? |
@Async runs on a new thread → new thread has no ThreadLocal TransactionSynchronizationManager context → no transaction propagates. |
| 4 | Why does @Transactional on a private method do nothing? |
Spring uses proxies (JDK dynamic or CGLIB). Proxies can only intercept public (CGLIB also intercepts protected/package). Private methods bypass the proxy. |
| 5 | Why does @Transactional not work on a method called from inside the same bean (self-invocation)? |
Same reason — call is on this, not on the proxy. |
| 6 | HashMap in concurrent code — what’s the worst that happens? |
Pre-JDK 8: infinite loop on resize. JDK 8+: still data corruption / lost writes. Use ConcurrentHashMap. |
| 7 | Integer cache — why is Integer.valueOf(127) == Integer.valueOf(127) true but Integer.valueOf(128) == Integer.valueOf(128) false? |
Integer cache: -128 to 127 are cached as the same instance. |
| 8 | String s = "a" + "b" vs String s = a + b (where a, b are vars) — what’s different at bytecode? |
First is a compile-time constant in the String pool. Second is a StringBuilder.append at runtime. |
| 9 | Why is overriding finalize() an anti-pattern in 2026? |
Unpredictable timing, can resurrect objects, slow GC. Use Cleaner (JDK 9+) or try-with-resources. |
| 10 | Why can’t you throw new T() in a generic method? |
Type erasure — T is Object at runtime, JVM can’t verify it’s a Throwable. |
| 11 | Why does Arrays.asList(1, 2, 3).add(4) throw UnsupportedOperationException? |
Returns a fixed-size wrapper over the array, not an ArrayList. |
| 12 | What happens if a @Transactional method calls a REQUIRES_NEW method on the same bean? |
Same self-invocation trap — REQUIRES_NEW is ignored, you’re still in the outer tx. |
| 13 | Will a circuit breaker OPEN ever close on its own? |
Yes — after waitDurationInOpenState, it goes HALF_OPEN, lets N probe calls through. If they succeed, CLOSED. |
| 14 | @PostConstruct vs InitializingBean.afterPropertiesSet() vs @Bean(initMethod=...) — order? |
@PostConstruct → afterPropertiesSet → initMethod. |
| 15 | Two @Configuration classes both define @Bean DataSource — what happens? |
NoUniqueBeanDefinitionException unless one is @Primary or you use @Qualifier. |
8. Using Sanjay’s experience as concrete examples
Drop these as 1-2 sentence “I’ve shipped this” lines. They turn a generic answer into a senior answer.
| Topic | Sanjay’s drop-in line |
|---|---|
| CDC / Outbox pattern | “At Jio, we replaced a 30-min nightly batch with a Debezium → Kafka → Postgres pipeline. Sub-3-second end-to-end lag from source DB write to downstream consumer. The outbox was in the same Postgres tx as the business write, so we eliminated dual-write hazards entirely.” |
| API Gateway | “We fronted ~12 microservices with Kong + Konga at Jio. JWT validation, per-consumer rate limits, and request transformation lived in Kong — services stayed thin.” |
| Circuit breaker | “We wrapped every cross-service call in Resilience4j. Failure threshold 50% over a 20-call sliding window, 10s open state. When MDM Admin started returning 5xx during a deploy, the Treatment Plan service degraded gracefully instead of cascading.” |
| N+1 / EntityGraph | “Our Treatment Plan list endpoint went from ~800 ms (N+1) to ~80 ms after switching to @EntityGraph(attributePaths = …) on the repo method.” |
| Kafka exactly-once | “For the Treatment Plan event stream we used enable.idempotence=true + transactional producer + read_committed consumer. Replays were safe because the consumer was already idempotent on event_id.” |
| Saga / orchestration | “Patient onboarding spanned 4 services (MDM, Treatment Plan, Notification, Billing). We did orchestration via a state machine in the MDM Admin service — easier to debug than choreography for a non-trivial flow.” |
| Distributed tracing | “We instrumented every service with Micrometer Tracing → Jaeger. The trace-id was propagated via the gateway and stamped into structured JSON logs, so an SRE could pivot from a Kibana log line to the full request trace in one click.” |
| Spring Profiles | “Our config was Spring Cloud Config + profile-per-env (dev-int, qa, prod). Treatment Plan ran on 8901/treatment-plan; MDM Admin on 8085/mdm-admin. Liquibase migrations were profile-gated.” |
| Hibernate L1 / dirty checking | “We hit a dirty-checking regression — an entity was being modified inside a read-only tx by mistake, causing autoflush. Switching to a DTO projection killed the surprise updates.” |
| PostgreSQL MVCC + isolation | “We saw a serialization_failure under load on a SERIALIZABLE tx. Dropped to READ COMMITTED with explicit SELECT … FOR UPDATE on the contended row — throughput went up 3x.” |
| Idempotency keys | “Every external-facing write at Karkinos required an Idempotency-Key header. We stored (key → response) in Redis with a 24h TTL. Retries returned the cached response, no DB hit.” |
| HikariCP | “We sized HikariCP to (cores * 2) + 1 for the CPU-bound services and tracked hikari.connections.pending in Prometheus. Caught a leak via the metric before it hit prod.” |
| Spring Security + JWT | “JWT validated at the gateway, with a downstream JwtAuthenticationConverter in each MS so @PreAuthorize worked against extracted scopes.” |
| Liquibase | “Every schema change was a Liquibase changeset, applied at boot. Rollback scripts were mandatory in PR review.” |
| Docker / k8s | “Both MDM Admin (8085) and Treatment Plan (8901) ran as separate compose services in dev-int, then as separate k8s Deployments with readiness probes hitting /actuator/health/readiness.” |
| Virtual threads | “Haven’t shipped Loom to prod yet, but I prototyped it for an I/O-bound enrichment service — Executors.newVirtualThreadPerTaskExecutor() let us drop from a 200-thread pool to virtual threads and the heap stayed flat.” |
Tip: Don’t volunteer every story. Let the interviewer ask “have you done this?” — then drop the 1-liner. Brevity reads as senior.
9. Sources
- InterviewBit — Spring Boot Interview Questions
- Devinterview-io — Microservices Interview Questions
- WeCreateProblems — Spring Boot Interview Questions
- Baeldung — Java, Spring, Kafka, Hibernate deep-dives
- Spring Framework Reference Docs
- Spring Boot 3.x Reference
- Resilience4j Docs
- Debezium Documentation
- Confluent — Kafka Exactly-Once Semantics
- PostgreSQL — MVCC & Isolation Levels
- JEP 444 — Virtual Threads (JDK 21)
Appendix — 10-minute pre-interview warm-up
Run this checklist 30 minutes before the round:
- Open IntelliJ / a Spring Boot 3.x scratch project. Don’t go in cold.
- Re-read the trap section (section 7) — those are the cheapest points to lose.
- Re-read your own
CLAUDE.mdfor the Treatment Plan + MDM Admin port + JVM args. The “what does your prod config look like” question is free if you can rattle it off. - Have a 60-second version of the Debezium CDC story rehearsed. Specifics: source DB, target, lag, what it replaced.
- Have a 60-second version of one failure story — a prod incident, what you debugged, what you fixed. Senior-ness is calibrated on failure stories more than success ones.