<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nikhil Kamani</title>
    <description>The latest articles on DEV Community by Nikhil Kamani (@nikz11).</description>
    <link>https://dev.to/nikz11</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4016948%2F75c61da4-874b-4c6d-b812-e36a37e301ec.jpeg</url>
      <title>DEV Community: Nikhil Kamani</title>
      <link>https://dev.to/nikz11</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nikz11"/>
    <language>en</language>
    <item>
      <title>My AI Chatbot Started "Faking" Tool Calls in Plain Text. Here's Why.</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Sun, 16 Aug 2026 06:10:03 +0000</pubDate>
      <link>https://dev.to/nikz11/my-ai-chatbot-started-faking-tool-calls-in-plain-text-heres-why-5elc</link>
      <guid>https://dev.to/nikz11/my-ai-chatbot-started-faking-tool-calls-in-plain-text-heres-why-5elc</guid>
      <description>&lt;p&gt;I built a small AI "digital twin": a chatbot that answers questions about my background the way I would, and calls a tool to notify me the moment someone wants to get in touch. &lt;br&gt;
Stack is Groq's API running llama-3.3-70b-versatile, Gradio for the UI, deployed on Hugging Face Spaces.&lt;/p&gt;

&lt;p&gt;I skipped LangChain and any agent framework on purpose. I wanted to actually watch an agent decide when and how to use a tool, not have a framework make that decision invisible to me.&lt;/p&gt;

&lt;p&gt;That choice is what taught me the most, not about building a chatbot, but about how an LLM actually behaves once you hand it a tool and just tell it "use this when needed."&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The bug&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I gave the model a record_user_details tool: if a visitor wants to be contacted, the model calls it with their email, and I get a push notification. Simple enough.&lt;/p&gt;

&lt;p&gt;Except every so often, instead of triggering the tool, the model would just print this straight into the chat reply:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
&amp;lt;function=record_user_details&amp;gt;{"email": "someone@example.com", "notes": "wants to connect"}&amp;lt;/function&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Visible to the visitor, as plain text. And since it never actually went through the API's tool-call mechanism, my code never saw it. No notification. No record. The model was "calling" a function that, as far as my backend was concerned, didn't happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why it happens&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Llama 3.x models were trained on two different ways to represent a tool call: &lt;br&gt;
&lt;strong&gt;the structured tool_calls field an API returns and a text-based invocation syntax using special tags&lt;/strong&gt;. Depending on prompt shape and how the serving layer steers the model, it sometimes reaches for the second one instead of the first, especially under ambiguous instructions about when a tool should fire at all.&lt;/p&gt;

&lt;p&gt;This isn't a Groq-specific bug, it's a known quirk of the model itself. I only found this by staring at raw completions in my logs instead of trusting the SDK's parsed response, then cross-checking against the model card and a few GitHub issues describing the exact same symptom.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix (three layers, because one alone wasn't enough)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;temperature=0. Doesn't eliminate the behavior, but makes the model far more consistent about which format it reaches for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tightened the tool description. I was vague about when to call the tool. Being explicit about the trigger condition, and explicit that it should never be described in the reply text, cut down the ambiguous cases where the model improvised.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Defensive parsing. This is the one that actually matters for a real visitor. Even with the first two fixes, I don't fully control the model. So I wrapped the response handling to detect a malformed, text-only "call" and fail soft: a polite "could you rephrase that?" instead of leaking a raw function tag into someone's chat window.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What this taught me about agent behavior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model isn't "deciding" to call a tool the way the word "agent" makes it sound. It's predicting the next most likely tokens, and sometimes the most likely tokens look like a tool call without ever going through the real mechanism. &lt;br&gt;
A framework would have smoothed that over for me automatically. Hand-rolling it meant I actually saw, first-hand, how much less deterministic "agent behavior" is than the term implies.&lt;/p&gt;

&lt;p&gt;Try it: &lt;a href="https://huggingface.co/spaces/nik1988/digital-twin" rel="noopener noreferrer"&gt; https://huggingface.co/spaces/nik1988/digital-twin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Note: it's on a free Hugging Face Space, so it may have gone to sleep from inactivity. If it doesn't load right away, hit "Restart Space" and give it a few seconds to spin back up.)&lt;/p&gt;

&lt;p&gt;Curious about two things from anyone who's built something similar:&lt;/p&gt;

&lt;p&gt;If you were extending a digital-twin chatbot like this, what would you add next? &lt;br&gt;
I've been going back and forth on whether it's worth more tooling (calendar booking, resume Q&amp;amp;A grounded in a vector store) or keeping it deliberately minimal.&lt;/p&gt;

&lt;p&gt;Drop your ideas below, genuinely want to see what other people have tried with this.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>AI can write the code. It can't tell you why it's correct under load.</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Sat, 08 Aug 2026 04:09:25 +0000</pubDate>
      <link>https://dev.to/nikz11/ai-can-write-the-code-it-cant-tell-you-why-its-correct-under-load-1kh9</link>
      <guid>https://dev.to/nikz11/ai-can-write-the-code-it-cant-tell-you-why-its-correct-under-load-1kh9</guid>
      <description>&lt;p&gt;A junior developer asked me last week: "AI writes half my code now. Why does the interview process still grill me on HashMap internals and thread safety?"&lt;/p&gt;

&lt;p&gt;I've interviewed 300+ Java developers over 13 years. Here's what I told him.&lt;/p&gt;

&lt;p&gt;Ask any AI assistant to write a counter, a cache, or a payment method, and it'll hand you something that compiles, runs, and looks completely reasonable. It will also, quite often, hand you code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks fine. It passes every test you'd normally write. It will also silently lose updates the moment two threads call increment() at the same time — because volatile guarantees visibility, not atomicity, and count++ is three separate operations under the hood. AI doesn't know that this specific line is dangerous, because syntactically there's nothing wrong with it. It only becomes a bug under concurrent load, in production, weeks after it shipped.&lt;/p&gt;

&lt;p&gt;When I ask a candidate "walk me through what happens when two threads call this method at the same time," I'm not testing whether they can write a counter. I'm testing whether they can catch this exact bug in a code review — including one AI just generated for them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fundamentals didn't get less important. They got more important.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few years ago, the bottleneck was typing out correct code. Now AI removes most of that friction — which means the bottleneck has moved entirely to judgment: can you look at generated code and know whether it's actually safe?&lt;/p&gt;

&lt;p&gt;That skill doesn't come from prompting well. It comes from actually understanding what's happening underneath &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually changed in interviews&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI changed what junior developers are asked to produce day to day. It didn't change what interviewers are testing for. Every interview I run this year still comes back to the same core question: does this person understand memory, concurrency, and data structures well enough to catch the bug — or do they just know how to get an AI to write code that compiles?&lt;/p&gt;

&lt;p&gt;If anything, this makes fundamentals a bigger differentiator between candidates than they were five years ago, not a smaller one. Everyone can produce working-looking code now. Far fewer people can tell you why it's wrong.&lt;/p&gt;

&lt;p&gt;I put together everything I actually ask candidates into a guide — 700+ pages: Core Java, Concurrency, Spring Boot, Design Patterns, Coding Round Patterns.&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback or questions? Email me: &lt;a href="mailto:kamaninikhil71@gmail.com"&gt;kamaninikhil71@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>interview</category>
      <category>java</category>
    </item>
    <item>
      <title>12 Coding Pattern Scenario Questions That Expose Real Gaps</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Thu, 30 Jul 2026 02:52:14 +0000</pubDate>
      <link>https://dev.to/nikz11/12-coding-pattern-scenario-questions-that-expose-real-gaps-30cl</link>
      <guid>https://dev.to/nikz11/12-coding-pattern-scenario-questions-that-expose-real-gaps-30cl</guid>
      <description>

&lt;p&gt;I have 13 years of Java experience and have interviewed hundreds of developers at MNCs. Most candidates know the 14 major coding patterns by name. Fewer can look at a fresh problem and instantly know which one fits — that's the actual skill being tested. Here's the mapping.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Find if a sorted array has two numbers that sum to a target, without extra space → Two Pointers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the longest substring without repeating characters → Sliding Window&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Group a list of words into anagram sets → Hash Map / Frequency Counter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Answer many "sum between index i and j" queries efficiently, without recalculating each time → Prefix Sum&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find an element in a rotated sorted array in O(log n) → Binary Search and Variants&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if a string of brackets is balanced → Stack-Based Problems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the maximum sum of any contiguous subarray → Greedy / Kadane's Algorithm&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the shortest path between two nodes in an unweighted graph → Tree/Graph Traversal (BFS)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the maximum value of items that fit in a knapsack of limited capacity → Dynamic Programming (Pick / No-Pick)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the longest common subsequence between two strings → Dynamic Programming (Sequence Matching)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate all valid combinations of balanced parentheses → Backtracking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the Kth largest element in an unsorted array without fully sorting it → Quick Select&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;I put together a complete backend interview guide covering Core Java, Java 8-21, Multithreading, Spring Boot, Microservices, Design Patterns, and Coding Round Patterns.&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback or questions? Email me: &lt;a href="mailto:kamaninikhil71@gmail.com"&gt;kamaninikhil71@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bookmark this — which one do you always blank on when you're under pressure?&lt;/p&gt;

</description>
      <category>dsa</category>
      <category>interview</category>
      <category>coding</category>
    </item>
    <item>
      <title>What Actually Happens When the 201st User Hits Your Spring Boot App</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Sat, 25 Jul 2026 04:38:20 +0000</pubDate>
      <link>https://dev.to/nikz11/what-actually-happens-when-the-201st-user-hits-your-spring-boot-app-3mlk</link>
      <guid>https://dev.to/nikz11/what-actually-happens-when-the-201st-user-hits-your-spring-boot-app-3mlk</guid>
      <description>&lt;p&gt;The setup&lt;br&gt;
Your Spring Boot app runs on embedded Tomcat. By default, Tomcat has a pool of about 200 threads. Every incoming HTTP request grabs one thread from that pool, holds it for the entire duration of the request, and returns it when the response is sent.&lt;/p&gt;

&lt;p&gt;Your typical controller does something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/order/{id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;OrderView&lt;/span&gt; &lt;span class="nf"&gt;getOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathVariable&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fetch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// REST call — ~200ms waiting&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paymentClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// REST call — ~200ms waiting&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;shipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shippingClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// REST call — ~200ms waiting&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;combine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shipping&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three sequential network calls. About 600ms per request — and here's the key part: for almost all of those 600ms, the thread is doing nothing. It's just parked, waiting for other servers to reply.&lt;/p&gt;

&lt;p&gt;The 201st user&lt;br&gt;
200 users hit this endpoint at the same time. All 200 Tomcat threads are now holding a request, each one blocked, each one waiting on a slow downstream call.&lt;/p&gt;

&lt;p&gt;The 201st user arrives.&lt;/p&gt;

&lt;p&gt;There is no thread left to give them. Their request doesn't fail — it queues. It sits and waits for one of the 200 threads to finish and free up. Your server's CPU is nearly idle (everyone's just waiting on I/O), your memory is fine — and yet users are stuck in a line. &lt;strong&gt;This is thread pool exhaustion, and it's one of the most common ways a healthy-looking service falls over under load.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For years we solved this two painful ways: crank the pool size way up (each platform thread costs ~1MB of memory, so this doesn't scale far), or rewrite everything in reactive/WebFlux style (fast, but the code gets much harder to read and debug).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What virtual threads change&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A platform thread is a thin wrapper around a real OS thread — expensive, ~1MB, you can have a few thousand. A virtual thread is managed by the JVM instead of the OS. It costs a few hundred bytes, and you can have millions of them.&lt;/p&gt;

&lt;p&gt;The magic is what happens when a virtual thread blocks on I/O. Instead of sitting there holding an OS thread hostage, the JVM unmounts it — the virtual thread steps aside, the real OS thread is freed to go run someone else's work, and when the network reply finally comes back, the virtual thread gets re-mounted onto any free OS thread to continue.&lt;/p&gt;

&lt;p&gt;So during those three REST calls, the underlying OS thread isn't wasted waiting. It's off serving other requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Spring Boot 3.2+, you turn this on with a single line:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spring.threads.virtual.enabled=true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now every request runs on its own fresh virtual thread. There is no pool of 200 to exhaust. The 201st user — and the 20,000th — each get their own virtual thread, and the handful of real OS threads underneath stay busy instead of blocked. Same simple blocking code above. No WebFlux. No callback spaghetti.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The catch (this is the real interview follow-up)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Virtual threads only help when threads spend their time waiting — I/O-bound work. For CPU-bound work (heavy computation), there's nothing to unmount from, so they give no benefit over a normal pool sized to your cores.&lt;/p&gt;

&lt;p&gt;And one trap that bites people: if a virtual thread blocks inside a synchronised block, the JVM currently can't unmount it — it stays "pinned" to its OS thread for the whole block, and you lose the entire advantage. In code that runs on virtual threads, prefer ReentrantLock over synchronised for anything that wraps a blocking call.&lt;/p&gt;

&lt;p&gt;That's the full answer to "what happens to the 201st user" — the pool, the exhaustion, the unmount/re-mount, and the one line that changes it. If you can tell that story in an interview, you're already ahead of most candidates.&lt;/p&gt;

&lt;p&gt;I cover this and more (Core Java, Java 8 to 21, Multithreading, Spring Boot, Microservices, Design Patterns, Coding Round Patterns) in my guide.&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback or questions? Email me: &lt;a href="mailto:kamaninikhil71@gmail.com"&gt;kamaninikhil71@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ever been burned by thread pool exhaustion in production? What did you do before virtual threads existed?&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>concurrency</category>
      <category>interview</category>
    </item>
    <item>
      <title>2 Concurrency Traps That Look Thread-Safe But Aren't</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Mon, 20 Jul 2026 03:45:42 +0000</pubDate>
      <link>https://dev.to/nikz11/2-concurrency-traps-that-look-thread-safe-but-arent-6bh</link>
      <guid>https://dev.to/nikz11/2-concurrency-traps-that-look-thread-safe-but-arent-6bh</guid>
      <description>

&lt;p&gt;I have 13 years of Java experience and have interviewed hundreds of developers at MNCs. Both of these come up constantly in multithreading rounds — and both involve code that looks perfectly safe until you think about it for another 10 seconds.&lt;/p&gt;




&lt;h3&gt;
  
  
  Q1: Is this thread-safe?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Answer: No.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reason, in plain terms:&lt;/strong&gt; &lt;code&gt;volatile&lt;/code&gt; guarantees &lt;em&gt;visibility&lt;/em&gt; — every read and write goes straight to main memory, so all threads see the latest value immediately. It does &lt;strong&gt;not&lt;/strong&gt; guarantee &lt;em&gt;atomicity&lt;/em&gt;. &lt;code&gt;count++&lt;/code&gt; is actually three separate steps: read the value, add 1, write it back. &lt;code&gt;volatile&lt;/code&gt; makes each of those three steps visible to other threads, but it doesn't stop another thread from jumping in between them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread-1: reads count (0)
Thread-2: reads count (0)      &amp;lt;- interleaves here
Thread-1: writes count = 1
Thread-2: writes count = 1     &amp;lt;- overwrites Thread-1's update

Result: count = 1 (should be 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why a "thread-safe" counter silently loses updates under load, and it's almost impossible to catch in testing — it only shows up under real concurrent traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; use &lt;code&gt;AtomicInteger&lt;/code&gt;, which provides both visibility and atomicity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AtomicInteger&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AtomicInteger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;incrementAndGet&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Q2: Is this safe on a &lt;code&gt;ConcurrentHashMap&lt;/code&gt;?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ConcurrentHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ConcurrentHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsKey&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user1"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Answer: No.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reason:&lt;/strong&gt; every &lt;em&gt;individual&lt;/em&gt; operation on &lt;code&gt;ConcurrentHashMap&lt;/code&gt; is thread-safe — &lt;code&gt;containsKey()&lt;/code&gt; alone is safe, &lt;code&gt;put()&lt;/code&gt; alone is safe. But the sequence of the two together is not one atomic unit. Another thread can insert &lt;code&gt;"user1"&lt;/code&gt; in the gap between your &lt;code&gt;containsKey()&lt;/code&gt; check and your &lt;code&gt;put()&lt;/code&gt; call, and you'll silently overwrite it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; use the map's built-in atomic compound methods instead of check-then-act:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putIfAbsent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;                        &lt;span class="c1"&gt;// atomic check-and-put&lt;/span&gt;
&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// atomic get-modify-put&lt;/span&gt;
&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;merge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;Integer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;                   &lt;span class="c1"&gt;// atomic get-modify-put&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I cover this and more (Core Java, Java 8 to 21, Multithreading, Spring Boot, Microservices, Design Patterns, Coding Round Patterns) in my guide.&lt;/p&gt;

&lt;p&gt;Free sample: &lt;a href="https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, typos, or suggestions? Email me: &lt;a href="mailto:kamaninikhil71@gmail.com"&gt;kamaninikhil71@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which one would you have caught in a code review? Drop it in the comments.&lt;/p&gt;

</description>
      <category>java</category>
      <category>multithreading</category>
      <category>interview</category>
    </item>
    <item>
      <title>Circuit Breakers Come Up In Almost Every Microservices Interview — Here's The 3-State Flow</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Tue, 14 Jul 2026 03:13:23 +0000</pubDate>
      <link>https://dev.to/nikz11/circuit-breakers-come-up-in-almost-every-microservices-interview-heres-the-3-state-flow-3jn1</link>
      <guid>https://dev.to/nikz11/circuit-breakers-come-up-in-almost-every-microservices-interview-heres-the-3-state-flow-3jn1</guid>
      <description>

&lt;p&gt;I have 13 years of Java experience and have interviewed hundreds of developers at MNCs. "Explain circuit breaker state transitions" is one of the most common microservices questions I ask — most candidates can name the pattern but fumble the actual states.&lt;/p&gt;

&lt;p&gt;Here they are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwiuonu1ixrbguxb05q2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwiuonu1ixrbguxb05q2q.png" alt=" " width="798" height="189"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  1. CLOSED — Normal Operation
&lt;/h3&gt;

&lt;p&gt;All requests go through to the real service. The circuit breaker silently tracks successes and failures in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Moves to OPEN when:&lt;/strong&gt; the failure rate crosses a threshold — e.g. 50% of the last 10 calls failed.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. OPEN — Service Is Failing
&lt;/h3&gt;

&lt;p&gt;Rejects ALL requests immediately. Doesn't even call the service — just returns a fallback response instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Moves to HALF_OPEN when:&lt;/strong&gt; a wait duration elapses — e.g. after 60 seconds, to give the service a chance to recover.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. HALF_OPEN — Testing Recovery
&lt;/h3&gt;

&lt;p&gt;Allows a small number of test requests through — e.g. 3 calls. Everything else still gets the fallback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test calls succeed → back to CLOSED.&lt;/strong&gt; Test calls fail → back to OPEN.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Why it actually matters, not just theory:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Say Payment Service goes down.&lt;/p&gt;

&lt;p&gt;Without a circuit breaker: 100 users each wait 30 seconds for a timeout. Threads pile up waiting on a dead service. The failure cascades into your own system.&lt;/p&gt;

&lt;p&gt;With a circuit breaker: the first ~10 requests fail and the circuit OPENS. The next 90 requests fail instantly, no waiting. Users get "Payment down, try later" and the rest of the system stays responsive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The code (Spring Boot + Resilience4j):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"payment-service"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"paymentFallback"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;PaymentResult&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;paymentClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTotal&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Called when circuit is OPEN or the call fails&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PaymentResult&lt;/span&gt; &lt;span class="nf"&gt;paymentFallback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;failed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Try again later."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;resilience4j&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;circuitbreaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;payment-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;failure-rate-threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
        &lt;span class="na"&gt;wait-duration-in-open-state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;60s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The follow-up I always ask next:&lt;/strong&gt; how is this different from Retry? Retry helps with transient blips — a single dropped packet, a momentary glitch. Circuit breaker helps with sustained outages — there's no point retrying against a service that's been down for 2 minutes, you're just adding load to something already struggling.&lt;/p&gt;

&lt;p&gt;Other resilience patterns worth knowing alongside this: &lt;strong&gt;Timeout&lt;/strong&gt; (gives up waiting after a max duration), &lt;strong&gt;Bulkhead&lt;/strong&gt; (isolates thread pools so one failing service can't starve others), and &lt;strong&gt;Rate Limiter&lt;/strong&gt; (caps requests per second to protect a service).&lt;/p&gt;




&lt;p&gt;I cover this and more (Core Java, Java 8 to 21, Multithreading, Spring Boot, Microservices, Design Patterns, Coding Round Patterns) in my guide.&lt;/p&gt;

&lt;p&gt;Free sample: &lt;a href="https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, typos, or suggestions? Email me: &lt;a href="mailto:kamaninikhil71@gmail.com"&gt;kamaninikhil71@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which state trips people up most — OPEN or HALF_OPEN? Drop it in the comments.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>microservices</category>
      <category>interview</category>
    </item>
    <item>
      <title>12 Java Collections Scenario Questions That Expose Real Gaps</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Sat, 11 Jul 2026 04:42:26 +0000</pubDate>
      <link>https://dev.to/nikz11/12-java-collections-scenario-questions-that-expose-real-gaps-5d90</link>
      <guid>https://dev.to/nikz11/12-java-collections-scenario-questions-that-expose-real-gaps-5d90</guid>
      <description>&lt;p&gt;Most "explain HashMap" interview questions are dead now — anyone &lt;br&gt;
can look that up. What separates candidates today is scenario &lt;br&gt;
reasoning: given a real constraint, which collection do you reach &lt;br&gt;
for, and why not the obvious one?&lt;/p&gt;

&lt;p&gt;12 questions worth testing yourself on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You need an LRU cache that evicts the least recently used entry &lt;br&gt;
automatically when full. Which collection do you reach for?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A producer thread generates data faster than the consumer can &lt;br&gt;
process it, and the app is running out of memory. What do you &lt;br&gt;
change?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need the top 10 highest scores out of 1 million incoming &lt;br&gt;
values, without holding all 1 million in memory. How?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple threads read a config map constantly, but writes &lt;br&gt;
happen once a day. ConcurrentHashMap, synchronizedMap, or &lt;br&gt;
something else entirely?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You store a mutable object as a HashMap key, then modify one &lt;br&gt;
of its fields after inserting it. What breaks?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Every key in your HashMap somehow returns the same hashCode(). &lt;br&gt;
What happens to lookup performance, and why?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You remove an element from a List while iterating it with a &lt;br&gt;
for-each loop. What exception do you get — and why does it happen &lt;br&gt;
even in single-threaded code?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why does iterator.remove() avoid the exception in Q7, but &lt;br&gt;
list.remove() inside the same loop doesn't?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the real difference between a fail-fast and a fail-safe &lt;br&gt;
iterator — and where do ArrayList, HashMap, ConcurrentHashMap, and &lt;br&gt;
CopyOnWriteArrayList each fall?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need a Set that stays sorted at all times and supports &lt;br&gt;
range queries — "give me everything between X and Y." Which &lt;br&gt;
collection, and why not just sort a HashSet every time you need it?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A teammate says LinkedList is always faster for insertion than &lt;br&gt;
ArrayList. Is that actually true in production?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your CopyOnWriteArrayList is quietly driving up memory and GC &lt;br&gt;
pressure. Why — and when should you actually reach for it?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How many could you answer confidently without looking anything up?&lt;/p&gt;

&lt;p&gt;I've written out full answers with code and the reasoning behind &lt;br&gt;
each one in my guide, alongside Java 8-21, Multithreading, Spring &lt;br&gt;
Boot, Microservices, Design Patterns, and Coding Round Patterns.&lt;/p&gt;

&lt;p&gt;Free sample: &lt;a href="https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>interview</category>
      <category>career</category>
    </item>
    <item>
      <title>2 @Transactional Traps That Catch Even Senior Java Developers in interviews</title>
      <dc:creator>Nikhil Kamani</dc:creator>
      <pubDate>Wed, 08 Jul 2026 03:52:46 +0000</pubDate>
      <link>https://dev.to/nikz11/2-transactional-traps-that-catch-even-senior-java-developers-in-interviews-41eb</link>
      <guid>https://dev.to/nikz11/2-transactional-traps-that-catch-even-senior-java-developers-in-interviews-41eb</guid>
      <description>

&lt;p&gt;I have 13 years of Java experience. I have also interviewed hundreds of developers at MNCs.&lt;/p&gt;

&lt;p&gt;Two questions about &lt;code&gt;@Transactional&lt;/code&gt; that catch even senior developers. Try answering before you scroll down.&lt;/p&gt;




&lt;h3&gt;
  
  
  Q1: If a non-transactional method calls a &lt;code&gt;@Transactional&lt;/code&gt; method in the same class, does the transaction apply?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;placeOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;inventoryRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Answer: No.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reason, in plain terms:&lt;/strong&gt; when you add &lt;code&gt;@Transactional&lt;/code&gt;, Spring does not add the transaction logic inside your class. Instead, it creates a second object that sits in front of your class — think of it as a wrapper. Other classes that call &lt;code&gt;saveOrder()&lt;/code&gt; (through &lt;code&gt;@Autowired&lt;/code&gt;) actually call this wrapper first. The wrapper starts the transaction, then calls your real method, then commits or rolls back.&lt;/p&gt;

&lt;p&gt;This wrapper only exists &lt;em&gt;outside&lt;/em&gt; your class. So when your own code calls &lt;code&gt;this.saveOrder(order)&lt;/code&gt;, it skips the wrapper completely and goes straight to the real method. No wrapper means no transaction logic. No rollback if &lt;code&gt;inventoryRepository.update()&lt;/code&gt; fails.&lt;/p&gt;

&lt;p&gt;This bug never shows up in tests. It only shows up in production, when a failure leaves your data half-updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; call the method from a different class, or inject the wrapper of your own class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// this is the wrapper, not the raw object&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;placeOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// now it goes through the wrapper&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;inventoryRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Q2: Does &lt;code&gt;@Transactional&lt;/code&gt; roll back on every exception?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processRefund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;RefundException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;paymentRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;markRefunded&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;externalRefundService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// throws RefundException&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Answer: No.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reason:&lt;/strong&gt; by default, &lt;code&gt;@Transactional&lt;/code&gt; only rolls back on unchecked exceptions (&lt;code&gt;RuntimeException&lt;/code&gt; and its subclasses). &lt;code&gt;RefundException&lt;/code&gt; above is a checked exception. So if it is thrown, Spring lets the transaction &lt;strong&gt;commit anyway&lt;/strong&gt; — including the &lt;code&gt;markRefunded&lt;/code&gt; write that happened right before the failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; tell Spring to roll back on any exception, not just unchecked ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rollbackFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processRefund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;RefundException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;paymentRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;markRefunded&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;externalRefundService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I cover topics like this in more depth in my guide — Core Java, Java 8 to 21, Multithreading, Spring Boot, Microservices, Design Patterns, and Coding Round Patterns.&lt;/p&gt;

&lt;p&gt;Free sample: &lt;a href="https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1u3PQbTY1gLn34UmWG7Cxx4cmdibD2dvU/view?usp=sharing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://kamaninikhil.gumroad.com/l/java-interview-guide" rel="noopener noreferrer"&gt;https://kamaninikhil.gumroad.com/l/java-interview-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Got either one right? Drop it in the comments.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>interview</category>
      <category>career</category>
    </item>
  </channel>
</rss>
