🍃

Spring Boot & Microservices

Spring Boot core, dependency injection, REST APIs, JPA/Hibernate, transactions, Spring Security, and the microservices patterns — service discovery, API gateway, resilience, messaging — that hold a distributed system together.

REST Fundamentals

Q

What is a REST API, and what are its core architectural constraints?

beginner

REST (Representational State Transfer) is an architectural style for designing networked APIs around resources identified by URIs. Its core constraints are: client-server separation, statelessness (each request contains everything needed to process it), cacheability, a uniform interface (standard HTTP verbs acting on resources), a layered system, and optionally code-on-demand — together these make REST APIs scalable, simple to reason about, and independently evolvable on client and server sides.

Q

What is a resource, a sub-resource, and a URI in REST API design?

beginner

A resource is any entity a client can interact with — a user, an order, a product — identified by a unique URI like /users/42. A sub-resource represents something that only exists in relation to a parent resource, expressed as a nested path, e.g. /users/42/orders for the orders belonging to user 42. The URI itself is the resource's address; well-designed REST APIs use nouns in URIs (resources) and HTTP verbs (actions) rather than encoding actions into the URI path.

Q

What are the main HTTP methods used in REST APIs, and what does each represent?

beginner

GET retrieves a resource without side effects (safe and idempotent); POST creates a new resource or triggers a non-idempotent action; PUT replaces an entire resource with the given representation (idempotent — calling it twice with the same body has the same effect as once); DELETE removes a resource (idempotent). Correctly matching intent to verb is what makes an API behave predictably for clients, caches, and retry logic.

Q

What is the difference between HTTP and HTTPS?

beginner

HTTP transmits data in plain text over the network, meaning anyone intercepting the traffic (a man-in-the-middle) can read or tamper with it. HTTPS wraps HTTP inside TLS, encrypting the data in transit and verifying the server's identity via a certificate — it's the mandatory baseline for any API handling credentials, tokens, or personal data.

Q

What is the difference between GET and POST in a REST API?

beginner

GET requests data and should never change server state — it's safe, idempotent, cacheable, and its parameters typically appear in the URL query string, which limits length and exposes them in logs/browser history. POST sends data in the request body to create a resource or trigger an action, is not idempotent (calling it twice may create two resources), and is not cached by default.

Q

What is the difference between POST and PUT in a REST API?

beginner

POST is used to create a new resource, and the server typically decides the new resource's identifier — calling it repeatedly with the same body creates multiple resources (not idempotent). PUT is used to replace an entire existing resource at a known URI, and calling it repeatedly with the same body produces the same end state (idempotent) — if the resource doesn't exist yet, some APIs treat PUT as an upsert.

Q

What is the difference between PUT and PATCH in a REST API?

beginner

PUT replaces the ENTIRE resource with the representation you send — any field you omit is typically treated as cleared/reset. PATCH applies a PARTIAL update, sending only the fields that actually changed, leaving everything else untouched — PATCH is the right choice when a client only wants to modify one or two fields without resending the whole object.

Q

What is the difference between REST and SOAP?

beginner

REST is an architectural style built on standard HTTP, using lightweight JSON/XML payloads and standard HTTP verbs/status codes — simple, cacheable, and the default choice for most modern web/mobile APIs. SOAP is a strict, XML-based protocol with a formal contract (WSDL), built-in security/transaction standards (WS-Security, WS-AtomicTransaction), and works over multiple transports beyond HTTP — it's heavier but still used in enterprise/financial systems that need those formal guarantees.

Spring Boot Core

Q

What is Spring Boot and how is it different from the Spring Framework?

beginner

Tests whether you know Spring Boot is an opinionated, auto-configured layer on top of Spring, not a replacement for it.

Q

What does @SpringBootApplication do? What 3 annotations does it combine?

beginner

Tests whether you know this one annotation is really @Configuration + @EnableAutoConfiguration + @ComponentScan bundled together.

Q

What is Spring Actuator? Name 5 important endpoints it exposes.

intermediate

Tests whether you know how to expose health, metrics, and diagnostic data for a production Spring Boot application.

Q

How does Spring Boot handle multiple environments (dev, QA, prod) using profiles?

intermediate

Tests whether you know how to structure environment-specific configuration cleanly using @Profile and profile-specific property files.

Q

Why can @Async fail to execute asynchronously, and how do you fix it?

intermediate

@Async relies on an AOP proxy — calling the method from within the same class (self-invocation) bypasses the proxy and runs synchronously on the calling thread. Fix by calling it through an injected reference to the bean (from a different class) instead of `this`.

Q

Your Spring Boot application takes 60+ seconds to start — how do you optimize it?

advanced

Profile startup with `--debug` and Spring Boot's built-in startup tracking (ApplicationStartup/Micrometer), then look for slow auto-configurations, excessive component scanning scope, eager bean initialization that could be @Lazy, and heavy @PostConstruct work — often it's a small number of specific beans, not Spring itself, causing most of the delay.

Q

How do you process millions of records efficiently using Spring Batch?

advanced

Spring Batch structures work into Jobs made of Steps, each with a chunk-oriented ItemReader → ItemProcessor → ItemWriter pipeline that commits in configurable chunk sizes (not one giant transaction). Use partitioning or multi-threaded steps to parallelize across large datasets, and a JobRepository to track progress and support safe restarts after failure.

Q

How do you implement multi-tenancy in Spring Boot?

advanced

Three common strategies: a shared schema with a tenant_id column filtered on every query (cheapest, needs discipline or a Hibernate filter to enforce), a schema-per-tenant (moderate isolation), or a database-per-tenant (strongest isolation, most operational overhead) — resolved per-request via a tenant-identifying header/subdomain and a routing DataSource or Hibernate multi-tenancy config.

Q

How would you design an audit logging system for every database change?

advanced

For simple field-level tracking, Spring Data's @CreatedDate/@LastModifiedDate/@CreatedBy/@LastModifiedBy with @EnableJpaAuditing cover who/when. For a full change history, use Hibernate Envers (automatic revision tables) or write changes to a separate audit_log table inside the same transaction as the business write, capturing old/new values and the acting user.

Spring Boot Internals

Q

How does Spring Boot auto-configuration work internally (@EnableAutoConfiguration)?

advanced

@EnableAutoConfiguration (bundled inside @SpringBootApplication) triggers Spring to read META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports — a list of candidate auto-configuration classes each starter ships. Every candidate is guarded by @Conditional annotations (@ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty), so only the configurations whose conditions actually match your classpath and existing beans get activated — which is also exactly why defining your own bean of the same type silently overrides the auto-configured one.

Q

What's the difference between BeanFactoryPostProcessor and BeanPostProcessor?

intermediate

A BeanFactoryPostProcessor runs BEFORE any bean is instantiated, operating on bean DEFINITIONS (metadata) — PropertySourcesPlaceholderConfigurer, which resolves ${...} placeholders, is a classic example. A BeanPostProcessor runs AFTER each bean is instantiated, wrapping its initialization via postProcessBeforeInitialization()/postProcessAfterInitialization() — this is exactly how AOP proxies for @Transactional and @Cacheable get created, by replacing the raw bean instance with a proxy during this phase.

Q

When should you use @Lazy, and what are its trade-offs?

intermediate

Use @Lazy when a bean is expensive to create but rarely actually used, deferring its cost until the first real request for it, or to break specific circular-dependency deadlocks where eager initialization would otherwise fail. The trade-off: lazy beans move a configuration failure from a predictable, fail-fast point at application startup to an unpredictable point during request handling — most teams reserve @Lazy for genuinely optional or costly beans rather than applying it broadly, since it trades startup safety for startup speed.

Q

What happens internally during the Spring Boot application startup lifecycle?

advanced

SpringApplication.run() first prepares the Environment (property sources, active profiles), creates the appropriate ApplicationContext type, and invokes any registered ApplicationContextInitializers. It then calls context.refresh(), which loads all bean definitions, runs BeanFactoryPostProcessors, registers BeanPostProcessors, instantiates every singleton bean (triggering auto-configuration's conditional evaluation along the way), and publishes a ContextRefreshedEvent — finally, any ApplicationRunner/CommandLineRunner beans execute before the application is considered fully started.

Q

What's the difference between ApplicationContextInitializer, ApplicationRunner, and CommandLineRunner?

intermediate

ApplicationContextInitializer runs very early, BEFORE the context is refreshed — used to programmatically customize the context (e.g. adding property sources) before any bean exists yet. ApplicationRunner and CommandLineRunner both run AFTER the context is fully started with every bean ready, differing only in how they receive command-line arguments: CommandLineRunner gets a raw String[] array, while ApplicationRunner gets a parsed ApplicationArguments object with named-option support (e.g. --name=value).

Q

How does Spring Boot Actuator expose metrics, and how would you secure them in production?

intermediate

Actuator's /actuator/metrics endpoint is backed by Micrometer, a vendor-neutral metrics facade that Actuator auto-configures to collect JVM, HTTP request, and custom application metrics, which can then be exported to Prometheus, Datadog, or similar monitoring backends. In production, sensitive endpoints (env, heapdump, shutdown) should never be left publicly exposed — restrict what's exposed via management.endpoints.web.exposure.include, move actuator to a separate management port, and secure it with Spring Security rather than relying on obscurity.

HikariCP & Connection Pool

Dependency Injection & Core

Spring MVC vs WebFlux vs Virtual Threads

Spring Fundamentals

Q

What is the Spring IoC (Inversion of Control) Container?

beginner

The IoC container is the core of the Spring Framework — it's responsible for instantiating, configuring, and managing the complete lifecycle of application objects (beans), based on configuration metadata (annotations or XML). Instead of your code creating its own dependencies with `new`, you declare what a class needs and the container 'inverts control' by injecting them for you, which is the foundation Spring's dependency injection is built on.

Q

What is a Spring Bean?

beginner

A Spring Bean is simply an object that's instantiated, assembled, and managed by the Spring IoC container, rather than being created directly by application code with `new`. Any class annotated with @Component (or its specializations @Service/@Repository/@Controller) or declared via an @Bean method in a @Configuration class becomes a bean, making it eligible for dependency injection anywhere else in the application.

Q

What is the default scope of a Spring Bean, and what other scopes are available?

beginner

The default scope is singleton — the container creates exactly one shared instance of the bean for the entire application context, and every injection point receives that same instance. Other scopes include prototype (a new instance every time the bean is requested), and web-specific scopes like request and session that tie a bean's lifetime to an HTTP request or session.

Q

What is the difference between BeanFactory and ApplicationContext in Spring?

beginner

BeanFactory is the most basic container interface, providing lazy initialization (beans are created only when first requested) and the fundamental DI capability. ApplicationContext extends BeanFactory and adds enterprise features on top — eager singleton initialization at startup, event publishing, internationalization support, and easier integration with Spring AOP — which is why virtually every real Spring/Spring Boot application uses ApplicationContext rather than BeanFactory directly.

Spring Boot Fundamentals

Q

What are Spring Boot Starters, and why do they exist?

beginner

Starters are curated dependency bundles — e.g. spring-boot-starter-web pulls in Spring MVC, an embedded Tomcat, and Jackson for JSON, all with versions that are known to work together. They exist to eliminate the manual, error-prone work of figuring out and aligning individual library versions for a common use case, letting you add one dependency instead of a dozen.

Q

What is spring-boot-starter-parent, and what does it provide?

beginner

It's a special parent POM that a Spring Boot Maven project inherits from, which centrally manages dependency versions (via a Bill of Materials), sensible default plugin configurations (like the Spring Boot Maven plugin for building executable JARs), and default Java/encoding settings — so individual dependencies in your own pom.xml don't need explicit version numbers, avoiding version-mismatch issues.

Q

What embedded servers does Spring Boot support, and how do you change the default?

beginner

Spring Boot ships with embedded Tomcat by default (via spring-boot-starter-web), and also supports Jetty and Undertow. To switch, exclude the default Tomcat starter dependency and add the starter for the server you want instead (e.g. spring-boot-starter-undertow) — the embedded-server model means the application itself is a runnable JAR with the server built in, rather than a WAR deployed into an externally-installed server.

Q

What is Spring Boot DevTools, and what does it do during development?

beginner

DevTools is a development-time-only dependency that speeds up the local feedback loop: it automatically restarts the application when it detects a classpath change (faster than a full manual restart, since it uses two classloaders and only reloads your own classes), enables LiveReload for the browser, and applies development-friendly default property overrides. It's automatically excluded from a production build/JAR, so it never adds overhead in a deployed environment.

Kafka: Producer, Consumer & Idempotency

Q

How do you achieve Kafka producer idempotency and exactly-once processing?

advanced

Tests whether you know enable.idempotence alone only prevents duplicate writes at the broker, not end-to-end exactly-once.

Q

A database update succeeds, but publishing the corresponding Kafka event fails. How do you maintain consistency?

advanced

Tests whether you know this is the classic dual-write problem, and that the Outbox Pattern is the real fix, not a retry loop.

Q

What happens if a Kafka consumer processes a message successfully but crashes before committing the offset?

advanced

Tests whether you know the message will be redelivered, which is exactly why consumer-side idempotency is non-negotiable.

Q

Kafka consumer lag suddenly spikes in production. What do you check first?

advanced

Tests whether you know to check for GC pauses freezing poll(), slow downstream calls in the consumer, or an actual rebalance loop.

Q

One Kafka partition is overloaded while others sit idle. What could cause this?

advanced

Tests whether you know a poorly chosen partition key (like a low-cardinality field) creates a hot partition.

Q

Why do Kafka consumer groups keep rebalancing every few minutes, and how do you minimize the disruption?

advanced

Tests whether you know session timeouts, slow processing exceeding max.poll.interval.ms, and static membership all factor in.

Q

You have 10 consumers in a group but only 3 Kafka partitions. How many consumers actually process messages?

intermediate

Tests whether you know partition count is a hard ceiling on consumer parallelism within a group — the extra 7 sit idle.

Q

A Kafka message reaches the Dead Letter Topic. How do you safely reprocess it after fixing the underlying issue?

advanced

Tests whether you know to replay from the DLT deliberately rather than just deleting and hoping the source retries.

Q

What is enable.auto.commit=false and why do senior engineers prefer it over the default?

advanced

Tests whether you know manual commit lets you commit only after successful processing, avoiding silent message loss.

Q

How do you implement a transactional Kafka producer in Spring Boot for exactly-once semantics?

advanced

Tests whether you know transactional.id and KafkaTransactionManager, and what read_committed means for downstream consumers.

Q

What is the significance of max.poll.records and max.poll.interval.ms in preventing consumer rebalancing?

advanced

Tests whether you know a slow batch that exceeds max.poll.interval.ms triggers a rebalance even though the consumer is still alive.

Q

A payment service's Kafka consumer lag jumps from 500 to 2 million messages in 30 minutes with unchanged producer throughput, and your SLA requires 5-second processing. How do you diagnose and fix it?

advanced

Tests whether you can reason through a real high-stakes production incident, not just recite the theory around lag.

Q

Design exactly-once semantics for a fund-transfer payment microservice — no double debit, no lost credit.

expert

Tests whether you can combine idempotent producers, Kafka transactions, and a transactional outbox into one coherent design.

Spring MVC Annotations

Q

What does the @RequestMapping annotation do in Spring MVC?

beginner

@RequestMapping maps an HTTP request to a specific handler method (or an entire controller class), matching on URL path, HTTP method, headers, or parameters. It's the general-purpose mapping annotation that @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping are all built as method-specific shorthand for — e.g. @GetMapping("/users") is equivalent to @RequestMapping(value = "/users", method = RequestMethod.GET).

Q

What does @GetMapping do, and when would you use plain @RequestMapping instead?

beginner

@GetMapping is shorthand for @RequestMapping(method = RequestMethod.GET) — it maps HTTP GET requests to a handler method and is the standard choice for any read/retrieval endpoint. You'd fall back to plain @RequestMapping when a single handler needs to respond to multiple HTTP methods at once, or when matching on more complex conditions (headers, content negotiation) that the shorthand annotations don't directly expose.

Q

What do @PostMapping and @RequestBody do together in a Spring Boot REST controller?

beginner

@PostMapping maps an HTTP POST request to a handler method — typically used for creating a new resource. @RequestBody tells Spring to deserialize the incoming HTTP request body (usually JSON) directly into a Java object parameter, using Jackson under the hood — together they let a method like createUser(@RequestBody UserDto dto) receive a JSON payload as a fully-populated object with zero manual parsing code.

Q

What does @PutMapping do, and how does it fit REST semantics?

beginner

@PutMapping maps HTTP PUT requests to a handler method, matching REST's convention that PUT should fully replace an existing resource at a known URI in an idempotent way. A typical handler signature is updateUser(@PathVariable Long id, @RequestBody UserDto dto), where the ID identifies which resource to replace and the body supplies its complete new state.

Q

What does @DeleteMapping do in Spring MVC?

beginner

@DeleteMapping maps HTTP DELETE requests to a handler method, used for removing a resource identified by a path variable — e.g. deleteUser(@PathVariable Long id). DELETE is expected to be idempotent: calling it multiple times on the same (now already-deleted) resource should still result in the resource being absent, typically returning a 204 No Content on success or a 404 if it was already gone.

Q

What is the difference between @RequestParam and @PathVariable in Spring MVC?

beginner

@PathVariable extracts a value embedded directly in the URI path itself, e.g. /users/{id} binds {id} to a method parameter — used for identifying a specific resource. @RequestParam extracts a value from the query string, e.g. /users?status=active binds status to a parameter — used for optional filters, pagination, or sorting options that aren't part of the resource's identity.

Hibernate Internals

Spring Core Annotations

Q

What does the @Qualifier annotation do in Spring, and when do you need it?

beginner

@Qualifier resolves ambiguity when multiple beans of the same type exist and Spring can't determine which one to autowire by type alone — you pass @Qualifier("beanName") alongside @Autowired to specify exactly which implementation to inject. Without it, Spring throws a NoUniqueBeanDefinitionException the moment more than one matching bean is found for a given injection point.

Q

What does the @Primary annotation do, and how does it differ from @Qualifier?

beginner

@Primary marks one bean as the default choice among multiple candidates of the same type — when Spring needs to autowire and finds several matches, it picks the @Primary one automatically without any extra hint at the injection point. @Qualifier, by contrast, is specified at the injection point itself and lets you pick a DIFFERENT (non-primary) bean explicitly when needed — @Primary sets a sensible default, @Qualifier overrides it case-by-case.

Q

What does the @Lazy annotation do in Spring?

beginner

@Lazy defers a bean's initialization until it's actually first requested/injected, rather than at application startup (Spring's default for singleton beans is eager initialization). It's useful for reducing startup time when a bean is expensive to create but rarely used, or for breaking certain circular-dependency situations where eager initialization would otherwise fail.

Q

What does the @Scope annotation do, and what scopes can you specify with it?

beginner

@Scope overrides a bean's default lifecycle/visibility — common values are "singleton" (one shared instance, the default), "prototype" (a new instance per request for the bean), and, in a web application, "request" or "session" (tied to the HTTP request or session lifetime). It's applied directly on a @Component class or an @Bean method when the default singleton behavior isn't what you want.

Q

What does the @Value annotation do in Spring?

beginner

@Value injects a single configuration value — from application.properties/yml, an environment variable, or a system property — directly into a field or constructor parameter, e.g. @Value("${server.port}") private int port. It also supports SpEL (Spring Expression Language) for computed values and can specify a default with @Value("${some.key:defaultValue}") if the property is missing.

Q

What do @PropertySource and @PropertySources do in Spring?

beginner

@PropertySource explicitly registers an additional .properties file (beyond the default application.properties) into Spring's Environment, so its keys become available for @Value injection or @ConfigurationProperties binding — e.g. @PropertySource("classpath:custom.properties"). @PropertySources is the container annotation that lets you specify multiple @PropertySource entries together on a single @Configuration class.

Q

What does @ConfigurationProperties do, and how is it different from @Value?

intermediate

@ConfigurationProperties binds an entire group of related, hierarchical configuration properties (e.g. everything under app.mail.*) into a single strongly-typed POJO with matching fields, all at once, with built-in validation support. @Value injects one individual property at a time into one field — @ConfigurationProperties is the better choice once you have more than a couple of related settings, since it avoids a long list of scattered @Value fields.

Redis & Caching

Q

How do you prevent a cache stampede when using Spring's @Cacheable annotation?

advanced

Tests whether you know @Cacheable alone doesn't coalesce concurrent misses, and what actually does (locking, soft TTL).

Q

Redis is down. Should your application also go down? How would you design the fallback?

advanced

Tests whether you know caching should degrade gracefully to the database, not become a hard dependency that takes down the app.

Q

How would you solve the cache invalidation problem when multiple service instances are running?

advanced

Tests whether you know local in-memory caches need a coordination mechanism (pub/sub or shared cache) to stay consistent across instances.

Q

What are the different Redis eviction policies and when would you choose each?

advanced

Tests whether you know the tradeoffs between allkeys-lru, volatile-lru, allkeys-lfu, and the noeviction default.

Q

How do you implement distributed locking using Redis — SETNX vs Redisson?

advanced

Tests whether you know the difference between a raw atomic SETNX-with-TTL lock and a library that handles renewal and edge cases for you.

Q

What is the problem with a distributed lock expiring before the job holding it completes?

advanced

Tests whether you know a second process can acquire the 'freed' lock while the first is still working, causing double-processing.

Q

What is a Redis pipeline and how does it improve performance?

advanced

Tests whether you know batching commands avoids paying a network round trip for every single Redis call.

Q

What is the difference between Redis Cluster and Redis Sentinel?

advanced

Tests whether you know one shards data across nodes for scale while the other provides high availability via failover for a single dataset.

Q

How do you handle cache warming after a deployment or Redis restart to avoid a cold-cache traffic spike hitting the database?

advanced

Tests whether you know to proactively pre-populate hot keys instead of letting production traffic discover the cold cache.

Q

What is cache penetration — requests for keys that don't exist, each falling through to the database? How do you fix it with a Bloom Filter?

advanced

Tests whether you know a Bloom Filter can cheaply reject requests for keys that provably don't exist, before they ever reach the DB.

Q

After enabling caching, your database load drops as expected, but memory usage keeps climbing. What might be wrong?

advanced

Tests whether you know unbounded cache growth (no TTL, no max size) silently turns a cache into a memory leak.

Transactions & Concurrency

Spring Ecosystem

Q

What is the difference between Spring Boot and Spring Cloud?

beginner

Spring Boot is about building a SINGLE, standalone, production-ready application quickly — auto-configuration, embedded servers, and starters that remove boilerplate for one service. Spring Cloud is built ON TOP of Spring Boot and addresses concerns that only exist once you have MULTIPLE services talking to each other — service discovery (Eureka), API gateways, distributed config, circuit breakers, and client-side load balancing.

Q

What is the difference between Spring Boot and Microservices?

beginner

Spring Boot is a FRAMEWORK for building applications quickly with minimal configuration — it works equally well for a monolith or a single microservice. Microservices is an ARCHITECTURAL STYLE for structuring an entire system as a collection of small, independently deployable services — Spring Boot is simply a popular, convenient tool for implementing each individual microservice in that architecture, not a requirement of the architecture itself.

Q

What is the difference between synchronous and asynchronous communication in microservices?

intermediate

In synchronous communication (typically REST/gRPC over HTTP), the calling service blocks and waits for an immediate response, creating tight temporal coupling — if the downstream service is slow or down, the caller is directly affected. In asynchronous communication (typically via a message broker like Kafka or RabbitMQ), the caller publishes an event and moves on without waiting, decoupling the services in time — the consumer processes the message whenever it's ready, which improves resilience at the cost of not getting an immediate result.

Spring Security

Q

How does Spring Security's filter chain work?

intermediate

Tests whether you know a request passes through an ordered chain of filters before ever reaching your controller.

Q

What is JWT? How do you implement JWT-based authentication in Spring Boot?

intermediate

Tests whether you know how a stateless, signed token replaces server-side session storage for authentication.

Q

What is @PreAuthorize and @Secured? What is the difference?

intermediate

Tests whether you know @PreAuthorize supports full SpEL expressions while @Secured only supports simple role checks.

Q

What is CSRF protection? When should you disable it?

intermediate

Tests whether you know why CSRF matters for browser sessions but is usually irrelevant for stateless token-based APIs.

Q

What changed in Spring Security 6 (Spring Boot 3)? What was removed?

advanced

WebSecurityConfigurerAdapter was removed — you define a SecurityFilterChain @Bean directly instead. antMatchers() was replaced by requestMatchers(), and authorizeRequests() by authorizeHttpRequests(). CSRF is commonly disabled for stateless REST APIs using SessionCreationPolicy.STATELESS.

Q

What is @HttpExchange in Spring Boot 3? How does it replace Feign?

advanced

@HttpExchange is Spring's own declarative HTTP client — define an interface with @GetExchange/@PostExchange annotations, register it via HttpServiceProxyFactory backed by WebClient or RestClient. Similar convenience to OpenFeign, but built into core Spring Framework with no extra dependency, and integrates natively with observability and virtual threads.

Q

What is RestClient (Spring Boot 3.2)? How does it differ from RestTemplate and WebClient?

intermediate

RestClient is a synchronous HTTP client with WebClient's fluent builder API — the blocking counterpart to WebClient. RestTemplate is older, less fluent, and effectively frozen for new code. WebClient is reactive/non-blocking. RestClient is Spring's recommended choice for new synchronous REST calls from Spring Boot 3.2 onward.

Q

What is Problem Details (RFC 9457) support in Spring Boot 3?

intermediate

Spring Boot 3 can auto-configure ProblemDetail as the standard error response shape (enable with spring.mvc.problemdetails.enabled=true) — structured JSON with type/title/status/detail/instance fields, replacing ad-hoc custom error response objects; @ExceptionHandler methods can return ProblemDetail directly.

Q

What is CRaC (Coordinated Restore at Checkpoint)? How does it complement native images?

advanced

CRaC checkpoints a fully warmed-up, already-JIT-optimized JVM process and restores it almost instantly — unlike Native Image (AOT, no JVM at all), CRaC keeps the real JVM, giving you full JIT performance AND fast startup. Spring Boot 3.2+ supports a Checkpointable lifecycle, aimed at serverless cold-start scenarios.

Q

What is SecurityContext and SecurityContextHolder? What are the storage strategies?

advanced

SecurityContext holds the current Authentication object. SecurityContextHolder stores it via a pluggable strategy: ThreadLocal (default, per-thread), InheritableThreadLocal (shared with child threads), or Global (one shared context, for desktop apps). With virtual threads, ThreadLocal still works correctly since each virtual thread gets its own.

Q

What is UserDetailsService? How does Spring Security authenticate a user?

intermediate

UsernamePasswordAuthenticationFilter extracts credentials, builds a token, and passes it to AuthenticationManager, which delegates to DaoAuthenticationProvider — that calls UserDetailsService.loadUserByUsername(), compares the password via PasswordEncoder.matches(), and on success sets the resulting Authentication into SecurityContext.

Q

What is PasswordEncoder? Why must you never store plain-text passwords?

beginner

PasswordEncoder hashes passwords before storage and verifies them on login without ever storing or comparing plain text. Default is BCryptPasswordEncoder (deliberately slow, adaptive cost factor); DelegatingPasswordEncoder's {bcrypt} prefix supports multiple algorithms. Never use NoOpPasswordEncoder in production.

Q

Where should you store JWT tokens on the client side? What are the security tradeoffs?

advanced

localStorage/sessionStorage are readable by any JS on the page (XSS-vulnerable). An HttpOnly cookie is safe from XSS but vulnerable to CSRF unless mitigated with SameSite=Strict/Lax or a CSRF token. Common best practice: keep the access token only in memory (a JS variable) and put the refresh token in an HttpOnly cookie.

Q

How do you handle JWT token expiry and refresh tokens?

advanced

Use a short-lived access token (e.g. 15 min) plus a long-lived refresh token (e.g. 7 days) stored server-side. On expiry, the client calls a dedicated refresh endpoint; the server validates the stored refresh token and issues a new pair, rotating (invalidating) the old refresh token to prevent replay. On logout, add the JWT to a denylist (Redis) until its natural expiry.

Q

What is the difference between authentication and authorization in Spring Security?

beginner

Authentication answers 'who are you' (verifying identity via password, JWT, OAuth2 token) and is handled by AuthenticationManager. Authorization answers 'what can you do' (checking permissions after identity is established) and is handled by AuthorizationManager, at both method and URL level.

Q

Explain the OAuth2 Authorization Code Flow. When is it used?

advanced

The user is redirected to the Authorization Server to authenticate and consent; it redirects back with a short-lived code; your backend exchanges that code (server-to-server, with a client secret that's never exposed to the browser) for an access + refresh token, then uses the access token to call the Resource Server. Used for server-side web apps — the most secure flow when you have a confidential backend.

Q

What is PKCE and why is it required for SPAs and mobile apps?

advanced

PKCE (Proof Key for Code Exchange) has the client generate a random code_verifier and send its hash (code_challenge) with the initial auth request; when exchanging the returned code, it sends the original verifier, which the server hashes and compares. Since SPAs and mobile apps can't safely hold a client secret, PKCE replaces it, preventing authorization-code interception attacks.

Q

What is the difference between oauth2Login() and oauth2ResourceServer() in Spring Security?

advanced

oauth2Login() is for apps acting as an OAuth2 CLIENT — it drives the Authorization Code flow and creates a session. oauth2ResourceServer() is for APIs acting as a RESOURCE SERVER — it validates incoming JWT Bearer tokens per request, stateless, no session. Most microservices use oauth2ResourceServer().

Q

How does Spring Security validate JWT tokens in an OAuth2 Resource Server?

advanced

Spring Security fetches the Authorization Server's public keys (JWK Set) from its jwks-uri, verifies the incoming JWT's signature against them, and validates standard claims (iss, aud, exp). Configure via spring.security.oauth2.resourceserver.jwt.jwk-set-uri.

Q

How do you integrate Spring Boot with Keycloak or Okta?

advanced

Add spring-boot-starter-oauth2-resource-server and set spring.security.oauth2.resourceserver.jwt.issuer-uri to the provider's realm URL — Spring auto-discovers the OIDC configuration and validates tokens automatically. For role mapping, customize JwtAuthenticationConverter to pull roles from Keycloak's non-standard realm_access.roles claim.

Apache Kafka

Q

What is a Kafka broker, and what is a Kafka cluster?

beginner

A broker is a single Kafka server that stores data and serves client requests (produce/consume). A cluster is a group of brokers working together, coordinated via a controller, which lets Kafka distribute topic partitions across multiple machines for both scalability (parallel throughput) and fault tolerance (if one broker fails, others still hold replicas of the data).

Q

What is Kafka replication, and why does it matter?

beginner

Each partition can be configured with a replication factor N, meaning N total copies of that partition's data are stored across different brokers — one is the leader (handles all reads/writes) and the rest are followers (passively replicate from the leader). If the leader broker fails, one of the in-sync followers is automatically promoted to leader, which is what gives Kafka its durability and fault tolerance without any data loss for committed messages.

Q

How does Kafka achieve fault tolerance?

intermediate

Fault tolerance comes from partition replication across multiple brokers (so losing one broker doesn't lose data), the ISR (in-sync replica) mechanism that only promotes a follower that's fully caught up to leader status, and configurable acknowledgment levels (acks=all waits for all in-sync replicas to confirm a write before considering it successful) — together these ensure the cluster keeps serving data correctly even when individual brokers fail.

Q

How does Kafka guarantee message durability?

intermediate

Kafka persists every message to disk (not just memory) as an append-only log, and with acks=all plus a replication factor greater than 1, a message is only considered successfully written once it's been copied to every in-sync replica — meaning it survives a single broker failure without loss. This combination of disk persistence, replication, and configurable acknowledgment is what lets Kafka be trusted for critical event data, not just best-effort messaging.

Q

How does Kafka achieve high throughput and low latency?

intermediate

Kafka uses sequential disk writes (append-only logs, which are much faster than random I/O), zero-copy transfer (sending data straight from disk to the network socket via the OS, bypassing the application's own memory), batching of messages on both the producer and consumer sides to reduce per-message network overhead, and partitioning to parallelize work across many brokers and consumers simultaneously.

Microservices Patterns

Q

What is the API Composition pattern in microservices?

intermediate

API Composition solves the problem of a query that needs data spread across multiple services' own databases — a composer (often the API Gateway or a dedicated aggregator service) calls each relevant service, then combines their responses into a single result for the client. It's the straightforward alternative to CQRS's dedicated read-model approach, simple to implement but less efficient for very large datasets or complex joins across many services.

Q

What is Transaction Log Tailing, and how does it relate to the Transactional Outbox pattern?

intermediate

Transaction Log Tailing is a specific implementation strategy for the Outbox pattern: instead of a separate poller reading an outbox table (Polling Publisher), a Change-Data-Capture tool (like Debezium) directly tails the database's own transaction/replication log to detect new committed rows and publish them as events. It achieves the same reliable dual-write guarantee as polling but with much lower latency and no added load from repeated polling queries.

Q

What is the Polling Publisher pattern in the context of the Transactional Outbox?

intermediate

Polling Publisher is the simpler of the two common Outbox-pattern implementations: a scheduled background job periodically queries the outbox table for new, unpublished rows, publishes each one as an event to the message broker, and marks it as sent. It's easier to build than transaction-log tailing (no CDC infrastructure needed) but introduces publish latency equal to the polling interval and adds repeated read load on the database.

Q

What is Data Offloading in a distributed system, and why is it used?

intermediate

Data Offloading means moving large payloads OUT of the primary message/event itself and into cheaper, purpose-built storage (like S3 or a blob store), replacing the payload in the message with just a reference/pointer to that storage location. It's used because message brokers like Kafka have practical size limits and cost characteristics that make them a poor fit for large binary blobs (images, big JSON documents) — keeping messages small and fast while the actual data lives elsewhere.

Q

What is Semantic Monitoring in microservices, and how is it different from standard health checks?

intermediate

Semantic Monitoring continuously runs synthetic, business-level transactions against a live production system (e.g. actually placing a test order end-to-end) to verify the system behaves correctly from a user's perspective, not just that individual services report themselves healthy. A standard health check can report every service as 'up' while a business flow is silently broken due to a misconfiguration between services — semantic monitoring catches exactly that class of failure.

Q

What is the Scaling Cube, and how does it apply to microservices architecture?

intermediate

The Scaling Cube (from 'The Art of Scalability') describes three independent axes for scaling a system: the X-axis (running multiple identical instances behind a load balancer — horizontal duplication), the Y-axis (splitting the application by function/service — which is exactly what microservices architecture does), and the Z-axis (splitting data by a key, like sharding by customer ID or region). Microservices architecture is essentially applying Y-axis scaling at the system level, and each individual microservice can then be independently scaled further along the X and Z axes.

Distributed Transactions & Saga

Q

What is the Two-Phase Commit (2PC) protocol and why is it not recommended for microservices?

advanced

Tests whether you know 2PC's blocking coordinator model doesn't scale and creates a single point of failure across services.

Q

When would you use the Saga pattern, and how would you handle a compensation transaction that itself fails?

advanced

Tests whether you've thought past the happy path — what happens when the undo step doesn't work either.

Q

Payment succeeds, but the Order Service crashes right after. How do you recover safely without losing money or the order?

advanced

Tests whether you can reason through a concrete Saga recovery scenario, not just define the pattern abstractly.

Q

How do you achieve exactly-once business processing on top of an at-least-once messaging system?

expert

Tests whether you know the trick isn't stopping duplicates from arriving — it's making processing idempotent so duplicates are harmless.

Q

What is the dual-write problem in microservices, and how does the Outbox Pattern solve it?

advanced

Tests whether you know writing to a DB and publishing an event are two separate operations that can't be made atomic without help.

Q

How does the Transactional Outbox Pattern work with Debezium or Change Data Capture (CDC)?

advanced

Tests whether you know CDC tails the database's own write-ahead log to publish outbox rows, instead of a fragile polling loop.

Q

How do you handle outbox table growth in a high-throughput system?

advanced

Tests whether you know to prune published rows and index the table correctly so it doesn't become its own bottleneck.

Q

What is eventual consistency, and how would you explain it to a non-technical business stakeholder?

advanced

Tests whether you can translate a technical consistency model into a concrete business-facing tradeoff.

Q

How do you test distributed transactions in a microservices architecture?

advanced

Tests whether you know this needs dedicated integration environments and event-assertion tooling, not just unit tests per service.

Q

What is the difference between the Outbox Pattern and the Saga Pattern — are they complementary or competing?

advanced

Tests whether you know Outbox solves reliable event publishing while Saga solves multi-step business transaction coordination — they're often used together.

Q

How do you implement the Inbox Pattern for idempotent message consumption?

advanced

Tests whether you know tracking processed message IDs in a dedicated table is the consumer-side mirror of the Outbox Pattern.

API Design, Performance & Resilience

Q

An API works perfectly with 100 concurrent users but times out at 10,000, even though CPU sits at only 40%. Why?

expert

Tests whether you know low CPU with high failure at scale usually points to thread pool or connection pool saturation, not compute.

Q

Average API latency is 200ms, but p99 is 8 seconds. What is the real problem, and why does average latency hide it?

advanced

Tests whether you know averages mask tail latency, and that a small fraction of very slow requests is often the actual production issue.

Q

Retries are making an outage worse instead of better. How does a retry storm actually happen, and how do you prevent it?

advanced

Tests whether you know synchronized retries without jitter can pile onto an already-struggling service and push it further down.

Q

When would you use a Circuit Breaker, a Retry, a Timeout, and a Bulkhead pattern — and how do they combine?

advanced

Tests whether you know these four resilience patterns solve different failure modes and are usually layered together, not chosen one at a time.

Q

Where would you store an idempotency key, and how do you handle two concurrent requests arriving with the same key?

advanced

Tests whether you've thought through the race condition of two identical requests landing at nearly the same instant.

Q

The same resource is updated from two devices simultaneously. How do you prevent one update from silently overwriting the other?

advanced

Tests whether you know optimistic locking (a version check) catches this cleanly without holding a lock the whole time.

Q

Two users try to book the last available seat at the exact same moment. How do you prevent double booking?

advanced

Tests whether you can pick correctly between optimistic locking, pessimistic locking, or an atomic decrement for this exact scenario.

Q

How would you process a 5GB CSV file upload without causing an OutOfMemoryError?

advanced

Tests whether you know to stream and process the file line by line instead of loading it entirely into memory first.

Q

How would you trace one request as it flows across five microservices and millions of log entries?

advanced

Tests whether you know a propagated correlation ID plus distributed tracing is what makes this actually possible.

Q

Your API's SLA is 1 second, but a downstream dependency's timeout is set to 2 seconds. What's wrong with this design?

advanced

Tests whether you know timeout budgets must cascade correctly — a downstream timeout longer than your own SLA guarantees you'll breach it.

Q

How do you implement API versioning — URI versioning vs header versioning vs media type versioning — and what are the tradeoffs of each?

advanced

Tests whether you know the practical implications each approach has for clients, caching, and backward compatibility.

Q

How would you rate-limit APIs differently for different customers or tenants?

advanced

Use a per-tenant key (API key, tenant ID) as the rate-limiter's bucket key instead of a single global limit — Resilience4j's RateLimiter or Redis-backed token buckets (as in Spring Cloud Gateway's RequestRateLimiter) both support a configurable KeyResolver so each tenant gets its own independent bucket and limit tier.

SOLID Principles in Practice

Q

Your PaymentService has 15 if-else branches for different payment types. Which SOLID principle is being violated, and how would you refactor it?

advanced

Tests whether you can spot an Open/Closed Principle violation in real code and know Strategy pattern is the standard fix.

Q

Can a class with only a single method still violate the Single Responsibility Principle?

advanced

Tests whether you know SRP is about reasons to change, not method count — a single method can still mix multiple concerns.

Q

When does implementing the Open/Closed Principle become over-engineering?

advanced

Tests whether you know abstracting for change that will never actually happen just adds indirection with no payoff.

Q

What happens when a child class compiles fine but returns unexpected results compared to its parent contract?

advanced

Tests whether you know this is a Liskov Substitution violation even without a compile error — the contract broke silently.

Q

What problems do 'fat interfaces' create in large systems, and how would you split one without breaking existing consumers?

advanced

Tests whether you know a bloated interface forces implementers to depend on methods they don't use, and how to migrate safely.

Q

What is the difference between Dependency Injection and Dependency Inversion? Does using @Autowired automatically guarantee DIP?

advanced

Tests whether you know DI is a mechanism while DIP is a design principle, and injecting a concrete class still violates DIP.

Q

How do SOLID principles apply at the microservice level, not just the class level — is SRP applicable to service boundaries?

advanced

Tests whether you can map object-oriented design principles onto architectural decisions about service decomposition.

Q

Looking at a 2000-line service class, which SOLID violations would you expect to find first, and how would you start refactoring it?

advanced

Tests whether you have a practical, prioritized approach to untangling a real legacy God class, not just theory.

Design Patterns for Distributed Systems

Kubernetes & Production Ops

Q

Your Kubernetes pod keeps restarting, but application logs show no clear error. How would you debug it?

advanced

Tests whether you know to check kubectl describe, previous container logs, OOMKilled status, and probe configuration.

Q

What is the difference between liveness, readiness, and startup probes in Kubernetes, and why does confusing liveness with readiness matter for Spring Boot?

intermediate

Tests whether you know a common pitfall: using the same health endpoint for both can cause unnecessary pod restarts.

Q

What is a CrashLoopBackOff and how do you debug it?

advanced

Tests whether you know Kubernetes' exponential backoff behavior for repeatedly-crashing containers and how to find the root cause fast.

Q

What is a PodDisruptionBudget and why is it important during rolling deployments?

advanced

Tests whether you know it prevents voluntary disruptions (like node drains) from taking down too many replicas at once.

Q

How do you implement graceful shutdown in a Spring Boot microservice running in Kubernetes so in-flight requests aren't dropped?

advanced

Tests whether you know server.shutdown=graceful, a SIGTERM handler, and a preStop hook all need to work together.

Q

One pod consistently receives 80% of the traffic while the remaining pods stay nearly idle. Why might this happen?

advanced

Tests whether you know client-side connection reuse or a misbehaving load-balancing algorithm can defeat even distribution.

Q

A scheduled job runs once locally but five times after scaling to five pods. How do you prevent this duplicate execution?

advanced

Tests whether you know a @Scheduled job needs a distributed lock (or ShedLock) to run exactly once across a clustered deployment.

Q

Your Spring Boot application takes 5 minutes to start in production but only 20 seconds locally. How do you debug it?

advanced

Tests whether you know to check DB connectivity latency, DNS resolution, and autoconfiguration scanning under production networking.

Q

What is the difference between resource requests and resource limits in Kubernetes, and what happens if limits are exceeded?

advanced

Tests whether you know exceeding a CPU limit throttles the pod while exceeding a memory limit gets it OOMKilled outright.

Database Migrations

Spring Internals — Bean Lifecycle & Proxies

Q

Why can returning a new object from a custom BeanPostProcessor silently remove @Transactional, @Cacheable, and @Secured proxies?

advanced

If postProcessAfterInitialization returns a brand-new object instead of the (possibly already-proxied) bean it was given, any AOP proxy Spring built for that bean is discarded — silently disabling every annotation-driven feature (transactions, caching, security) that depended on that proxy.

Q

Why does declaring a BeanFactoryPostProcessor as a non-static @Bean sometimes break @Value placeholder injection?

advanced

BeanFactoryPostProcessors must be instantiated very early, before normal bean instantiation and before @Value placeholders are resolved. A non-static @Bean method inside a @Configuration class can force that configuration class itself to be instantiated too early, before property sources are fully set up.

Q

How can a custom FactoryBean accidentally bypass Spring AOP proxy creation?

advanced

AOP proxies are normally applied via BeanPostProcessor around the OBJECT a bean definition produces. If a FactoryBean's getObject() constructs and returns its target manually instead of going through the full Spring-managed creation path, the proxy-creation BeanPostProcessors may never get a chance to wrap it.

Q

Why does a manually instantiated bean (new MyService()) never receive dependency injection or AOP advice?

intermediate

Dependency injection and AOP proxying both happen through Spring's container-managed bean creation lifecycle (BeanPostProcessors, autowiring). An object created with `new` bypasses the container entirely, so none of that machinery ever touches it.

Q

How does Spring decide between JDK Dynamic Proxy and CGLIB, and what production issues can that choice introduce?

advanced

JDK proxy requires the bean to implement an interface (the proxy implements that interface); CGLIB creates a runtime subclass and is used when there's no interface, or when proxyTargetClass=true (Spring Boot's default). CGLIB proxies can't proxy final classes/methods, and calling a proxied method from within the same class (self-invocation) bypasses either proxy type entirely.

Q

Why can SmartInitializingSingleton trigger expensive database calls before your application is actually ready?

advanced

SmartInitializingSingleton.afterSingletonsInstantiated() runs once ALL singleton beans are created, but before the application context is fully refreshed and ApplicationReadyEvent fires — code here that does eager DB warm-up can run before readiness probes or downstream dependencies expect traffic.

Q

What happens when two auto-configurations define the same bean with conflicting conditions?

advanced

Spring Boot evaluates auto-configuration classes in a defined order (via @AutoConfigureBefore/@AutoConfigureAfter and @ConditionalOnMissingBean); the first one whose conditions pass typically wins, and later ones back off. Running with --debug shows the exact Conditions Evaluation Report explaining which configuration was applied and why.

Q

Why can overriding an auto-configured bean unintentionally disable metrics, tracing, or health checks?

advanced

Many auto-configured beans (like a DataSource or RestTemplate) are automatically wrapped or instrumented by other auto-configurations (Micrometer metrics, tracing). Defining your own bean of the same type can suppress the @ConditionalOnMissingBean-guarded instrumentation that would have wrapped Spring Boot's default.

Q

How do ApplicationContextInitializer, BeanFactoryPostProcessor, and BeanPostProcessor execute during the Spring lifecycle?

advanced

ApplicationContextInitializer runs earliest, before the context is refreshed at all (can add property sources, register listeners). BeanFactoryPostProcessor runs after bean DEFINITIONS are loaded but before any bean is INSTANTIATED (can modify definitions). BeanPostProcessor runs around each individual bean's instantiation (can wrap the actual bean instances, e.g. for AOP proxies).

Q

Why does exposing JPA entities directly from REST APIs eventually become a production problem?

intermediate

Entities carry lazy associations (risking LazyInitializationException during JSON serialization), can leak internal/sensitive fields, tightly couple your API contract to your database schema, and make it hard to evolve either independently — DTOs decouple the two and let you control exactly what's exposed.

Q

How can Open Session in View hide performance bottlenecks until your database connection pool gets exhausted?

advanced

OSIV keeps the Hibernate session (and its DB connection) open for the entire HTTP request, including view rendering — lazy loading 'just works' anywhere in the request, but N+1 queries triggered by the view layer stay invisible, and every request holds a connection far longer than it needs to, exhausting the pool under load.

Q

Why can @TransactionalEventListener(AFTER_COMMIT) silently stop working in asynchronous event processing?

advanced

AFTER_COMMIT relies on the listener running within the SAME thread's transaction synchronization callbacks. If the listener is also marked @Async (running on a different thread) or the publishing transaction never actually commits (e.g., it's read-only or rolled back), the listener may never fire, with no obvious error.

Q

Why can a poorly written OncePerRequestFilter execute multiple times for a single request?

advanced

OncePerRequestFilter guards against re-execution using a request attribute flag — but internal dispatches (forward, include, async dispatch, error dispatch) with a DIFFERENT request object, or a filter registered under multiple filter-chain matches, can each re-trigger it since the 'already filtered' marker doesn't always carry over.

Q

How does @Configuration(proxyBeanMethods=false) improve startup performance, and what trade-offs does it introduce?

advanced

By default, @Configuration classes are CGLIB-proxied so that calling one @Bean method from another returns the SAME singleton instance. Setting proxyBeanMethods=false skips that proxy (faster startup, less CGLIB overhead) — but then calling one @Bean method directly from another creates a NEW instance instead of reusing the singleton, which only matters for configurations with inter-bean method calls.

Virtual Threads & GraalVM

Q

What are Virtual Threads and how do they differ from platform (OS) threads?

intermediate

Platform threads map 1:1 to OS threads — expensive to create in large numbers. Virtual threads are lightweight, JVM-managed threads (not OS-backed 1:1), cheap enough to create millions of. They don't make code faster; they make blocking code scalable, since a blocked virtual thread doesn't tie up an OS thread.

Q

How do you enable Virtual Threads in Spring Boot 3.2+?

intermediate

Set `spring.threads.virtual.enabled=true` in application.properties — Spring Boot auto-configures Tomcat and the @Async task executor to run on virtual threads, with no code changes needed for typical blocking Spring MVC code.

Q

How do Virtual Threads interact with @Transactional and connection pools?

advanced

Each virtual thread holding a DB connection for a transaction's duration still consumes a real pooled connection — with thousands of concurrent virtual threads, HikariCP pool exhaustion can become the new bottleneck even though threads themselves are cheap, so pool sizing and keeping transactions short (@Transactional(readOnly=true) where possible) still matter.

Q

How does Spring Boot support GraalVM Native Image, and what are its limitations?

advanced

Spring Boot 3+ runs an AOT processing phase at build time that generates bean-definition source code and reflect/proxy/resource config hints GraalVM needs, replacing most runtime reflection. Limitations: no dynamic class loading, longer build times, and libraries with heavy runtime reflection may need manual @RegisterReflectionForBinding or RuntimeHintsRegistrar hints.

Spring AI — Core, ChatClient & RAG

Q

What is Spring AI? How does it differ from LangChain? What is its core design principle?

beginner

Spring AI applies familiar Spring idioms (@Bean, starters, @Autowired, auto-configuration) to AI engineering, unlike LangChain's Python-first, chain-centric style. Its core principle is portability — swap AI providers with a config change and zero code changes.

Q

What is the ChatClient API? How is it similar to WebClient and RestClient?

intermediate

A fluent builder: chatClient.prompt().system("...").user("...").advisors(...).call().content(). Supports both synchronous (.call()) and streaming (.stream() returning Flux<String>), auto-configured via the starter, idiomatically mirroring WebClient's builder style.

Q

What is the Advisors API? Explain how the advisor chain works.

advanced

Advisors are interceptors wrapping ChatClient calls, ordered by getOrder(): Request → Advisor-1 pre → Advisor-2 pre → ChatModel → Advisor-2 post → Advisor-1 post → Response. Built-in ones include QuestionAnswerAdvisor (RAG), MessageChatMemoryAdvisor (memory), SimpleLoggerAdvisor (logging).

Q

What model types does Spring AI support? How are embeddings used?

beginner

ChatModel, EmbeddingModel, ImageModel, AudioTranscriptionModel, TextToSpeechModel, ModerationModel. Embeddings convert text into high-dimensional vectors for semantic similarity search — the foundation RAG is built on.

Q

How does Spring AI's structured output work? How do you map LLM responses to POJOs?

intermediate

Call .call().entity(MyClass.class) — Spring AI generates a JSON schema from the class, adds it as instructions in the prompt, and parses the response back into that type (backed by BeanOutputConverter). For lists, use .entity(new ParameterizedTypeReference<List<X>>(){}). Eliminates brittle manual string parsing.

Q

What AI providers does Spring AI support and how do you switch between them?

beginner

OpenAI, Anthropic Claude, Google Gemini/Vertex AI, Azure OpenAI, Amazon Bedrock, Mistral, and local Ollama. Switch by changing the starter dependency and updating properties (API key, model name) — the ChatModel interface itself is provider-agnostic, so application code doesn't change.

Q

What is RAG? Why does it exist and what problems does it solve?

beginner

RAG (Retrieval-Augmented Generation) solves an LLM's static training cutoff, hallucination on domain-specific facts, and lack of access to proprietary data — it embeds the query, does a vector similarity search, injects the top-k matching chunks into the prompt, and the LLM answers grounded in that retrieved context.

Q

Explain the full RAG ingestion pipeline in Spring AI.

intermediate

Load with a DocumentReader (Pdf/Text/Tika), split with TokenTextSplitter into chunks (512-1024 tokens with 10-20% overlap is a common starting point), embed each chunk with an EmbeddingModel, and store chunks+metadata+embedding via VectorStore.add(documents).

Q

What is the difference between QuestionAnswerAdvisor and RetrievalAugmentationAdvisor?

advanced

QuestionAnswerAdvisor is simple one-shot RAG — search the vector store, append context to the prompt. RetrievalAugmentationAdvisor is a modular pipeline supporting query transformers (rewrite/expand), multiple document retrievers, and document post-processors (re-ranking) — the production-grade, multi-step option.

Q

What vector stores does Spring AI support? How do you switch between them?

intermediate

PGVector, Chroma, Redis, Pinecone, Milvus, Weaviate, Qdrant, MongoDB Atlas, Elasticsearch, Neo4j and more, all behind one VectorStore abstraction (add(docs), similaritySearch(SearchRequest)) — switching is a dependency + config change, no application-code rewrite.

Q

What is query rewriting (RewriteQueryTransformer)? Why does it improve RAG quality?

advanced

Conversational follow-up queries ("what about its price?") are ambiguous to a vector search on their own. RewriteQueryTransformer uses an LLM to turn them into standalone, specific queries first; MultiQueryExpander generates several variants to improve recall — both plug into RetrievalAugmentationAdvisor.

Q

How do you implement conversation memory in Spring AI?

intermediate

Use MessageChatMemoryAdvisor with a ChatMemory implementation (InMemoryChatMemory for dev, a Redis/DB-backed one for production), passing a conversationId per session — the advisor appends prior messages to the prompt automatically. Order matters: add the memory advisor before any RAG advisor.

Q

What is the difference between RAG and fine-tuning? When do you use each?

advanced

RAG injects knowledge at inference time — cheaper, instantly updatable, and the answer is traceable to a source. Fine-tuning bakes knowledge into model weights — better for consistent tone/format, faster inference, but expensive and static. Use RAG for frequently-changing or proprietary knowledge; fine-tune when a consistent style/task format matters more.

Q

What are chunking strategies in RAG? How does chunk size affect quality?

intermediate

Fixed-size (split by token count), sentence-based (better coherence), recursive (paragraphs → sentences → words), and semantic (split on topic shifts, more expensive). Too small loses context; too large adds irrelevant noise — overlap between chunks preserves context across boundaries.

Q

What is hybrid search in RAG? How does it combine vector and keyword search?

advanced

Vector search finds conceptually similar chunks; keyword (BM25/full-text) search finds exact term matches. Hybrid search combines both scores (commonly via Reciprocal Rank Fusion) for better recall — important when users search using exact terms like error codes or product IDs that pure vector similarity can miss.

Q

How do you evaluate a RAG pipeline? What metrics matter?

advanced

Retrieval metrics: Precision@k, Recall@k, MRR. Generation metrics: ROUGE, BLEU, METEOR against reference answers. RAG-specific: Faithfulness (is the answer grounded in the retrieved context?), Answer Relevance, Context Precision — tools like RAGAS, Arize, and LangSmith automate this.

Spring AI — Tool Calling, Agents & Production

Q

What is tool/function calling in Spring AI? How do you register a Java method as a tool?

intermediate

Annotate a method with @Tool and pass its containing object to chatClient.prompt().tools(...). Spring AI generates a JSON schema for it and sends it to the LLM; when the LLM decides to call it, ToolCallingAdvisor intercepts, executes the real Java method, and feeds the result back for the LLM to finish its answer.

Q

What is an AI Agent? How do you build one with Spring AI?

advanced

An agent is an LLM that reasons over a goal, picks tools, executes them, observes results, and repeats (the ReAct loop) until done. In Spring AI: expose multiple @Tool methods and let the LLM orchestrate which to call, add MessageChatMemoryAdvisor for multi-turn state, and optionally use MCP for external tool ecosystems.

Q

What is MCP (Model Context Protocol)? How does Spring AI integrate with it?

advanced

MCP is an open protocol (from Anthropic) for connecting LLMs to external tools and data sources in a standardized, language-agnostic way. Spring AI provides both an MCP client and server — a Spring Boot app can expose its @Tool methods as an MCP server, discoverable by any MCP-compatible AI agent.

Q

What is the ToolCallingManager interface? How does it manage the tool execution lifecycle?

advanced

It's Spring AI's internal engine: receives a tool-call request from the LLM, resolves the matching ToolCallback (by name, via ToolCallbackResolver), executes it, and formats the result to send back — all automatically driven by ToolCallingAdvisor when you use ChatClient.

Q

What is GraphRAG? How does it differ from standard vector RAG?

advanced

Standard RAG retrieves flat chunks by vector similarity. GraphRAG stores knowledge as a graph (entities as nodes, relationships as edges, e.g. in Neo4j) enabling multi-hop reasoning ('subsidiaries of Apple's chip suppliers') that flat vector search can't express — Spring AI's Neo4j VectorStore supports hybrid graph+vector queries.

Q

What is re-ranking in RAG? How does a CrossEncoder improve retrieval quality?

advanced

Initial top-k vector retrieval can return chunks that are semantically similar but not truly relevant. A CrossEncoder jointly processes the query and each candidate chunk through a model to score real relevance, reordering results — plugged in via a DocumentPostProcessor in RetrievalAugmentationAdvisor.

Q

What are the agentic workflow patterns supported in Spring AI?

advanced

Prompt Chaining (output feeds the next call), Routing (LLM picks which tool/workflow to invoke), Parallelization (multiple calls in parallel, aggregated), Orchestrator-Subagent (a master LLM delegates to specialized agents), and Evaluator-Optimizer (one LLM generates, another critiques in a loop) — all composed from ChatClient calls and @Tool methods.

Q

How do you implement a multi-agent system in Spring AI?

advanced

Each agent is its own ChatClient with its own system prompt, tools, and memory. A supervisor agent routes a task to the right specialized agent (SearchAgent, DatabaseAgent, etc.) based on intent, and agents report results back to the supervisor — MCP can expose agents as tools to each other for full autonomous orchestration.

Q

What is the difference between zero-shot, few-shot, and chain-of-thought prompting?

intermediate

Zero-shot gives just the task, no examples. Few-shot includes 2-5 example input/output pairs to demonstrate the expected format. Chain-of-thought instructs the model to 'think step by step,' dramatically improving reasoning on complex tasks — in Spring AI, few-shot examples go in the system message, CoT is triggered in the user message or system instructions.

Q

What is @ToolParam and how does Spring AI generate tool schemas?

intermediate

@ToolParam(description="...") annotates a tool method's parameters; Spring AI uses this plus Jackson's schema generation to produce the JSON Schema sent to the LLM alongside the tool definition. Clear, descriptive parameter descriptions directly improve how accurately the LLM calls the tool.

Q

How do you implement tool call error handling and retries in Spring AI?

advanced

Wrap tool logic in try-catch and return a descriptive error STRING as the tool result — the LLM sees it and can decide to retry with different arguments or acknowledge failure. For HTTP-level retries, configure RetryTemplate on the ChatModel, or use Spring Retry's @Retryable on the @Tool method for transient failures.

Q

What is semantic caching and how can it reduce LLM costs in Spring AI?

advanced

Standard caching matches by exact prompt string. Semantic caching embeds the incoming prompt and searches a vector store for a similar-enough past query (above a similarity threshold), returning its cached answer instead of calling the LLM again — implemented as a custom CallAdvisor, useful for reducing cost on repeated or paraphrased questions.

Q

How do you handle LLM token limits in a production Spring AI application?

advanced

Each model has a fixed context window; if history + RAG context + system prompt exceeds it, the API errors out. Mitigate with a memory advisor that trims the oldest messages as the limit approaches, periodic summarization of old messages, and capping how many chunks RAG retrieval injects.

Q

What is the Guardrails pattern in Spring AI? How do you implement input/output validation?

advanced

Input guardrails check user input before it reaches the LLM (prompt injection, PII, off-topic queries); output guardrails check the LLM's response (hallucination, PII leakage, policy violations). Implement both as custom CallAdvisors — pre-advisors for input, post-advisors for output — using either an LLM-based moderation call or regex/NLP checks.

Q

What is prompt injection and how do you defend against it in Spring AI?

advanced

Prompt injection is malicious user input designed to override the system's instructions (e.g. 'ignore all previous instructions'). Defend by keeping system and user messages in separate roles rather than concatenating them into one string, sanitizing input, adding output guardrails, and requiring human-in-the-loop confirmation for sensitive tool actions.

Q

How do you implement streaming Server-Sent Events (SSE) with Spring AI in a REST controller?

intermediate

Return a Flux<String> from a controller method with produces = MediaType.TEXT_EVENT_STREAM_VALUE, backed by chatClient.prompt().user(message).stream().content() — Spring auto-configures SSE from the Flux return type, and the browser receives tokens as they're generated.

Q

What is the difference between ChatMemory and VectorStore for context management?

intermediate

ChatMemory stores the conversation's own messages in order — short-term, session-scoped continuity. VectorStore stores embedded knowledge-base chunks — long-term, shared domain knowledge. A production chatbot typically uses both together: memory for the conversation, RAG for facts.

Company & Architect-Level