Hirenix kaise padhata hai
Ek chapter. 90 minute.
Interview ke liye taiyaar.
Har concept ek real-world problem se — jaisa production code mein aata hai, waisa. Ratna nahi padta, samajh aa jaata hai. Har question ka model answer diya hai: interviewer ko exactly kya bolna hai, aur kyun. Phir usi chapter ka AI mock interview.
- 📖Concept, 5 min meinJargon nahi — seedhi baat
- 🛠️Real-world problemJaisa production code mein aata hai
- 💬Model answerInterview mein kya bolna hai
- 🧠FlashcardsRevision 10 min mein
- 🤖AI mock interviewFollow-up bhi poochta hai
- 📊Weak topicsKahan phans rahe ho, pata chale

Farq content ka nahi, filter ka hai — sirf wahi jo production mein actually use hota hai aur interview mein actually poocha jaata hai. Kitaabi topics jo industry mein kahin nahi chalte, wo yahan nahi milenge.
Certificates
Learn all 18 topics and earn your Spring Microservices certificate
Finish every Spring Microservices topic and a certificate with your name on it is issued instantly. No exam, no waiting. Download it, share it on LinkedIn, and put it on your resume.
Chapter certificate
Your name, the Spring Microservices course and all 18 topics on it.
Stack Mastery certificate
Finish every Java Backend chapter for the Java Backend Stack Mastery certificate.
Anyone can verify it
Each certificate has a QR code and a public link at hirenix.in/verify.

Verified credential
hirenix.in/verify/…
What you’ll learn
- ●Microservices kyun: kya milta hai, kya chukana padta hai, aur kab monolith jeetta hai
- ●Service-to-service calls: RestClient aur HttpExchange interfaces
- Timeouts: ek dheemi service caller ko kaise le doobti haiPro
- Retries aur idempotency: jab retry duplicate bana deta haiPro
- Resilience4j ke circuit breakers: closed, open aur half-openPro
- Eureka ke saath service discovery aur client-side load balancingPro
- API gateway: ek entry point, routes aur filtersPro
- Spring Cloud Config ke saath centralized configurationPro
- Distributed tracing: ek request ko kai services me follow karnaPro
- Kafka ke saath asynchronous messaging: topics, partitions, keys aur consumer groupsPro
- Kafka error handling: retries, poison messages aur dead-letter topicsPro
- Services ke beech data consistency: dual-write problem, outbox aur sagasPro
- Health probes aur deployment: liveness, readiness, containersPro
- Service boundaries ko test karna: stubbed HTTP aur embedded brokerPro
- RecapPro
- ●Project: Job Board ko Services me Baanto
- Project: Ek Flaky Service Call ko Resilient BanaoPro
- Project: Kafka ke saath Event-Driven Application AlertsPro
Free lessons
Microservices kyun: kya milta hai, kya chukana padta hai, aur kab monolith jeetta hai
"Kya hume microservices use karne chahiye?" asal me ye sawaal hai ki aap kya keemat chukane ko taiyaar hain. Application ko services me baantne se method calls network calls ban jaati hain, ek database kai ban jaate hain, aur ek deployment bahut saare. Ye topic job board ka ek hi chhota feature dono tarah chalata hai - monolith ki tarah aur do services ki tarah - aur naapta hai ki asal me kya badalta hai.
Setup: ek feature, do shakal
Feature seedha hai: kisi job ki application ko us job ka title chahiye. Is machine par ek hi JVM me teen Spring Boot apps start ki gayi, har ek --server.port=0 ke saath, taaki har ek ko apna random port mile:
| App | Kiska maalik | Job title kaise milta hai |
|---|---|---|
monolith (MonoApp) |
ek H2 database jisme job aur job_application tables |
JobCatalog bean ko bulata hai - ek method call |
jobs-service (JobsApp) |
apna jobsdb jisme job table |
GET /jobs/{id} deta hai |
| applications-service | apna appsdb jisme sirf job_application |
RestClient se jobs-service ko bulata hai - ek network call |
Yahan service ka matlab bas ek alag chalti hui application hai jiska apna port, apna data aur ek HTTP contract ho. (Teeno ek hi JVM me localhost par chali. Asli services alag process aur alag machines par chalti hain, jisse neeche ki har keemat aur badi hi hoti hai. Is environment me Docker aur asli network nahi hai.)
Naap ne kya dikhaya
1. Network hop mehnga hai, aur asthir bhi. Dono raaston ne wahi H2 query chalayi. Har ek ki 5000 calls, 2000 warm-up calls ke baad, teen rounds, do alag runs me. In chhe rounds me HTTP raasta method call se 76x se 272x tak zyada samay le gaya. Farak jitna bada hai, utna hi ahem uska phailaav hai: localhost par, bina kisi asli network ke, ek round doosre se teen guna se zyada dheema tha. Latency ke kisi ek number ko ek sample maaniye, sach nahi.
2. Database-per-service integrity ko database se bahar le jaata hai. Monolith me table par foreign key hai, isliye job 999 ki application daalna JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation ke saath fail hua. applications-service me wahi insert save ho gaya (rows=1), jabki jobs-service me job 999 tha hi nahi (0). Database-per-service me boundary ke paar koi foreign key nahi hoti. Jo kaam ek constraint muft me karta tha, wo ab aapke code ko karna padega - ek check call, ek event, ya ek clean-up job.
3. Failure aadha-adhoora ho jaata hai. jobs-service band karne par applications-service chalti rahi (true), par uski call fail hui: ResourceAccessException, jad me HttpHostConnectException ... Connection refused. Monolith me beech me network nahi hai, par wahan aadhi haalat bhi nahi hoti: wo band to sab band. Services fault isolation deti hain, aur badle me har call ki jagah ko tay karna padta hai ki doosri taraf gayab ho to kya karein. Topic 3 se 5 isi baare me hain.
4. Independent deploy sach hai - par use madad chahiye. applications-service chalti rahi (active=true, kabhi restart nahi hui) aur ek naya jobs-service start kiya gaya. Yahi independent deploy ka fayda hai. Par naye instance ko naya random port mila, aur applications-service purane address ko bulati rahi aur Connection refused paati rahi, jab tak use naya URL nahi diya gaya. Hard-coded address independent deploy me nahi tikte; ye wahi samasya hai jo service discovery (topic 6) hal karti hai.
Fayde, dhyan se kahe hue
- Independent deploy aur release: ek team applications-service ko dobara deploy kiye bina jobs-service ship kar sakti hai. Upar dikhaya.
- Fault isolation: ek service band hone se baaki chalti rehti hain. Upar dikhaya - par jo caller failure ko handle nahi karta, wo phir bhi toot-ta hai.
- Independent scaling: sirf vyast service ki zyada copies chala sakte hain (topic 6 do instances chalata hai).
- Team ownership: ek chhoti team ek service aur uske data ki maalik. Ye sangathan ka fayda hai; koi code run ise dikha nahi sakta.
Keemat
- Method calls ki jagah network calls: dheemi, aur aise tareekon se fail ho sakti hain jo method call nahi hoti (timeout, connection refused, aadhi safalta).
- Bikhra hua data: services ke paar koi join ya foreign key nahi, aur do databases par ek transaction nahi (topic 12).
- Operational overhead: zyada deployments, configuration, monitoring aur tracing (topic 7 se 9 aur 13).
- Services ke paar debugging: user ki ek request kai logs chhoo sakti hai.
Kab use karein: jab system ke hisse sach me alag-alag deploy, scale ya own hone chahiye, unke beech ki boundaries achhi tarah samajh me aa chuki hon, aur aap kai services chalane ka operational overhead utha sakte hon.
Kab NAHI: naye product ke liye jiski boundaries abhi badal rahi hain, chhoti team ke liye, ya jab asli maqsad sirf "saaf code" ho. Saaf modules wala ek achha monolith chalane me sasta aur badalne me aasaan hai, aur baad me unhi boundaries par baanta ja sakta hai jo aapne sach me seekhi hain. Microservices ko default maan lena har fayde ki zaroorat se pehle hi upar ki har keemat chuka deta hai.
Trade-off: aap in-process saadgi (tez calls, ek transaction, database ki integrity) ke badle independence (alag deploy, scale aur fail) lete hain. Ye sauda tabhi faydemand hai jab wo independence aap sach me use karte hon.
// ---- MONOLITH (t1.mono): one app, one database. The catalog is just a bean. ----
@Service
public class JobCatalog {
private final JdbcTemplate db;
public JobCatalog(JdbcTemplate db) { this.db = db; }
public String title(long id) { return db.queryForObject("select title from job where id = ?", String.class, id); }
}
// monodb: job_application.job_id REFERENCES job(id) <- the database guards the link
// ---- SERVICES: jobs-service (t1.jobs) owns jobsdb and exposes the same question over HTTP ----
@RestController
class JobsController {
private final JdbcTemplate db;
JobsController(JdbcTemplate db) { this.db = db; }
@GetMapping("/jobs/{id}") String title(@PathVariable("id") long id) {
return db.queryForObject("select title from job where id = ?", String.class, id);
}
}
// applications-service (t1.apps) owns appsdb: job_application(job_id bigint not null) - no job table, no foreign key
// ---- Main: all three apps started in one JVM, each on its own random port ----
var mono = new SpringApplicationBuilder(MonoApp.class).run("--server.port=0", "--spring.datasource.url=jdbc:h2:mem:monodb", ...);
var jobs = new SpringApplicationBuilder(JobsApp.class).run("--server.port=0", "--spring.datasource.url=jdbc:h2:mem:jobsdb", ...);
var apps = new SpringApplicationBuilder(ApplicationsApp.class).run("--server.port=0", "--spring.datasource.url=jdbc:h2:mem:appsdb", ...);
RestClient http = apps.getBean(RestClient.Builder.class).baseUrl("http://localhost:" + jobsPort).build();
// 1. same question, two shapes
catalog.title(7); // method call
http.get().uri("/jobs/7").retrieve().body(String.class); // network call
// 2. 5000 calls each after 2000 warm-up, timed with System.nanoTime(), 3 rounds
// 3. who guards the reference?
monoDb.update("insert into job_application(job_id, candidate) values (999, 'asha')");
appsDb.update("insert into job_application(job_id, candidate) values (999, 'asha')");
// 4. stop jobs-service, call it again
jobs.close();
http.get().uri("/jobs/7").retrieve().body(String.class);
// 5. start a new jobs-service (new random port); applications-service is not restarted
var jobs2 = new SpringApplicationBuilder(JobsApp.class).run("--server.port=0", ...);Service-to-service calls: RestClient aur HttpExchange interfaces
Application baantte hi ek service ko doosri service ko HTTP par bulana padta hai. Spring Boot 3.5 me ye kaam kai clients kar sakte hain, aur wo tab tak ek jaise dikhte hain jab tak kuch galat na ho. Ye topic ek hi jobs-service ko teen tarah ke clients se bulata hai aur dikhata hai ki har ek success par, 404 aur 500 par, aur timeout property set hone par kya lautata hai.
Setup
jobs-service me GET /jobs/{id} hai (Job record lautata hai, anjaan id par 404, id 500 par 500), POST /jobs (Location header ke saath 201) aur GET /slow?ms=.... Caller app --spring.http.client.read-timeout=1s ke saath start ki gayi. Sab kuch localhost par Boot 3.5.16 aur Spring Cloud OpenFeign 4.3.3 par chala.
A. RestClient: fluent client
RestClient ek synchronous client hai jiska fluent API hai: get(), uri(...), retrieve(), phir body(...) ya toEntity(...). Runs ne dikhaya:
body(Job.class)ne JSON koJob[id=7, title=Java Developer, company=Acme]bana diya.body(String.class)ne kachcha JSON lautaya.toEntity(Job.class)ne status aur headers bhi diye:201 CREATED Location=/jobs/101.404parretrieve()neHttpClientErrorException$NotFoundphenka.500parHttpServerErrorException$InternalServerError. Dono me status aur response body tha. Dhyan dijiye body me kya nahi tha: server ka reason textjob 404 not foundBoot ke default error JSON me nahi tha. Doosri service ka error message us body se padhne ki yojana tab tak mat banaiye jab tak wo service use wahan na daale.onStatus(...)ne default badal diya: 404 aapka apnaNoSuchElementExceptionban gaya. Remote status ko domain exception me badalne ka yahi tareeka hai.exchange(...)ne kachcha access diya aur kuch nahi phenka:status 404, nothing thrown. Ise tab use kijiye jab 404 ek normal jawab ho, galti nahi.
B. @HttpExchange: calls ki jagah ek interface
@HttpExchange("/jobs") ke saath @GetExchange aur @PostExchange remote API ko ek Java interface ki tarah likhte hain. RestClientAdapter.create(rc) ke saath HttpServiceProxyFactory ne runtime par implementation banaya - ek JDK dynamic proxy (jdk.proxy2.$Proxy120). Calls neeche wale RestClient jaisi hi chali: jc.get(7) ne record lautaya, jc.create(...) ne 201 CREATED, aur jc.get(404) ne wahi HttpClientErrorException$NotFound phenka. Interface sirf ek saaf chehra hai; error handling aur configuration us RestClient se aati hai jo aap andar dete hain.
C. OpenFeign: @FeignClient
@EnableFeignClients aur Spring MVC annotations (@GetMapping, @PathVariable) wale interface par @FeignClient(name = "jobs-service", url = "${jobs.url}") se jo bean bana wo bhi JDK proxy tha. Success par wahi Job mila, par exceptions alag hain: 404 par feign.FeignException$NotFound aur 500 par feign.FeignException$InternalServerError. Jo code HttpClientErrorException pakadta hai, wo inhe nahi pakdega. OpenFeign Spring Cloud ka hissa hai, Spring Framework ka nahi; @HttpExchange ke liye koi alag project nahi chahiye.
D. Ek property, chaar clients - sabse ahem nateeja
spring.http.client.read-timeout=1s set karke har client ne GET /slow?ms=1500 bulaya:
| Client | Nateeja |
|---|---|
injected RestClient.Builder se bana RestClient |
lagbhag 1 s baad ResourceAccessException, jad me SocketTimeoutException |
RestClient.create(url) |
intezaar kiya aur dheema jawab lautaya (lagbhag 1.5 s) |
new RestTemplate() |
intezaar kiya aur dheema jawab lautaya |
@FeignClient |
intezaar kiya aur dheema jawab lautaya |
Boot property sirf us client par lagi jo Boot ke RestClient.Builder se bana tha. RestClient.create() ya new RestTemplate() se bana client Boot ki configuration se guzra hi nahi, aur OpenFeign ne bhi wo property use nahi ki (uski apni client settings hain, jo is run me test nahi hui). Topic 9 tracing headers ke liye yahi bantwara dikhata hai. Jo aadat banani hai: RestClient.Builder inject kijiye aur usi se banaiye; application code me RestClient.create() mat bulaiye.
RestTemplate, WebClient, RestClient
RestTemplateSpring Framework 6.2.19 par ab bhi chala (row D). Spring documentation ke hisaab se ye purana template-style API hai, aur naye synchronous code koRestClientki taraf bheja jaata hai.WebClientspring-webfluxka reactive client hai. Wo module is environment ke classpath par nahi hai, isliye yahanWebClientka kuch nahi chalaya gaya; documentation ke hisaab se ise tab chuniye jab bulane wali application khud reactive ho.RestClient(documentation ke hisaab se Spring Framework 6.1+)RestTemplatewale blocking model par hi fluent API deta hai.
Kab kaunsa use karein: servlet application me seedhi calls ke liye injected builder se RestClient; @HttpExchange interface jab ek remote API kai jagah se bulaya jaaye aur aapko typed contract chahiye; OpenFeign jab codebase pehle se use use karta ho aur uske aas-paas Spring Cloud features bane hon.
Kab NAHI: application code me RestClient.create() ya new RestTemplate() mat use kijiye - upar naapa, ye Boot ki client settings ko chup-chaap nazarandaaz karte hain. Feign aur RestClient ke exceptions ko bina map kiye ek error-handling layer me mat milaiye; ye alag types hain.
Trade-off: declarative interfaces (@HttpExchange, Feign) boilerplate hatate hain aur calls ko local method call jaisa dikhate hain. Yahi unka khatra bhi hai - jc.get(7) jaisi line ek network call chhupati hai jo timeout ho sakti hai, 404 de sakti hai ya beech me fail ho sakti hai, theek jaise topic 1 ne dikhaya.
// ---- jobs-service (t2.jobs): the service being called ----
@GetMapping("/jobs/{id}") Job get(@PathVariable("id") long id) {
if (id == 500) throw new IllegalStateException("database unavailable");
Job j = jobs.get(id);
if (j == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "job " + id + " not found");
return j;
}
@PostMapping("/jobs") ResponseEntity<Job> create(@RequestBody Job in) { ... return ResponseEntity.created(URI.create("/jobs/" + j.id())).body(j); }
@GetMapping("/slow") String slow(@RequestParam("ms") long ms) throws InterruptedException { Thread.sleep(ms); return "slow reply after " + ms + " ms"; }
// ---- caller (t2.caller), started with --spring.http.client.read-timeout=1s ----
@SpringBootApplication
@EnableFeignClients
public class CallerApp { }
// A. RestClient from Boot's injected builder
RestClient rc = ctx.getBean(RestClient.Builder.class).baseUrl(jobsUrl).build();
rc.get().uri("/jobs/{id}", 7).retrieve().body(Job.class);
rc.post().uri("/jobs").body(new Job(0, "SRE", "Beta")).retrieve().toEntity(Job.class);
rc.get().uri("/jobs/{id}", 404).retrieve().body(Job.class); // 4xx
rc.get().uri("/jobs/{id}", 500).retrieve().body(Job.class); // 5xx
rc.get().uri("/jobs/{id}", 404).retrieve()
.onStatus(s -> s.value() == 404, (req, res) -> { throw new NoSuchElementException("no such job"); })
.body(Job.class);
rc.get().uri("/jobs/{id}", 404).exchange((req, res) -> "status " + res.getStatusCode().value() + ", nothing thrown");
// B. declarative interface on top of the same RestClient
@HttpExchange("/jobs")
public interface JobsHttpClient {
@GetExchange("/{id}") Job get(@PathVariable("id") long id);
@PostExchange ResponseEntity<Job> create(@RequestBody Job job);
}
JobsHttpClient jc = HttpServiceProxyFactory.builderFor(RestClientAdapter.create(rc)).build().createClient(JobsHttpClient.class);
// C. OpenFeign (spring-cloud-openfeign 4.3.3)
@FeignClient(name = "jobs-service", url = "${jobs.url}")
public interface JobsFeignClient {
@GetMapping("/jobs/{id}") Job get(@PathVariable("id") long id);
@GetMapping("/slow") String slow(@RequestParam("ms") long ms);
}
// D. one property, four clients: GET /slow?ms=1500
rc.get().uri("/slow?ms=1500")... // built from the injected Builder
RestClient.create(jobsUrl).get().uri("/slow?ms=1500")...
new RestTemplate().getForObject(jobsUrl + "/slow?ms=1500", String.class);
feignClient.slow(1500);Project: Job Board ko Services me Baanto
Ch9 me job board ek database wali ek Spring Boot application thi; Ch10 ne use surakshit kiya aur Ch11 ne test kiya. Ye project use do services me baant-ta hai - jobs-service jobs ki maalik, applications-service applications ki - aur har wo faisla chala kar dekhta hai jo ye bantwara zaroori banata hai. Dono services is machine par apne-apne H2 database ke saath alag Spring Boot apps ki tarah chali, Spring Boot 3.5.16 par.
Bantwara
| jobs-service | applications-service | |
|---|---|---|
| maalik | job table (id, title, status) |
application table (candidate, job_id) |
| deti hai | GET /jobs/{id}, baad me GET /jobs?ids=... |
POST /applications, GET /applications |
| doosre ke baare me jaanti hai | kuch nahi | ek @HttpExchange interface JobsApi, sirf zaroori fields ke saath |
Boundary maalikaana hak ke hisaab se hai: jo job ka status badalta hai, wahi job table ka maalik. applications-service sirf job_id rakhti hai aur uske paas koi job table nahi - topic 1 ka database-per-service.
JobsApi Boot ke injected RestClient.Builder se bana hai (topic 2), connect-timeout aur read-timeout 1 s ke saath (topic 3). Client factory jdk rakhi gayi taaki HTTP client khud se request dobara na bheje (topic 3 ki chhupi retry).
Kadam 1: foreign key network call ban jaati hai
Monolith me ek hi transaction ke andar foreign key aur status check applications ko bachate the. Ab POST /applications pehle jobs-service se poochta hai:
- job 7 (khuli) ->
201 applied to Java Developer - job 999 (maujood nahi) ->
422 job 999 does not exist- remote404ko is service ke apne jawab me badla gaya, error ki tarah aage nahi bheja - job 8 (band) ->
409 job 8 is CLOSED
Ye check atomic nahi hai: check aur insert ke beech job band ho sakti hai. Monolith ki ek transaction ise rokti thi; yahan aap ek chhoti khidki maan lete hain, ya baad me events se sambhalte hain (topic 12 aur project 18).
Kadam 2: HTTP par N+1
"Meri applications" ko job titles chahiye, jo applications-service ke paas nahi hain. Pehle version ne har application ke liye jobs-service ko ek baar bulaya: 5 applications -> 5 calls. Har call 150 ms lene par page ne 847 ms liye.
Batch endpoint GET /jobs?ids=... jodne par wahi paanch titles 1 call aur 173 ms me aaye. Ye Ch9 ki N+1 samasya hi hai, bas har "query" ab network ka chakkar hai. Provider ka API consumers ke asli padhne ke tareeke ke hisaab se banaiye, aur sirf response body nahi, calls ki ginti naapiye. (Timings localhost par ek run ki; calls ki ginti bharosemand hissa hai.)
Kadam 3: jobs-service dheemi hai
jobs-service ko har call par 3 s lene diya.
- 1 s read timeout ke saath: 1020 ms baad
503 jobs-service unavailable, try again later. - Break 1 - bina timeout properties: user ne 3035 ms intezaar kiya aur
201paaya. Kaam hua, par apply sambhalne wala applications-service ka har thread 3 s pakda raha. Asli traffic me yahi topic 3 ka cascading failure hai.
Kadam 4: jobs-service band hai
- Sambhala hua: 25 ms me
503 jobs-service unavailable, try again later. Connection refused tez hota hai, aur user ko saaf, dobara try karne laayak jawab milta hai. - Break 2 - exception sambhala nahi: 29 ms me
500 Internal Server Error. User aur kisi bhi monitoring ko ab applications-service tooti dikhti hai, jabki band jobs-service hai. - Dono case me
applications rows for meera: 0. Bina jaanchi job ke kuch save nahi hua, isliye data sahi raha - keemat ye ki jobs-service band rehne tak users apply nahi kar sakte.
Ye project aapke saamne kaunse faisle chhodta hai
- Availability vs sakhti. Kadam 4 ne "pakka na ho to mana karo" chuna. Doosra raasta - application ko
PENDINGle lena aur asynchronously jaanchna (topic 12 ka saga) - outage me bhi apply chalu rakhta hai, baad ke rejections ki keemat par. - Copy kiya data vs maanga hua data. Kadam 2 ko applications-service me job titles ki events se update hone wali local copy se bhi hal kar sakte hain: padhte waqt koi call nahi, par titles eventually consistent.
- Errors kaun badle. applications-service ko jobs-service ke
404, timeouts aur connection failures ko apne khud ke API jawabon (422,503) me badalna padta hai. Doosri service ke errors aage bhejna, ya unhe500ban jaane dena, ek service ki samasyaon ko poore system me faila deta hai.
Saath le jaane wali shakal
Monolith baantne se koi niyam nahi hat-ta; har niyam ek network call, ek event, ya ek maani hui asangati me chala jaata hai. Jo niyam pehle foreign key, join ya transaction tha, uske liye saaf tay kijiye ki wo teeno me se kya banega - aur jodi gayi har call par timeout aur error translation lagaiye.
// ---- jobs-service: owns the job table (its own H2 database) ----
@GetMapping("/jobs/{id}")
Job one(@PathVariable("id") long id) throws InterruptedException {
return query("where id = ?", id).stream().findFirst()
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "job " + id));
}
@GetMapping("/jobs") // batch endpoint, added in step 2
List<Job> many(@RequestParam("ids") List<Long> ids) throws InterruptedException { ... "where id in (?, ?, ...)" ... }
// query(...) counts HITS and can sleep DELAY_MS to simulate a slow service
// ---- applications-service: owns the application table (its own H2 database, no job table) ----
public interface JobsApi { // only the fields this service needs
record JobView(long id, String title, String status) { }
@GetExchange("/jobs/{id}") JobView job(@PathVariable("id") long id);
@GetExchange("/jobs") List<JobView> jobs(@RequestParam("ids") List<Long> ids);
}
@Bean
JobsApi jobsApi(RestClient.Builder builder, Environment env) { // built from Boot's builder: timeouts apply
RestClient rc = builder.baseUrl(env.getProperty("jobs.url")).build();
return HttpServiceProxyFactory.builderFor(RestClientAdapter.create(rc)).build().createClient(JobsApi.class);
}
@PostMapping("/applications")
ResponseEntity<String> apply(@RequestBody ApplyRequest req) {
JobsApi.JobView job;
try {
job = jobs.job(req.jobId());
} catch (HttpClientErrorException.NotFound e) {
return ResponseEntity.unprocessableEntity().body("job " + req.jobId() + " does not exist");
} catch (RestClientException e) {
if (!handleFailures) throw e; // break 2 sets demo.handle-failures=false
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("jobs-service unavailable, try again later");
}
if (!"OPEN".equals(job.status())) return ResponseEntity.status(HttpStatus.CONFLICT).body("job " + job.id() + " is " + job.status());
db.update("insert into application(candidate, job_id) values (?, ?)", req.candidate(), req.jobId());
return ResponseEntity.status(HttpStatus.CREATED).body("applied to " + job.title());
}
@GetMapping("/applications") // v1: one jobs-service call per application
List<String> mine(@RequestParam("candidate") String candidate) {
return db.queryForList("select job_id from application where candidate = ? order by id", Long.class, candidate)
.stream().map(id -> jobs.job(id).title()).toList();
}
@GetMapping("/applications/v2") // v2: one batch call
List<String> mineBatched(@RequestParam("candidate") String candidate) {
List<Long> ids = db.queryForList("select job_id from application where candidate = ? order by id", Long.class, candidate);
Map<Long, String> titles = jobs.jobs(ids).stream().collect(Collectors.toMap(JobsApi.JobView::id, JobsApi.JobView::title));
return ids.stream().map(titles::get).toList();
}
// applications-service runs with --spring.http.client.connect-timeout=1s --spring.http.client.read-timeout=1s
// --spring.http.client.factory=jdk (no hidden 503/429 resend, topic 3)
// break 1: a second applications-service started with no timeout propertiesSpring Microservices interview questions & answers
10 sample questions below — 204+ in the full bank inside.
Registry ki nazar se instance ke graceful shutdown aur crash me kya farak hai?
Graceful shutdown instance ko deregister karta hai, isliye callers use jaldi chhod dete hain - chapter me close() ke theek baad caller ne instances=1 dikhaya aur saari calls bache instance par bheji. Crash koi alvida nahi bhejta; entry tab tak rehti hai jab tak heartbeats ke bina uski lease expire na ho, aur tab tak callers use aazmate rehte hain. (Sach me crash hue process ka lease-expiry raasta yahan chalaya nahi gaya.)
In simple terms: Graceful raaste aasaan case hain.
Microservices ke mukhya fayde kya hain?
Independent deploy aur release (team doosron ko redeploy kiye bina apni service ship karti hai), fault isolation (ek service band hone se baaki chalti rehti hain), independent scaling (sirf vyast service ki zyada copies) aur team ownership (chhoti team ek service aur uske data ki maalik). Demo ne inme se do dikhaye: jobs-service band hone par applications-service chalti rahi, aur applications-service restart kiye bina naya jobs-service deploy hua.
In simple terms: Ginaiye, phir dikhaiye ki aap jaante hain har fayde ke saath ek shart judi hai.
Poison event dead-letter topic me surakshit hai. Kya kaam poora ho gaya?
Nahi. Kisi ko use dekhna, data (yahan missing candidate email) ya bug theek karna, aur event replay karna hoga - warna candidate ko kabhi alert nahi milega. Monitoring aur replay process ke bina dead-letter topic data khone ka bas dheema tareeka hai.
In simple terms: Operational poora-pan.
Project jis resilience stack par pahuncha, use kram se sankshep me bataiye.
Call par khud timeout; call ke aas-paas circuit breaker; breaker ke bahar retry jo sirf asthaayi errors retry kare, CallNotPermittedException nahi; aur sab kuch fail hone par fallback. Har jod ke baad teeno failure modes dobara naape gaye.
In simple terms: Chhota interview jawab.
Idempotent ka kya matlab hai, aur kaunse HTTP methods idempotent hain?
Koi operation idempotent hai agar use ek baar ya kai baar karne par aakhri haalat wahi rahe. HTTP ki paribhasha me GET, PUT aur DELETE idempotent hain aur POST nahi - par ye paribhasha ek contract hai jise handler ko implement karna padta hai. Chapter me candidate ke naam par application store karne wale PUT ko 3 requests mili aur 1 row bachi, jabki wahi timings par POST ne 3 rows chhodi.
In simple terms: Paribhasha aur naapa hua control.
Project ka har kadam ek safal warm-up search se kyun shuru hua?
Har configuration ko ek hi haalat se shuru karne ke liye: bana hua connection, aur - fallback aane par - lautne ke liye ek aakhri achha nateeja. Ye circuit breaker me ek darj safalta bhi gini gayi, jo ek wajah hai ki outage aur slow modes me pehli fail search ke attempts ke baad breaker khula. Aisi setup details naape numbers badalti hain, isliye unhe likhna chahiye.
In simple terms: Prayog ki saaf-safai.
Kafka me topic, partition, offset, producer aur consumer samjhaiye.
Topic ek naam wala log hai, jo partitions me banta hai. Producer ek record ek partition me jodta hai, jahan use agla offset milta hai - demo ke job-7 records partition 0 ke offsets 0, 2 aur 4 par gaye. Consumer ek partition ko kisi offset se padhta hai. Broker partitions store karta hai; chapter ne JVM ke andar ek broker chalaya, isliye replication run ka hissa nahi tha.
In simple terms: Naape gaye offsets se judi paribhashayein.
StripPrefix aur AddRequestHeader filters kya karte hain?
StripPrefix=1 forward karne se pehle path ka pehla hissa hata deta hai: /api/jobs/7 ki client call backend tak GET /jobs/7 bankar pahunchi. AddRequestHeader=X-Via, gateway aisa header jodta hai jo client ne bheja hi nahi; backend ne X-Via=gateway dekha. Filters sirf apne route par lagte hain - us filter ke bina wale route par backend ne X-Via=null dekha.
In simple terms: Har filter ka pehle/baad naapa hua.
API gateway kya hai aur microservices use kyun use karti hain?
Bahari clients ke liye single entry point. Clients gateway ko bulate hain, jo har request ko sahi service tak route karta hai aur raaste me authentication, headers aur rate limits jaise cross-cutting niyam lagata hai. Ye andar ki service addresses clients se chhupata hai aur edge policies ki ek jagah deta hai. Chapter me gateway par API-key check ne 401 diya jabki backend ko 0 hits mile.
In simple terms: Paribhasha aur naapa hua fayda.
Services ke beech communication ke liye Kafka kab galat tool hai?
Jab caller ko jawab turant chahiye, aur chhupe request-reply ki tarah - messaging ki saari jatilta milti hai aur intezaar phir bhi karna padta hai. Jab aap at-least-once delivery aur duplicates sambhal nahi sakte, ya broker cluster chala nahi sakte, tab bhi. Ek consumer aur kam volume ke liye saral tareeka chal sakta hai.
In simple terms: Santulit nazariya.
194+ more Spring Microservices questions inside
Start free to read the first 10 with model answers and take a voice mock interview. The full question bank comes with Pro.
Start free