<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Himanshu Singour on Medium]]></title>
        <description><![CDATA[Stories by Himanshu Singour on Medium]]></description>
        <link>https://medium.com/@himanshusingour7?source=rss-81912d0c6ef8------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*EjfWFU_lEK2ZCyhYJ3EF9w.jpeg</url>
            <title>Stories by Himanshu Singour on Medium</title>
            <link>https://medium.com/@himanshusingour7?source=rss-81912d0c6ef8------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 04 Nov 2026 19:17:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@himanshusingour7/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Software Engineering Is Dead.]]></title>
            <link>https://medium.com/@himanshusingour7/software-engineering-is-dead-a5bfa59a0704?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/a5bfa59a0704</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[careers]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Tue, 03 Nov 2026 15:53:20 GMT</pubDate>
            <atom:updated>2026-11-03T15:53:20.154Z</atom:updated>
            <content:encoded><![CDATA[<h4>Every few years someone writes the obituary. Here’s why the patient keeps getting up.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LY8eQ17_zFnG8Wdp_dX_dw.png" /></figure><p>Scroll LinkedIn for five minutes and you’ll see it.</p><p><em>“Built a full app in one weekend. Zero code.”</em></p><p><em>“AI agents will replace developers by next year.”</em></p><p><em>“Software engineering is dead.”</em></p><p>And in the comments, the same worried question again and again:</p><blockquote><em>Should I even bother learning to code anymore?</em></blockquote><p>If you’re a student grinding DSA at 1 AM, or a developer a few years into your career, that hits hard. I get it.</p><p>So let’s skip the hype and the panic. Let’s look at three things instead: <strong>history, data, and the actual work.</strong></p><h3>1. We’ve heard this prediction before. Many times.</h3><p>“Programmers will soon be useless” is not a new idea. It’s older than most of our parents.</p><ul><li><strong>1954:</strong> A report on FORTRAN said it would “virtually eliminate coding and debugging.”</li><li><strong>1959:</strong> COBOL came with English-like code, so managers could “write programs themselves.”</li><li><strong>1980s:</strong> CASE tools promised software without programmers.</li><li><strong>2000s:</strong> “All coding jobs are moving offshore.”</li><li><strong>2010s:</strong> No-code tools would make developers optional.</li><li><strong>Now:</strong> AI.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*voDP0sNyudDOkchi8pt_VA.png" /></figure><p>Here’s the twist. <strong>Every one of those tools actually worked.</strong></p><p>And after every wave, the world needed <em>more</em> programmers, not fewer. When building software gets cheaper, people just want more software.</p><blockquote><em>Every tool that made coding easier ended up creating more coding jobs, not fewer.</em></blockquote><h3>2. What the 2026 data actually says</h3><p>Opinions are loud. Numbers are quiet. So let’s listen to the quiet ones.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Xj1gLxQVuwHWRDc6GoVRJw.png" /></figure><h4>The good news</h4><ul><li><strong>67,000+ open software engineering roles</strong>, up about 30% this year and the highest in three years (TrueUp, via Business Insider).</li><li>Top tech companies are hiring <strong>~20% more engineers</strong> than last year (The Pragmatic Engineer, May 2026).</li><li>Many big companies have <strong>50–100% more AI engineering jobs</strong> than a year ago.</li></ul><h4>The honest news</h4><ul><li>Layoffs are real: over <strong>52,000 tech job cuts</strong> in Q1 2026 (Challenger, Gray &amp; Christmas).</li><li>Jobs asking for <strong>5+ years of experience</strong> went from 37% to 42% (Indeed). Freshers have it tougher.</li></ul><p>So the real picture is this:</p><blockquote><em>The profession is growing. The entry bar has gone up. That’s a skill problem, and skill problems can be solved.</em></blockquote><h3>3. Writing code was never the whole job</h3><p>This is what most “engineering is dead” posts miss.</p><p>Typing code is just <em>one step</em>. Here’s how a real feature gets built:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x27AWsbu2Rhpg3muty9fqg.png" /></figure><p>The <strong>green box</strong> is where AI shines. Boilerplate, small functions, quick tests. It’s genuinely fast there.</p><p>But look at everything else. Someone still has to:</p><ul><li>Figure out what the customer <em>actually</em> wants</li><li>Decide how the system should be designed</li><li>Catch the edge case the AI quietly skipped</li><li>Fix production when it breaks at 2 AM</li></ul><p>That someone is an engineer.</p><h3>4. A tale of two developers</h3><p>Imagine two developers joining the same company on the same day.</p><h4>Developer A: “AI does it all”</h4><p>Copies whatever AI gives. Closes tickets fast. Looks great for three months.</p><p>Then a payment bug appears. It only happens when two requests hit at the same millisecond. AI suggests five fixes. None work.</p><p>Developer A is stuck, because they never understood the code in the first place.</p><h4>Developer B: “AI helps, I decide”</h4><p>Uses AI every day too. But reads every line, asks questions, and pushes back.</p><p>Sees the same bug and thinks: <em>“This looks like a race condition.”</em> Adds a lock, writes a test, done.</p><p>Same tool. Very different result.</p><blockquote><em>AI doesn’t replace engineers. It amplifies whatever is already inside them.</em></blockquote><h3>5. So what should you do?</h3><p>No need for a dramatic career switch. Just get sharper at the basics.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z_CtFcxtBmH8rJQpgHc1tQ.png" /></figure><ol><li><strong>Master the fundamentals.</strong> DSA, OS, networking, databases. This is what lets you judge if AI’s code is good or dangerous.</li><li><strong>Build real projects.</strong> Pick things slightly too hard for you. Read other people’s code too.</li><li><strong>Use AI, but stay the driver.</strong> Treat it like a fast junior teammate: helpful, often right, never accountable.</li><li><strong>Learn system design early.</strong> It’s exactly where freshers can stand out.</li><li><strong>Practice thinking out loud.</strong> Interviews now test how you reason, not just your final answer.</li></ol><h3>The bottom line</h3><p>Software engineering isn’t dying.</p><p>It’s dropping its most boring, repetitive layer and asking more from the people who stay.</p><p>It happened with compilers. With the internet. With the cloud. It’s happening again.</p><p>The winners won’t be the fastest typists. They’ll be the ones who <strong>understand problems, think in systems, and use AI as a tool</strong>.</p><blockquote><em>The door isn’t closing. It just has a new lock. And you can learn to open it.</em></blockquote><h3>Tools to help you prepare</h3><p>Knowing what to learn is one thing. Having the right place to practise it is another. These three platforms map directly to the plan above: learn, track, and rehearse.</p><p><em>A quick note for transparency: I built these platforms. I’m sharing them because they were made for exactly the problem this article is about.</em></p><h4>1. AlgorithmXlr8: learn system design and DSA the structured way</h4><p><a href="https://algorithmxlr8.io">algorithmxlr8.io</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eKTP4n9xrGhHedafOEvmPw.png" /></figure><p>A one-stop learning platform for engineers preparing for software engineering interviews.</p><ul><li><strong>High Level Design:</strong> how real scalable systems are built, taught in an interview context with no skippable topics</li><li><strong>Low Level Design:</strong> class diagrams, relationships, design principles and API-level components</li><li><strong>System Design Scenarios:</strong> real cross-questioning of the kind that comes up in most interviews</li><li><strong>DSA patterns and core concepts</strong>, plus a weekly engineering newsletter with system design stories</li></ul><h4>2. CodEyes: all your engineering stats in one profile</h4><p><a href="https://codeyes.in">codeyes.in</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0rYm4BD-kdPd8w7EuEYRuA.png" /></figure><p>Your progress is usually scattered across half a dozen platforms. CodEyes brings it together.</p><ul><li>Connects <strong>LeetCode, Codeforces, CodeChef, GitHub, Medium and Substack</strong> in one free profile</li><li>Shows total questions solved, active days, streaks, contest ratings and a submission heatmap</li><li>Contest tracker and leaderboard to keep you consistent</li><li>A clean public link you can add to your resume or share with recruiters</li></ul><h4>3. InterviewXlr8: your AI interviewer for every round</h4><p><a href="https://interviewxlr8.io">interviewxlr8.io</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tSNV9VTY3OQ8kwCFeQvJ_A.png" /></figure><p>The best way to get better at interviews is to give more of them. InterviewXlr8 lets you do that without waiting for the real thing.</p><ul><li>An AI interviewer that talks to you, asks follow-up questions and scores you like a real panel</li><li>Live evaluation of the key points you cover and how clearly you explain them</li><li>Mock rounds for coding and DSA, system design and SQL</li><li>Ideal for placements, job switches or your very first interview, starting at ₹199</li></ul><p><strong>Learn on AlgorithmXlr8. Track your growth on CodEyes. Rehearse on InterviewXlr8.</strong></p><p>That combination still gets people hired, in the AI era or any other.</p><h3>Remember this. Mark my words.</h3><h3>You will still need DSA. You will still need system design. You will still need every fundamental we have been learning all these years.</h3><p><em>If this article helped, share it with someone who has been worrying about the future of tech. They will probably appreciate it.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a5bfa59a0704" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Become a Great AI Engineer]]></title>
            <link>https://medium.com/@himanshusingour7/how-to-become-a-great-ai-engineer-00c4f7c70a8f?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/00c4f7c70a8f</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[career-advice]]></category>
            <category><![CDATA[ai-engineering]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Thu, 29 Oct 2026 17:54:52 GMT</pubDate>
            <atom:updated>2026-10-29T17:54:52.897Z</atom:updated>
            <content:encoded><![CDATA[<p>Most people learn AI backwards. Here are 20 steps in the right order with a lesson for every single one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mNc_OTOFN3A47IIBvAj0tg.png" /></figure><p>Hi, I am Himanshu.</p><p>I worked as a Senior Software Engineer. Today I work as a Senior AI Engineer.</p><p>I learned AI engineering in 7 months. Since then I have built a lot of AI agents, and many of them now do real work for me every single day.</p><p>Right now I am working on something that would have sounded crazy to me a year ago. I am training my own model on a standalone server sitting in my home.</p><p>My first real AI project started with a simple question from my dad. ChatGPT gave him a confident but wrong answer about our electricity bill. So I built my first RAG system that could read our own documents and answer correctly. I wrote about it <a href="https://medium.com/@himanshusingour7/i-built-my-first-rag-system-because-my-dad-asked-one-simple-question-16c6e3e115cd">here</a>.</p><p>Now I share what I learn with other engineers.</p><p>Almost every week I get a message on Instagram that looks like this.</p><blockquote><em>“Bhaiya I have done a LangChain course. I made a chatbot. But I am getting rejected in every AI interview. What am I doing wrong?”</em></blockquote><p>The person is usually not weak. Most of them are good developers. They work hard. They watch every new video.</p><p>So I ask them three small questions.</p><p>What does an embedding actually store?<br>Your chatbot has the right document. Why does it still give a wrong answer?<br>You changed your prompt. How do you know the new one is better?</p><p>Most of the time the reply is the same.</p><blockquote><em>“I know how to use the tools. I don’t know what is happening inside.”</em></blockquote><p>That line stayed with me. Because I made the same mistake when I started. I jumped to the shiny things first. I copied code that worked and felt good about it. Then the first time something broke I had no idea where to even look.</p><p>The problem was never hard work. The problem was the order.</p><p>When I sat down to build the AI Engineering track on <a href="https://algorithmxlr8.io/ai/engineering/home">AlgorithmXlr8</a> I spent most of my time on one question. What should a person learn first and what should come later?</p><p>This article is the answer. 20 steps in simple words. For every step I have added a lesson link so you can start today.</p><h3>First, what does an AI engineer do?</h3><p>An AI engineer does not invent new models. That is research work.</p><p>An AI engineer takes a model that already exists and builds a useful product with it. You connect it to data. You connect it to tools. You make sure it gives correct answers. You make it fast and cheap. Then you ship it.</p><p>Simple way to remember it. A researcher builds the engine. An AI engineer builds the car.</p><p>So you need two things. Good software skills and a clear idea of how models work. Here is the full path.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ISQDWx-96DWNzRSHVXZ7Sw.png" /></figure><h3>Phase 0: The basics</h3><h4>Step 1. DSA and system design</h4><p>I know you want to start with AI. But most AI engineer interviews still have a coding round and a system design round. And every AI product is first a normal software product. It has APIs, a database and users who don’t like waiting.</p><p>If you already work as a developer just revise and move on. If you are in college please don’t skip this.</p><p>Read: <a href="https://algorithmxlr8.io/dsa-patterns">DSA Patterns</a> and <a href="https://algorithmxlr8.io/hld">High Level Design</a></p><h3>Phase 1: Math and data</h3><h4>Step 2. Stats, probability and linear algebra</h4><p>Don’t be scared of this. You only need the basics. What is a vector. What is a dot product. What does probability mean. That’s it. Embeddings and attention are built on these ideas.</p><p>Give it two or three weeks. Don’t sit on math for six months.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/math-statistics/linear-algebra/scalars-vectors-matrices">Scalars, Vectors and Matrices</a></p><h4>Step 3. NumPy and Pandas</h4><p>Models work with numbers in arrays. Data comes in big tables. NumPy handles arrays. Pandas handles tables. You will use both every day.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/numpy-pandas-ml/module-1-numpy-fundamentals/introduction-to-numpy">Introduction to NumPy</a></p><h4>Step 4. Cleaning and plotting data</h4><p>Real data is messy. Empty values. Repeated rows. Wrong formats. If you feed bad data to a model you get bad answers. Learn to clean data and draw simple charts so you can see what is going on.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/data-visualization/module-1-data-cleaning/introduction-to-data-cleaning">Introduction to Data Cleaning</a></p><h3>Phase 2: Build and learn how models learn</h3><h4>Step 5. FastAPI</h4><p>A model inside a notebook helps nobody. FastAPI lets you turn your code into an API that an app can call. Learn it early. After this every project you make can be used by real people.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/fastapi/introduction/what-is-fastapi">What is FastAPI?</a></p><h4>Step 6. Machine learning basics</h4><p>Regression. Decision trees. Clustering. Overfitting. These old ideas still matter. They teach you why models fail and how to test them. Many real problems are still solved with simple models.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/classical-ml/introduction-to-machine-learning/what-is-machine-learning">What is Machine Learning?</a></p><h4>Step 7. Deep learning basics</h4><p>Neural networks. How they learn. And then transformers, the idea behind every big AI model today. After this step words like tokens and context window will finally make sense.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/deep-learning/introduction-to-deep-learning/what-is-deep-learning">What is Deep Learning?</a></p><h4>Step 8. PyTorch</h4><p>Now write it yourself. Train one small model from start to end in PyTorch. Once you do this, AI stops feeling like magic.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/pytorch/module-1-pytorch-fundamentals/introduction-to-pytorch">Introduction to PyTorch</a></p><h3>Phase 3: Working with LLMs</h3><p>This is where most people start. See how it is step 9 here. When you reach this point with strong basics you will learn it very fast.</p><h4>Step 9. Prompting and model APIs</h4><p>A good prompt is just clear instructions. Tell the model what to do. Give it the right information. Show an example. Ask for a fixed output format. Also learn how to call model APIs properly.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/prompting-apis/introduction-to-prompt-engineering/what-is-prompt-engineering">What is Prompt Engineering?</a></p><h4>Step 10. RAG and vector search</h4><p>If you go deep on only one topic, pick this one. It comes up in almost every AI interview I hear about.</p><p>RAG means two things. First find the right information. Then give it to the model so it can answer. That’s all.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yOqenu4d9kVeKpPv8b8MzA.png" /></figure><p>One thing I learned the hard way. When a RAG chatbot gives a wrong answer, the model is usually not the problem. The search gave it the wrong pages. Always check the search part first.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/rag-vector-search/rag-fundamentals/what-is-rag">What is RAG?</a></p><h4>Step 11. Fine-tuning</h4><p>Fine-tuning means training an existing model a little more on your own data. Learn it. But don’t use it first. Most problems get fixed with a better prompt or better search. Fine-tune only when nothing else works.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/fine-tuning/introduction-to-fine-tuning/what-is-fine-tuning">What is Fine-Tuning?</a></p><h4>Step 12. MCP</h4><p>MCP is a standard way to connect an AI model to tools and data. Think of it like a USB port for AI. One plug that works with many tools. It is becoming a must-know topic.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/mcp/introduction-to-mcp/what-is-mcp">What is MCP?</a></p><h4>Step 13. Hugging Face</h4><p>Hugging Face is where open models and datasets live. When you want to run your own model instead of using an API, you come here.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/huggingface/module-1-hugging-face-fundamentals/introduction-to-hugging-face">Introduction to Hugging Face</a></p><h3>Phase 4: Agents</h3><h4>Step 14. Agents and tool calling</h4><p>An agent is an AI model that works in a loop. It thinks. It uses a tool. It checks the result. Then it decides if it is done or needs one more round.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H4tQUL5OCsqZSiSI5nY-Og.png" /></figure><p>Also learn when not to use an agent. Many times a simple script is enough.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/agent-patterns/agent-fundamentals/what-is-an-agent">What is an Agent?</a></p><h4>Step 15. LangChain and other frameworks</h4><p>Now is the right time for LangChain. You already know what it does behind the scenes. So when something breaks you will know how to fix it.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/orchestration-frameworks/orchestration-fundamentals/what-is-orchestration">What is Orchestration?</a></p><h4>Step 16. Build your own projects</h4><p>Watching is not learning. Building is. Make your own small chatbot client. Your own vector database. Your own RAG system. These projects teach more than any certificate and they look great on a resume.</p><p>Project: <a href="https://algorithmxlr8.io/ai/engineering/home/ai-project/build-your-own-rag-system">Build Your Own RAG System</a></p><h4>Step 17. LangGraph</h4><p>For bigger agents that need many steps, retries or a human to approve something in the middle. LangGraph lets you draw your agent like a flowchart and run it.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/langgraph/langgraph-fundamentals/what-is-langgraph">What is LangGraph?</a></p><p>Want to go deeper on agents? There is a full separate agent course too. Start here: <a href="https://algorithmxlr8.io/ai/engineering/home/ai-agent-development/aad-module-1-introduction-to-ai-agents/aad-what-is-an-ai-agent">What Is an AI Agent?</a> Full course: <a href="https://algorithmxlr8.io/ai/engineering/home/ai-agent-development">AI Agent Development</a></p><h3>Phase 5: Production</h3><p>This is the part that makes you an engineer and not just a demo builder.</p><h4>Step 18. Deployment</h4><p>A demo works for one person. A real product works for thousands of people at the same time without a huge bill. Learn how to serve models, cache answers and track cost.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/deployment-llmops/model-serving/batch-inference">Batch Inference</a></p><h4>Step 19. Evaluation</h4><p>How do you know your AI is giving good answers? You test it. Make a set of questions with correct answers and check your system against it every time you change something.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/evaluation-safety/llm-evaluation-fundamentals/why-evaluation-matters">Why Evaluation Matters</a></p><h4>Step 20. Security</h4><p>People will try to trick your AI. They will try to make it leak data or do things it should not. When your AI can send emails or touch a database, security is a must.</p><p>Lesson: <a href="https://algorithmxlr8.io/ai/engineering/home/security/authentication-authorization/authentication">Authentication</a></p><h3>What not to learn first</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a00ahV3pSzNJdV9KFzDEHw.png" /></figure><p><strong>Don’t start with LangChain.</strong> Understand the basics first.</p><p><strong>Don’t try to train your own big model.</strong> No company expects that from you.</p><p><strong>Don’t study only math for months.</strong> Learn a little and start building.</p><p><strong>Don’t fine-tune before fixing your search.</strong> It costs more and usually fixes nothing.</p><p><strong>Don’t chase every new model launch.</strong> Names change every week. Basics don’t.</p><p><strong>Don’t collect certificates.</strong> Build projects.</p><h3>How long will it take?</h3><p>If you give around two hours a day, this is a normal pace. It is very close to how I did it myself in 7 months.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0ESfhgqYX3_OT_p4oX3dwA.png" /></figure><p>Some people will be faster. Some will be slower. Both are fine. Going in the right direction matters more than going fast.</p><h3>Last thing</h3><p>Remember that message? “I know how to use the tools. I don’t know what is happening inside.”</p><p>Tools will change every year. New frameworks will come. New models will come. But if you know what is happening inside, you can learn any new tool in a weekend. That is what makes someone really good at AI engineering.</p><p>The full roadmap with every step is here: <a href="https://algorithmxlr8.io/ai/engineering/home">algorithmxlr8.io/ai/engineering/home</a>. Every step has a lesson so you can try it first. The full AI agent course is here: <a href="https://algorithmxlr8.io/ai/engineering/home/ai-agent-development">AI Agent Development</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E0pec-x5wvKXqFzCf5IEMg.png" /></figure><p>If this helped you, save it and share it with one friend who is stuck watching tutorials. And tell me in the comments which step you are on. I read every comment.</p><p>Himanshu</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=00c4f7c70a8f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Is DSA Still Needed in the AI Era?]]></title>
            <link>https://medium.com/@himanshusingour7/is-dsa-still-needed-in-the-ai-era-9c3c34e43bd9?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/9c3c34e43bd9</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[sad]]></category>
            <category><![CDATA[career-advice]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Wed, 14 Oct 2026 14:35:16 GMT</pubDate>
            <atom:updated>2026-10-14T14:35:16.152Z</atom:updated>
            <content:encoded><![CDATA[<h4>Everyone is saying DSA is dead. I believed it too. Then one night in production taught me otherwise.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DalpaJbp7FeriA4b2lINcA.png" /></figure><p>Let me be very honest with you from the start.</p><p>Six months back I had stopped doing DSA completely. My LeetCode streak was dead. My notebook of graph problems was lying somewhere under my bed. Why would I waste time on linked lists when Copilot and ChatGPT and Claude can write the full function in ten seconds?</p><p>Every second post on LinkedIn was saying the same thing. “DSA is useless now.” “Companies will stop asking it.” “Just learn prompting yaar.”</p><p>I agreed with all of it. I was shipping features faster than ever. My manager was happy. I felt like a 10x developer.</p><p>Then came that one Thursday night.</p><h3>The night everything broke</h3><p>I am Himanshu. I work as a backend developer at a small startup. We handle orders for local sellers.</p><p>That week I got a simple task. Find duplicate orders before sending them to the payment system. Same customer, same product, same amount within a few minutes means it is probably a duplicate.</p><p>I opened my AI tool and typed the requirement. Within seconds I had clean code. Proper variable names. Comments also. I tested it on 500 sample orders from staging. Worked perfectly. Raised the PR. Got approved. Deployed on Thursday evening.</p><p>At 2:47 AM my phone started ringing.</p><p>The order API was timing out. Sellers were complaining. Payments were stuck. My manager was on the call and his voice was not very friendly.</p><p>I opened the code again with half sleepy eyes. And there it was. Sitting quietly inside that beautiful AI code.</p><p><strong>A loop inside a loop.</strong></p><p>For every order it was checking every other order. On 500 rows that is around 2.5 lakh comparisons. Nothing. Your laptop does it before you blink.</p><p>But production had 2 lakh orders that day.</p><p>2 lakh multiplied by 2 lakh is <strong>40 billion comparisons</strong>.</p><p>No server in this world is going to finish that before a seller in Indore loses his patience.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6lpFuS1DPDgbSFBPOWKRJw.png" /></figure><p><em>The red line is what AI gave me. The green line is what I should have asked for.</em></p><h3>The fix took 10 minutes. Knowing the fix took 2 years.</h3><p>I didn’t ask AI for help this time. I just knew.</p><p>Make a key from customer id plus product id plus amount. Put it in a HashSet. While going through the orders check if the key is already there. If yes it is a duplicate. If no add it and move ahead.</p><p>One loop. O(n). 2 lakh operations instead of 40 billion.</p><p>Deployed at 3:20 AM. API came back to normal in two minutes.</p><p>Sitting there at 3:30 AM with cold chai I realised something which changed my whole thinking.</p><p><strong>AI didn’t make a mistake. AI gave me exactly what I asked for.</strong> I asked for code that finds duplicates. It found duplicates. It never knew my table would have 2 lakh rows. It never knew the API had a 30 second timeout. That context was in my head. Not in the prompt.</p><p>And the only reason I could fix it in ten minutes was those boring evenings in college where I solved “Two Sum” with a HashMap and felt like a genius.</p><h3>What AI really can’t do (yet)</h3><p>After that night I started noticing these gaps everywhere. Here are the ones I see almost every week.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Rz4rzyIXUIE4Rzjrs-qb2g.png" /></figure><p><strong>1. AI doesn’t know your scale.</strong></p><p>It writes code for the example you gave. Your production data is 1000 times bigger. Only you know that. And only DSA tells you what happens when n grows.</p><p><strong>2. AI can’t judge its own output.</strong></p><p>It will give you an O(n²) solution with the same confidence as an O(n) solution. Both look clean. Both pass small tests. If you can’t read complexity you can’t tell which one will kill your server.</p><p><strong>3. AI doesn’t debug your 3 AM problem.</strong></p><p>When things break in production you don’t have time to paste 15 files and explain everything. You need to look at code and feel where the problem is. That feeling comes from practice.</p><p><strong>4. AI can’t sit in your interview.</strong></p><p>Most product companies in India still do live DSA rounds. Many have moved to in person or proctored rounds because of AI cheating. A friend of mine got rejected from a good company last month. He could build full apps with AI. He couldn’t explain why he used a list instead of a set.</p><p><strong>5. AI can’t defend your design in a meeting.</strong></p><p>When your senior asks “why not a heap here” you can’t say “ChatGPT told me”. You need to know the tradeoff yourself.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Bz8eKwjId2fNXRGiserYVQ.png" /></figure><p><em>The third box is where your salary comes from.</em></p><h3>So is DSA still needed?</h3><p>Yes. But not in the way we were taught.</p><p>You don’t need to mug up 500 LeetCode problems anymore. That era is going away. AI can recall syntax better than any of us.</p><p>What you need is the <strong>thinking</strong> behind DSA.</p><ul><li>Looking at code and knowing its time complexity in five seconds</li><li>Knowing when to use a HashMap vs a Heap vs a Tree vs a Graph</li><li>Smelling a nested loop on large data from far away</li><li>Breaking a big messy problem into small pieces before you even open the AI chat</li></ul><p>Think of it like this. AI is a very fast car. DSA is knowing how to drive. <strong>A Ferrari with a person who can’t drive is not fast. It is just dangerous.</strong></p><h3>My new routine</h3><p>After that night I made a small change. Nothing crazy.</p><ul><li><strong>30 minutes daily.</strong> One or two problems. Only patterns. Sliding window, two pointers, hashing, BFS and DFS, heaps, DP basics.</li><li><strong>Every AI generated function gets one question from me.</strong> What is the time complexity and what happens at 1 lakh rows?</li><li><strong>Solve first, then check with AI.</strong> Not the other way around.</li></ul><p>Within three months my code reviews became sharper. I caught two more O(n²) issues in other people’s PRs before they reached production. My manager noticed. That is the kind of thing that shows up in appraisals.</p><h3>Final words</h3><p>AI is doing 99% of the typing now. That is true and I am not fighting it. I use AI every single day.</p><p><strong>But the remaining 1% is judgement. And judgement is the part they pay you for.</strong></p><p>That 1% is what woke me up at 2:47 AM. And that 1% is what let me go back to sleep at 3:30.</p><p><strong>So no bhai. DSA is not dead.</strong></p><p><strong>It just stopped being about writing code. Now it is about knowing when the code is wrong.</strong></p><h3>Where I practice now</h3><p>After this story many friends asked me one thing. Bhai where do you practice? So I built two things for exactly this problem.</p><p><strong>1. </strong><a href="https://algorithmxlr8.io"><strong>AlgorithmXlr8.io</strong></a></p><p>This is everything I wish I had when I was preparing. DSA patterns explained with real interview context. High Level Design and Low Level Design without skippable topics. Real system design scenarios that come up in 90% of interviews. One subscription and everything is open. No hidden paywalls.</p><ul><li>Learn DSA by patterns, not by mugging 500 problems</li><li>HLD and LLD in one place, built for interviews</li><li>Scenario based cross questioning like a real interviewer</li><li>Weekly engineering newsletter with system design stories</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CBmmkJGCqBYdq1H3RdrbDg.png" /></figure><p><strong>2. </strong><a href="https://codeyes.in"><strong>CodEyes.in</strong></a></p><p>Once you start practising you want to see your growth. CodEyes connects LeetCode, Codeforces, CodeChef, GitHub, Medium and Substack into one profile. Your streak, your contest rating and your submission heatmap. All in one link.</p><ul><li>One public profile link you can put on your resume</li><li>Track your daily streak and contest rating across platforms</li><li>Contest tracker so you never miss a contest</li><li>Get your coding profile roasted for honest feedback</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WEj6Wfwq1TKQP1GM4ZMqOA.png" /></figure><p><strong>Learn on AlgorithmXlr8. Track on CodEyes. That is the full loop.</strong></p><p><em>If this hit home for you, give it a clap and share it with that one friend who says “DSA is useless now”. Tell me in the comments. Has AI code ever broken something for you in production?</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9c3c34e43bd9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Every Frontend Architecture Pattern]]></title>
            <link>https://medium.com/@himanshusingour7/every-frontend-architecture-pattern-340d16d9e049?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/340d16d9e049</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[frontend-development]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Thu, 08 Oct 2026 06:47:45 GMT</pubDate>
            <atom:updated>2026-10-08T06:47:45.623Z</atom:updated>
            <content:encoded><![CDATA[<h4>A simple guide from MVC to Micro Frontends</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2ftH5z3-0-F6NrO1Q-mNmw.png" /></figure><p>When I started my career as a frontend developer I thought architecture was something only senior people talk about in long meetings. I used to think my job was to make the button blue and make the API call work. That is it.</p><p>Then one day I joined a project where a single React file had 3000 lines. Nobody knew where the state was coming from. A small change in the header was breaking the checkout page. That day I understood why architecture matters.</p><p>In this article I will explain every major frontend architecture pattern I have seen in real projects. I will keep it simple. I will tell you what the pattern is and when you should use it. I will also tell you when you should not use it because that part is equally important.</p><p>So grab your chai and let us start.</p><h3>First what do we even mean by frontend architecture?</h3><p>Frontend architecture is just the answer to three simple questions.</p><ol><li>Where does my data live?</li><li>How does my data move from one place to another?</li><li>How is my code divided into files and folders?</li></ol><p>Every pattern you will read below is one way of answering these three questions. Some patterns focus on data. Some focus on UI. Some focus on how the page reaches the browser. Once you see it like this the whole topic becomes much less scary.</p><p>I have divided the patterns into four groups.</p><ul><li><strong>Data and state patterns</strong> like MVC, MVP, MVVM and Flux</li><li><strong>UI and component patterns</strong> like Atomic Design and Container Presentational</li><li><strong>Code organisation patterns</strong> like Feature Sliced Design, Clean Architecture and Monorepo</li><li><strong>Rendering and delivery patterns</strong> like SSR, SSG, Islands, Server Components and Micro Frontends</li></ul><h3>Part 1. Data and State Patterns</h3><h3>1. MVC (Model View Controller)</h3><p>This is the grandfather of all patterns. It came from desktop apps long before the web was a thing.</p><p>The idea is to split your app into three parts.</p><ul><li><strong>Model</strong> holds the data and business rules</li><li><strong>View</strong> shows the data to the user</li><li><strong>Controller</strong> listens to the user and tells the model what to change</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A3ctpOJbKa8kttlIo5UNJw.png" /></figure><p>The user clicks something. The controller catches that click and updates the model. The model then tells the view that something changed. The view redraws itself.</p><p>Old frameworks like Backbone.js and early AngularJS followed this pattern. Even today many backend frameworks like Spring MVC follow it.</p><p><strong>When to use it.</strong> Small apps and server rendered apps where the flow is simple.</p><p><strong>Where it hurts.</strong> In big frontend apps many views talk to many models. The arrows start going everywhere and you get what we call spaghetti. Debugging becomes a nightmare because you cannot tell who changed what.</p><h3>2. MVP (Model View Presenter)</h3><p>MVP is a small twist on MVC. Here the view becomes very dumb. It does not talk to the model at all.</p><ul><li><strong>View</strong> only shows things and passes user events to the presenter</li><li><strong>Presenter</strong> holds all the logic and updates the view directly</li><li><strong>Model</strong> holds the data</li></ul><p>The good thing about MVP is testing. Since the presenter has all the logic and no UI code you can test it very easily. This pattern was very popular in Android apps and in GWT based web apps.</p><p><strong>When to use it.</strong> When you want logic that is fully separate from the UI so you can unit test it.</p><p><strong>Where it hurts.</strong> You write a lot of extra code. Every view needs its own presenter and its own interface.</p><h3>3. MVVM (Model View ViewModel)</h3><p>MVVM is the pattern that made two way data binding famous.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jSSnIicfQXkkTlO4Ix-ITA.png" /></figure><ul><li><strong>Model</strong> is your data coming from the server</li><li><strong>View</strong> is the HTML template</li><li><strong>ViewModel</strong> is a special object that holds the state of the view</li></ul><p>The magic part is the binding. When the ViewModel changes the view updates on its own. When the user types in an input box the ViewModel updates on its own. You do not write any code to sync them.</p><p>Vue.js, Angular, Knockout and Svelte are all heavily inspired by this idea. If you have ever used v-model in Vue or ngModel in Angular then you have used MVVM.</p><p><strong>When to use it.</strong> Form heavy apps like admin panels, dashboards and enterprise tools where a lot of inputs are directly linked to data.</p><p><strong>Where it hurts.</strong> Two way binding is easy at first but in very large apps it becomes hard to track which change triggered which update. One small change can cause a chain reaction across the screen.</p><h3>4. Flux and Redux (Unidirectional Data Flow)</h3><p>Facebook faced exactly the problem I just mentioned. Their notification count was showing wrong numbers because too many things were updating too many other things. So they created Flux. Redux came later and made Flux simpler.</p><p>The rule is very strict. <strong>Data flows in only one direction.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NUG8uGqvdw_HqFQoIl3Msw.png" /></figure><ol><li>The view dispatches an action. An action is just a plain object like { type: “ADD_TO_CART”, payload: item }.</li><li>The reducer receives the action and the current state. It returns a brand new state.</li><li>The store saves that new state.</li><li>Every component that subscribed to the store gets the new data and re renders.</li></ol><p>What about API calls? Reducers must be pure functions so they cannot call APIs. That work goes into middleware. If you have used Redux Thunk or Redux Saga then you know what I am talking about. Thunk is simple and good for most cases. Saga uses generator functions and is great when you have complex flows like retry logic, cancelling requests or running tasks in parallel.</p><p><strong>When to use it.</strong> Medium to large apps where many screens share the same data. Think ecommerce cart, user session or a live trading dashboard.</p><p><strong>Where it hurts.</strong> Boilerplate. For a simple app it feels like writing ten files to toggle one checkbox. Redux Toolkit has fixed a lot of this pain so if you are still writing old style Redux please give RTK a try.</p><p>Today we also have lighter options like Zustand, Jotai and Recoil. They follow the same idea of a central store but with much less code. And for server data most teams now use React Query or SWR instead of keeping everything in Redux.</p><h3>Part 2. UI and Component Patterns</h3><h3>5. Component Based Architecture</h3><p>This is the foundation of almost every modern framework. React, Vue, Angular, Svelte and Solid all follow it.</p><p>The idea is simple. You build your UI as a tree of small independent pieces. Each piece has its own markup, its own style and its own logic. You combine small pieces to make bigger pieces. Just like Lego.</p><p>A good component follows a few rules.</p><ul><li>It does one job well</li><li>It gets its data through props or inputs</li><li>It does not reach out and touch other components directly</li><li>It can be reused in another screen without changes</li></ul><p>Honestly every other pattern in this article sits on top of this one. If you get components right half of your architecture problems are already solved.</p><h3>6. Atomic Design</h3><p>Brad Frost gave us this idea and it is borrowed from chemistry. Your UI is built in five levels.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MJrYHGw9Y3Ru7wQJvX6dXQ.png" /></figure><ul><li><strong>Atoms</strong> are the smallest things. A button. An input. A label. An icon.</li><li><strong>Molecules</strong> are small groups of atoms. A search box is an input plus a button.</li><li><strong>Organisms</strong> are bigger sections. A header has a logo, a nav menu and a search box.</li><li><strong>Templates</strong> are page layouts with empty slots.</li><li><strong>Pages</strong> are templates filled with real content.</li></ul><p>This pattern is the backbone of most design systems. If your company has a shared UI library in Storybook then most likely it is organised like this.</p><p><strong>When to use it.</strong> When you are building a design system or when many teams share the same UI components.</p><p><strong>Where it hurts.</strong> People waste a lot of time arguing whether something is a molecule or an organism. My advice is do not be too strict. Use the levels as a guide and not as a law.</p><h3>7. Container and Presentational Components</h3><p>Dan Abramov made this pattern popular in the early React days. The idea is to split every feature into two types of components.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aPbQmhtLmtOxJlGmUrKsWA.png" /></figure><ul><li><strong>Container components</strong> know how things work. They fetch data, manage state and handle events.</li><li><strong>Presentational components</strong> know how things look. They only receive props and render UI.</li></ul><p>So you might have a UserListContainer that calls the API and a UserList that just shows the cards.</p><p>The best part is that your presentational components become super reusable and super easy to test.</p><p><strong>A small update.</strong> After React Hooks came this pattern became less strict. Now we usually move the container logic into a custom hook like useUsers() and the component just calls that hook. The idea is the same. Only the shape has changed.</p><h3>8. Compound Components and Render Props</h3><p>These are smaller patterns but you will see them in every good component library.</p><p><strong>Compound components</strong> let a parent share state with its children without passing props manually. Think of how a select box works in HTML.</p><pre>&lt;Tabs&gt;<br>  &lt;Tabs.List&gt;<br>    &lt;Tabs.Tab&gt;Profile&lt;/Tabs.Tab&gt;<br>    &lt;Tabs.Tab&gt;Settings&lt;/Tabs.Tab&gt;<br>  &lt;/Tabs.List&gt;<br>  &lt;Tabs.Panel&gt;Profile content&lt;/Tabs.Panel&gt;<br>  &lt;Tabs.Panel&gt;Settings content&lt;/Tabs.Panel&gt;<br>&lt;/Tabs&gt;</pre><p>The Tabs parent keeps track of the active tab and shares it through context. Radix UI and Headless UI use this pattern a lot.</p><p><strong>Render props and headless components</strong> give you the logic and let you decide the UI. Libraries like TanStack Table and Downshift work this way. They handle sorting, filtering and keyboard support. You just write the markup.</p><h3>Part 3. Code Organisation Patterns</h3><h3>9. Feature Sliced Design</h3><p>Most of us start a project like this.</p><pre>src/<br>  components/<br>  hooks/<br>  services/<br>  utils/</pre><p>This is called organising by type. It works fine for small apps. But when your app grows the components folder has 200 files and you have no idea which file belongs to which feature.</p><p>Feature Sliced Design fixes this. It organises code by feature and by layer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y7zAhbl_CnXTjdQ244PzFg.png" /></figure><ul><li><strong>app</strong> has global setup like providers, routing and styles</li><li><strong>pages</strong> are full screens</li><li><strong>widgets</strong> are big independent blocks on a page</li><li><strong>features</strong> are user actions like add to cart or login</li><li><strong>entities</strong> are business objects like user, product or order</li><li><strong>shared</strong> has reusable stuff like UI kit, helpers and API config</li></ul><p>The golden rule is that <strong>a layer can only import from layers below it</strong>. A feature can use an entity. An entity can never use a feature. This one rule alone stops so much circular dependency mess.</p><p><strong>When to use it.</strong> Medium to large apps with multiple developers.</p><p><strong>Where it hurts.</strong> There is a learning curve. New developers need some time to understand where to put things.</p><h3>10. Clean Architecture (Layered Architecture)</h3><p>This idea comes from the backend world and Uncle Bob. But it works beautifully in the frontend too, especially in apps with heavy business logic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/909/1*QmKxrQoGxTvWb17sO9L8mw.png" /></figure><ul><li><strong>Domain layer</strong> has pure business rules. No React. No API. Just plain TypeScript. For example a function that calculates the final price after discount and tax.</li><li><strong>Application layer</strong> has use cases. These are your hooks or services that connect the UI with the domain.</li><li><strong>Infrastructure layer</strong> talks to the outside world. API clients, local storage, analytics.</li><li><strong>UI layer</strong> is your React or Vue components.</li></ul><p>The main benefit is that your business rules do not depend on any framework. If tomorrow your company moves from React to something else your domain code stays exactly the same.</p><p><strong>When to use it.</strong> Banking apps, insurance apps, trading platforms or anything where the business logic is complex and important.</p><p><strong>Where it hurts.</strong> For a simple marketing site this is total overkill. Do not build a five storey building for a tea stall.</p><h3>11. Event Driven Architecture (Pub Sub)</h3><p>Sometimes two parts of your app need to talk but they do not know each other. Here an event bus helps.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_RuWU_dE8aEWh1WAWgvcgQ.png" /></figure><p>One part publishes an event like “item added”. Any other part that cares about it can subscribe and react. The cart widget does not need to know that the header badge, the analytics tracker and the toast message exist.</p><p>You can build this with a tiny custom emitter, with the browser’s CustomEvent API or with libraries like mitt. It is also very common in micro frontends where different apps need to talk to each other.</p><p><strong>When to use it.</strong> Loosely connected widgets, plugin systems and micro frontends.</p><p><strong>Where it hurts.</strong> Too many events and you lose track of the flow. Please keep a list of all event names in one place. Your future self will thank you.</p><h3>12. Monorepo Architecture</h3><p>A monorepo is one Git repository that holds many apps and many shared packages.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OimJ5YAQxXuYnlgF4zTpbQ.png" /></figure><p>For example your customer website, your admin panel and your mobile app can all live in one repo. They share the same UI library, the same utils and the same ESLint and TypeScript config.</p><p>Tools like Nx, Turborepo and pnpm workspaces make this easy. They are smart enough to only build and test the parts that actually changed.</p><p><strong>When to use it.</strong> When you have multiple apps that share a lot of code.</p><p><strong>Where it hurts.</strong> CI setup and access control get tricky. A very big monorepo also needs good tooling or builds become slow.</p><h3>Part 4. Rendering and Delivery Patterns</h3><p>This part is about how your HTML actually reaches the user’s browser. This decides your page speed and your SEO.</p><h3>13. SPA vs MPA</h3><p><strong>Multi Page Application (MPA)</strong> is the classic web. Every click loads a new HTML page from the server. Old PHP sites, JSP apps and most WordPress sites work like this.</p><p><strong>Single Page Application (SPA)</strong> loads one HTML page once. After that JavaScript handles everything. Clicking a link just swaps the content without a full reload. Apps built with Create React App or plain Vite React are SPAs.</p><p>SPAs feel smooth like a mobile app. But the first load can be slow and search engines may struggle with them. That is why the patterns below exist.</p><h3>14. CSR, SSR, SSG and ISR</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2lJ7ejAAAM1Xi6LEA8ENLw.png" /></figure><p><strong>Client Side Rendering (CSR).</strong> The server sends an almost empty HTML file and a big JavaScript bundle. The browser runs the JS and builds the page. Good for dashboards behind login where SEO does not matter.</p><p><strong>Server Side Rendering (SSR).</strong> The server builds the full HTML for every request and sends it. The user sees content quickly. Then JavaScript loads and makes it interactive. This step is called hydration. Good for pages that change often and need SEO like a product page or a news feed.</p><p><strong>Static Site Generation (SSG).</strong> All HTML pages are built once at build time and served from a CDN. Super fast and super cheap. Good for blogs, docs and landing pages.</p><p><strong>Incremental Static Regeneration (ISR).</strong> This is a mix of SSG and SSR. Pages are static but they rebuild in the background after a fixed time or when you trigger it. Good for an ecommerce site with thousands of products where prices change sometimes but not every second.</p><p>Next.js, Nuxt, Remix and SvelteKit let you use all of these in the same app. You can choose per page. This flexibility is the reason these meta frameworks became so popular.</p><h3>15. Islands Architecture</h3><p>Here is a question. Why should a blog page load JavaScript for the whole page when only the comment box needs it?</p><p>Islands Architecture answers this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rPdUEPlMF8D3kIPH8_7Sqg.png" /></figure><p>The page is mostly static HTML. Only a few small parts are interactive. These parts are called islands. Each island loads its own JavaScript independently. Everything else is plain HTML with zero JavaScript.</p><p>Astro made this pattern famous. Fresh and Eleventy with plugins also support it.</p><p><strong>When to use it.</strong> Content heavy sites like blogs, marketing pages, docs and news sites.</p><p><strong>Where it hurts.</strong> Not a good fit for apps where almost everything is interactive like a Figma clone or a chat app.</p><h3>16. React Server Components</h3><p>This is the newest big pattern and it changed how we think about React.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2v4cWi5bDhOVhFNfNMi95g.png" /></figure><p>Now components are of two types.</p><ul><li><strong>Server Components</strong> run only on the server. They can read the database directly. Their code is never sent to the browser. So your bundle size becomes smaller.</li><li><strong>Client Components</strong> run in the browser. You mark them with “use client” at the top. Only these can use useState, useEffect and event handlers.</li></ul><p>Server components can render client components and pass props to them. So you keep the heavy data work on the server and send only small interactive pieces to the browser.</p><p>The Next.js App Router is built fully around this idea.</p><p><strong>When to use it.</strong> New Next.js projects where performance and SEO matter.</p><p><strong>Where it hurts.</strong> The mental model is new. Many developers get confused about what runs where. Some older libraries also do not work well inside server components yet.</p><h3>17. Micro Frontends</h3><p>Imagine a company like Flipkart or Amazon. Hundreds of developers work on one website. If everybody pushes code into one big frontend app then every release becomes a war.</p><p>Micro Frontends solve this by doing for the frontend what microservices did for the backend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tueP-KuC3L8Q_hGh9dzClA.png" /></figure><p>The website is split into smaller apps owned by different teams. One team owns product pages. Another owns the cart. Another owns payments. Each team can deploy on its own without waiting for others. In theory each team can even use a different framework.</p><p>A <strong>shell app</strong> (also called host or container) loads these micro frontends and handles common stuff like routing, login and layout.</p><p>Popular ways to build them.</p><ul><li><strong>Module Federation</strong> in Webpack or Rspack. This is the most common choice today.</li><li><strong>Single SPA</strong> as a framework to mount multiple apps together.</li><li><strong>Web Components</strong> as a framework neutral wrapper.</li><li><strong>iframes</strong> which are old school but still used for strong isolation.</li></ul><p><strong>When to use it.</strong> Large organisations with many independent teams.</p><p><strong>Where it hurts.</strong> It adds a lot of complexity. Shared dependencies, version mismatch, consistent styling and performance all become harder. For a team of five developers please do not do this. A well structured monolith is better.</p><h3>18. Backend for Frontend (BFF)</h3><p>This one sits between the frontend and the backend but frontend teams usually own it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J5k5aTPF0spyCphcds5GdA.png" /></figure><p>Different clients need different data. The mobile app wants a small response. The web app wants a richer one. Instead of making every client call five microservices and stitch the data you create a small server for each frontend. That server collects data from the services and returns exactly what the frontend needs.</p><p>You can build a BFF with Node.js, with Next.js API routes or with GraphQL.</p><p><strong>When to use it.</strong> When you have many backend services and multiple types of clients.</p><p><strong>Where it hurts.</strong> One more layer to build, deploy and monitor.</p><h3>So which pattern should you choose?</h3><p>This is the most important part so please read it slowly.</p><p><strong>You never choose only one pattern.</strong> A real app is always a combination. Let me give you a real example from a typical ecommerce project.</p><ul><li>Next.js with <strong>SSR and ISR</strong> for product pages</li><li><strong>React Server Components</strong> for heavy listing pages</li><li><strong>Feature Sliced Design</strong> for the folder structure</li><li><strong>Atomic Design</strong> for the shared UI library</li><li><strong>Redux Toolkit or Zustand</strong> for the cart and user session</li><li><strong>React Query</strong> for server data</li><li>A <strong>BFF</strong> layer to combine product, price and stock services</li><li>A <strong>monorepo</strong> with Turborepo to share code with the admin panel</li></ul><p>See how each pattern solves one specific problem?</p><p>Here is a quick cheat sheet I use.</p><ul><li><strong>Small personal project.</strong> Component based architecture with simple hooks. Nothing more.</li><li><strong>Blog or marketing site.</strong> SSG or Islands with Astro.</li><li><strong>Admin dashboard behind login.</strong> SPA with CSR, React Query and maybe Zustand.</li><li><strong>Ecommerce or content platform.</strong> Next.js with SSR, ISR and Server Components.</li><li><strong>Complex business app like banking.</strong> Add Clean Architecture and Feature Sliced Design.</li><li><strong>Huge company with many teams.</strong> Monorepo first. Micro frontends only if teams really need independent deploys.</li></ul><h3>A few things I learned the hard way</h3><p><strong>Start simple.</strong> Do not add Redux, micro frontends and clean architecture on day one. Add a pattern only when you actually feel the pain it solves.</p><p><strong>Consistency beats perfection.</strong> A team following an average pattern consistently will always do better than a team where everybody follows their own perfect pattern.</p><p><strong>Write it down.</strong> Keep a small README or an ADR (Architecture Decision Record) that explains why you picked a pattern. Six months later nobody will remember.</p><p><strong>Patterns are tools and not religion.</strong> Use what fits your problem. Leave what does not.</p><h3>Final words</h3><p>Frontend architecture is not about using fancy names in interviews. It is about making sure that six months from now you and your team can still change the code without fear.</p><p>If you understood the core ideas from this article you are already ahead of many developers. Next time you start a project just ask those three questions. Where does my data live? How does it move? How is my code divided? The right pattern will become clear on its own.</p><p>If this article helped you then please give it a clap and share it with your developer friends. And tell me in the comments which pattern you use in your current project. I read every comment.</p><p>Happy coding!</p><h3>Before you go</h3><p>If you are preparing for interviews or you just want to grow as an engineer then here are two platforms I built. I think both of them will help you.</p><h3>1. AlgorithmXlr8.io</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2FwP0-etEjAlFu4vo6vwaQ.png" /></figure><p><a href="https://algorithmxlr8.io">AlgorithmXlr8.io</a> is a one stop platform to master software engineering interviews in a systematic way.</p><ul><li><strong>System Design.</strong> High Level Design and Low Level Design built for interview context. There are also real scenario based system design questions that come up in almost eery interview.</li><li><strong>DSA the systematic way.</strong> Pattern based learning like sliding window and two pointers. You also get the DSA-31 sheet for interviews and the CF-18 sheet for competitive programming.</li><li><strong>Beyond DSA.</strong> Fix real production bugs in a codebase you have never seen. Live incidents and multi file repository problems right in your browser in Java, Python, Node.js or C++.</li></ul><h3>2. CodEyes.in</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zx5JEVViNFKamr_Z-Lfq7Q.jpeg" /></figure><p><a href="https://codeyes.in">CodEyes.in</a> puts all your coding stats in one profile. Connect LeetCode, Codeforces, CodeChef, GitHub, Medium and Substack and see your full progress in one place.</p><ul><li>One shareable profile link that you can put on your resume</li><li>Total questions solved, contests, active days and streaks across all platforms</li><li>A contest tracker so you never miss a contest</li><li>A leaderboard to compare yourself with other coders</li></ul><p>Do check out both and tell me in the comments what you think. Your feedback really helps me make them better.</p><p>Written with love by <strong>Himanshu Singour</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=340d16d9e049" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JWT in Microservices: What Really Happens from API Gateway to 10 Microservices?]]></title>
            <link>https://medium.com/@himanshusingour7/jwt-in-microservices-what-really-happens-from-api-gateway-to-10-microservices-392ed6d78fd3?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/392ed6d78fd3</guid>
            <category><![CDATA[explorepage]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[jwt]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Sat, 12 Sep 2026 06:12:38 GMT</pubDate>
            <atom:updated>2026-09-12T06:12:38.722Z</atom:updated>
            <content:encoded><![CDATA[<p>There is one question I keep seeing whenever JWT and microservices come together:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tUjNSs0UjoBjXM_LdwjbIA.png" /></figure><blockquote><strong><em>If I have 10 microservices and one API Gateway, where should I validate the JWT?</em></strong></blockquote><p>Should I validate it only at the API Gateway?</p><p>Or should I validate it again inside every microservice?</p><p>And then another question comes:</p><blockquote><strong><em>If every service validates the JWT, does every service need the private key?</em></strong></blockquote><p>And finally:</p><blockquote><strong><em>What actually happens when the user logs out?</em></strong></blockquote><p>These questions look complicated in the beginning.</p><p>But once you understand what the JWT, private key, public key, Gateway and microservice are each responsible for, the architecture becomes surprisingly simple.</p><p>Let’s understand it from the beginning.</p><h3>First, let’s imagine a real system</h3><p>Suppose we are building an HR platform.</p><p>We have one API Gateway and 10 microservices:</p><pre>                         Client<br>                            |<br>                            v<br>                       API Gateway<br>                            |<br>       +--------------------+--------------------+<br>       |         |          |         |          |<br>       v         v          v         v          v<br>    User     Employee    Company   Payroll    Leave<br>   Service    Service    Service   Service   Service<br>       +--------------------+--------------------+<br>       |         |          |         |          |<br>       v         v          v         v          v<br> Attendance   Audit     Document   Report   Notification<br>  Service    Service    Service    Service     Service</pre><p>Now we need authentication.</p><p>We don’t want every service to implement username/password login.</p><p>So we introduce an <strong>Authorization Server</strong>.</p><pre>                  Authorization Server<br>                            |<br>                            v<br>                         Client<br>                            |<br>                            v<br>                       API Gateway<br>                            |<br>              +-------------+-------------+<br>              |             |             |<br>              v             v             v<br>          Service 1     Service 2     Service 3<br>              ...</pre><p>The Authorization Server is responsible for issuing access tokens.</p><p>In our case, that access token is a JWT.</p><h3>Step 1: User logs in</h3><p>The user enters their username and password.</p><pre>User<br> |<br> | username + password<br> v<br>Authorization Server</pre><p>The Authorization Server verifies the credentials.</p><p>If everything is correct, it creates an access token.</p><p>For example:</p><pre>{<br>  &quot;iss&quot;: &quot;https://auth.example.com&quot;,<br>  &quot;sub&quot;: &quot;user-123&quot;,<br>  &quot;aud&quot;: &quot;hrmis-api&quot;,<br>  &quot;scope&quot;: &quot;employee.read employee.write&quot;,<br>  &quot;exp&quot;: 1799999999<br>}</pre><p>These claims tell us things like:</p><pre>iss   → Who issued this token?<br>sub   → Who is the user?<br>aud   → Who is this token intended for?<br>scope → What is the token allowed to do?<br>exp   → When does it expire?</pre><p>RFC 9068 defines a standardized profile for JWT-formatted OAuth 2.0 access tokens and describes important claims and validation expectations.</p><p>But there is one very important thing happening here.</p><p>The Authorization Server <strong>signs this JWT using its private key</strong>.</p><h3>Private key and public key:</h3><p>Let’s stop here because this is where many people get confused.</p><p>There are two keys:</p><pre>Private Key <br>Public Key </pre><p>The <strong>private key belongs to the Authorization Server</strong>.</p><p>It must remain secret.</p><p>The Authorization Server uses it to sign tokens.</p><pre>                Authorization Server<br>                         |<br>                    PRIVATE KEY <br>                         |<br>                         | Sign<br>                         v<br>                        JWT</pre><p>The public key is used by other components to verify that signature.</p><pre>Authorization Server<br>        |<br>        | Public Key<br>        v<br>     Gateway<br>        |<br>        +------&gt; Microservice 1<br>        |<br>        +------&gt; Microservice 2<br>        |<br>        +------&gt; Microservice 3</pre><p>The important rule is:</p><blockquote><strong><em>The private key signs. The public key verifies.</em></strong></blockquote><p>The private key does <strong>not</strong> travel with the request.</p><p>The JWT does.</p><h3>What does the JWT actually contain?</h3><p>A JWT normally has three parts:</p><pre>HEADER.PAYLOAD.SIGNATURE</pre><p>Something like:</p><pre>eyJhbGciOiJSUzI1NiJ9<br>.<br>eyJzdWIiOiJ1c2VyLTEyMyJ9<br>.<br>ABC123...</pre><p>The payload contains claims.</p><p>The signature proves that the token was signed by someone holding the private key corresponding to the public key used for verification.</p><p>One important point:</p><p><strong>JWT is not encrypted by default.</strong></p><p>The payload can generally be decoded.</p><p>So don’t think:</p><blockquote><em>“Nobody can see what’s inside my JWT.”</em></blockquote><p>The important security property here is usually the <strong>signature</strong>, not secrecy.</p><p>Never put sensitive secrets or passwords inside a normal JWT payload just because it is encoded.</p><h3>Step 2: Client calls the API Gateway</h3><p>The user now wants employee information.</p><p>The client sends:</p><pre>GET /employees/123</pre><pre>Authorization: Bearer &lt;JWT&gt;</pre><p>The request goes to:</p><pre>Client<br>   |<br>   | JWT<br>   v<br>API Gateway</pre><p>Now the Gateway becomes the first security boundary.</p><h3>Step 3: Gateway gets the public key</h3><p>The Gateway does not need the private key.</p><p>It needs the public key of the trusted Authorization Server.</p><p>In modern OAuth/OIDC systems, public signing keys are commonly exposed through a JWKS endpoint.</p><p>Conceptually:</p><pre>Authorization Server<br>        |<br>        | Public Key<br>        v<br>API Gateway</pre><p>The Gateway can cache these keys.</p><p>It doesn’t need to download the public key every time a request arrives.</p><h3>Step 4: Gateway validates the JWT</h3><p>Now the Gateway has:</p><pre>JWT<br>+<br>Trusted Public Key</pre><p>It verifies the JWT signature.</p><p>Think about it like this:</p><pre>Authorization Server</pre><pre>PRIVATE KEY<br>     |<br>     | signs<br>     v<br>    JWT<br>     |<br>     | travels through network<br>     v<br>API Gateway<br>     |<br>     | PUBLIC KEY<br>     v<br>  Verify</pre><p>If the signature is valid:</p><pre>Token was signed by the trusted issuer</pre><p>If somebody changed the token:</p><pre>Signature verification fails</pre><p>For example, imagine an attacker changes:</p><pre>scope = employee.read</pre><p>to:</p><pre>scope = employee.delete</pre><p>The signature no longer matches the modified content.</p><p>The Gateway rejects it.</p><h3>Gateway does more than checking the signature</h3><p>A valid signature alone isn’t enough.</p><p>The Gateway should validate the token according to the expected issuer, audience, time validity, signing algorithm and authorization requirements.</p><p>For example:</p><pre>Signature       <br>Issuer          <br>Audience        <br>Expiration      <br>Not Before      <br>Algorithm       <br>Scope          </pre><p>Imagine the token says:</p><pre>iss = auth.example.com<br>aud = hrmis-api<br>scope = employee.read<br>exp = future</pre><p>The Gateway asks:</p><pre>Did my trusted Authorization Server issue this?<br>             ↓<br>            YES<br>Is this token meant for this API?<br>             ↓<br>            YES<br>      Has it expired?<br>             ↓<br>             NO<br>Is the signature valid?<br>             ↓<br>            YES<br>Does it have the required permission?<br>             ↓<br>            YES</pre><p>Only then does the Gateway forward the request.</p><p>Microsoft’s API gateway guidance recommends gateway-level validation while also emphasizing validation at the backend API.</p><h3>Step 5: Gateway sends the request to the microservice</h3><p>Suppose the request is for Employee Service.</p><p>The Gateway forwards the request.</p><p>Importantly, the Gateway can forward the access token as well:</p><pre>Client<br>  |<br>  | JWT<br>  v<br>API Gateway<br>  |<br>  | same JWT<br>  v<br>Employee Service</pre><p>So Employee Service receives something like:</p><pre>GET /employees/123</pre><pre>Authorization: Bearer &lt;JWT&gt;</pre><p>What does <strong>not</strong> get forwarded?</p><pre>Private Key</pre><p>The Gateway doesn’t send the private key.</p><p>And normally it doesn’t need to send the public key with every request either.</p><p>The microservice can already obtain/trust the Authorization Server’s public keys.</p><h3>What about additional headers?</h3><p>Now, the Gateway can also add some additional headers before sending the request to the microservice. For example, it may add X-User-Id, X-Tenant-Id, or X-Organization-Id. These values can be taken from the already validated JWT.</p><p>For example, if the JWT contains the user, tenant, and organization information, the Gateway can send:</p><pre>Authorization: Bearer &lt;JWT&gt;<br>X-User-Id: user-789<br>X-Tenant-Id: tenant-123<br>X-Organization-Id: org-456</pre><p>This makes it easier for the microservice to understand which user and tenant the request belongs to.</p><p><strong>But there is one important rule:</strong> the microservice should not blindly trust these headers if the client can send them directly. The Gateway should validate the JWT first and then create or overwrite these headers using trusted information from the token.</p><p>So the flow becomes:</p><pre>Client<br>   ↓<br>JWT<br>   ↓<br>API Gateway<br>   ↓<br>Validate JWT<br>   ↓<br>Add User/Tenant/Organization headers<br>   ↓<br>Microservice</pre><p>These headers are not a replacement for JWT validation. They are simply additional context that the Gateway passes to the microservice.</p><h3>Step 6: Microservice validates the JWT again</h3><p>Now comes the part that creates the most discussion.</p><p>The Gateway already validated the token.</p><p>So why does Employee Service validate it again?</p><p>Because the service should not blindly trust the Gateway.</p><p>Employee Service has its own security boundary.</p><p>It receives:</p><pre>JWT<br>+<br>Trusted Public Key</pre><p>and verifies it.</p><pre>Employee Service<br>                        |<br>                  PUBLIC KEY <br>                        |<br>                        v<br>                    Verify JWT<br>                        |<br>                +-------+-------+<br>                |               |<br>              Valid           Invalid<br>                |               |<br>                v               v<br>          Business Logic       401</pre><p>This is <strong>defense in depth</strong>.</p><p>The Gateway protects the system at the edge.</p><p>The microservice protects itself.</p><p>Microsoft explicitly recommends backend validation even when a gateway has already validated the access token.</p><h3>Why is this actually important?</h3><p>Today your architecture might look like:</p><pre>Client<br>  |<br>Gateway<br>  |<br>Service</pre><p>But six months later, someone may add another path:</p><pre>Internal Service<br>      |<br>      v<br>Employee Service</pre><p>Or:</p><pre>Batch Job<br>    |<br>    v<br>Employee Service</pre><p>Or perhaps somebody accidentally exposes the service internally.</p><p>Now someone can bypass the Gateway:</p><pre>Attacker<br>   |<br>   X<br>Gateway<br>   |<br>   X<br>Employee Service</pre><p>If Employee Service says:</p><blockquote><em>“I don’t need to authenticate. Gateway already did it.”</em></blockquote><p>you have a problem.</p><p>But if Employee Service says:</p><blockquote><em>“I will validate the token myself.”</em></blockquote><p>then:</p><pre>Attacker<br>   |<br>   v<br>Employee Service<br>   |<br>   | Invalid / missing JWT<br>   v<br>  401</pre><p>That is why the second validation is valuable.</p><h3>Does every microservice need its own private key?</h3><p><strong>No.</strong></p><p>This is probably the most important thing to remember.</p><p>If the Authorization Server is issuing the user JWT, then the Authorization Server owns the signing private key.</p><p>You don’t need:</p><pre>Service 1 → Private Key<br>Service 2 → Private Key<br>Service 3 → Private Key<br>...<br>Service 10 → Private Key</pre><p>That would be unnecessary and dangerous if all those services were given the ability to sign the same kind of tokens.</p><p>Instead:</p><pre>                Authorization Server<br>                         |<br>                   PRIVATE KEY <br>                         |<br>                       Signs<br>                         |<br>                         v<br>                        JWT<br>                         |<br>                         v<br>                       Client<br>                         |<br>                         v<br>                    API Gateway<br>                         |<br>                    PUBLIC KEY <br>                         |<br>                       Verify<br>                         |<br>              +----------+----------+<br>              |          |          |<br>              v          v          v<br>          Service 1  Service 2  Service 3<br>              |          |          |<br>          PUBLIC KEY  PUBLIC KEY  PUBLIC KEY<br>              |          |          |<br>            Verify     Verify     Verify</pre><p>The services only need the public key for verification.</p><h3>Can someone steal the public key?</h3><p>Yes.</p><p>And that’s okay.</p><p>It’s public.</p><p>If someone gets your public key:</p><pre>Public Key<br>    |<br>    +---- Can verify tokens<br>    |<br>    +---- Cannot create legitimate tokens</pre><p>But if someone gets the private key:</p><pre>Private Key<br>    |<br>    +---- Can sign tokens<br>    |<br>    +---- Can potentially create tokens that validators accept</pre><p>That’s why the private key is the crown jewel.</p><p>It needs strong protection.</p><h3>How do microservices get the public key?</h3><p>You don’t necessarily hard-code a public key manually into every service.</p><p>A common approach is for the Authorization Server to publish its public keys through a JWKS endpoint.</p><p>Conceptually:</p><pre>Authorization Server<br>        |<br>        | JWKS<br>        v<br>+-------------------+<br>| Public Keys       |<br>|                   |<br>| kid = key-1       |<br>| kid = key-2       |<br>+-------------------+<br>        |<br>        v<br>Gateway / Services</pre><p>The services can discover the issuer’s keys and cache them.</p><p>This becomes especially useful when keys are rotated.</p><h3>What happens during key rotation?</h3><p>Suppose today the Authorization Server is using:</p><pre>Private Key 1</pre><p>and the corresponding public key is:</p><pre>Public Key 1</pre><p>Tomorrow you want to rotate the signing key.</p><p>You create:</p><pre>Private Key 2<br>Public Key 2</pre><p>The Authorization Server starts signing new tokens using Private Key 2.</p><p>The public keys can temporarily contain both keys:</p><pre>Public Keys:</pre><pre>Key 1<br>Key 2</pre><p>Why?</p><p>Because old tokens may still be valid.</p><p>So the Gateway and microservices can verify:</p><pre>Old JWT → Public Key 1<br>New JWT → Public Key 2</pre><p>Once all old tokens have expired and the old key is no longer needed, Key 1 can eventually be removed.</p><p>This is where the JWT kid header is useful: it helps a validator identify which published key should be used.</p><h3>Now let’s talk about service-to-service calls</h3><p>Suppose:</p><pre>Client<br>   |<br>   | User JWT<br>   v<br>Gateway<br>   |<br>   v<br>Order Service<br>   |<br>   v<br>Payment Service</pre><p>Now we have another question:</p><blockquote><em>Should Order Service send the same JWT to Payment Service?</em></blockquote><p>There isn’t one universal answer.</p><p>It depends on what identity and authorization model you want.</p><p>One approach is to propagate the user’s access token:</p><pre>Client<br>   |<br> User JWT<br>   v<br>Order Service<br>   |<br> User JWT<br>   v<br>Payment Service</pre><p>Payment Service then validates the token.</p><p>But you must make sure the token’s intended audience and permissions are appropriate.</p><p>Another approach is for Order Service to obtain a separate access token for calling Payment Service:</p><pre>Order Service<br>      |<br>      | service identity<br>      v<br>Authorization Server<br>      |<br>      | new access token<br>      v<br>Payment Service</pre><p>This gives you a clearer service-to-service trust boundary.</p><p>The important thing is not to blindly forward a user token everywhere without thinking about <strong>audience and permissions</strong>.</p><h3>Authentication vs Authorization</h3><p>Another simple but important distinction:</p><h3>Authentication</h3><blockquote><strong><em>Who are you?</em></strong></blockquote><h3>Authorization</h3><blockquote><strong><em>What are you allowed to do?</em></strong></blockquote><p>Suppose:</p><pre>JWT valid</pre><p>That only tells us that the token is acceptable according to our validation rules.</p><p>It doesn’t mean the user can do everything.</p><p>For example:</p><pre>scope = employee.read</pre><p>may allow:</p><pre>GET /employees/123</pre><p>But it may not allow:</p><pre>DELETE /employees/123</pre><p>because that could require:</p><pre>employee.delete</pre><p>So the flow becomes:</p><pre>JWT<br> ↓<br>Validate token<br> ↓<br>Authenticate identity<br> ↓<br>Check permission<br> ↓<br>Authorize operation<br> ↓<br>Business logic</pre><p>This distinction is extremely important in microservices.</p><h3>Now the big question: What happens during logout?</h3><p>This is where JWT is different from a traditional server-side session.</p><p>With a traditional session, you might have:</p><pre>Browser<br>   |<br>   | session ID<br>   v<br>Server<br>   |<br>   v<br>Session Store</pre><p>When the user logs out:</p><pre>Delete session</pre><p>The server can immediately know:</p><blockquote><em>This session no longer exists.</em></blockquote><p>JWT access tokens are often designed differently.</p><p>The token is usually self-contained.</p><p>For example:</p><pre>JWT<br> |<br> +-- user<br> +-- issuer<br> +-- audience<br> +-- scope<br> +-- expiration<br> +-- signature</pre><p>The server doesn’t necessarily maintain a database entry saying:</p><pre>JWT-123 = logged-in</pre><p>So you cannot always just “delete the JWT from the Authorization Server.”</p><h3>Simple JWT logout</h3><p>The simplest flow is:</p><pre>User clicks Logout<br>        |<br>        v<br>Client deletes access token<br>        |<br>        v<br>       Done</pre><p>Now the client no longer sends:</p><pre>Authorization: Bearer &lt;JWT&gt;</pre><p>So future requests fail because there is no access token.</p><p>But there is an important catch.</p><h3>What if someone already copied the JWT?</h3><p>Imagine:</p><pre>10:00 AM<br>User logs in</pre><pre>Access Token:<br>Valid until 10:15 AM</pre><p>At:</p><pre>10:05 AM</pre><p>the user logs out.</p><p>The client deletes the token.</p><p>But suppose an attacker copied the token at 10:04.</p><p>That copied token may still be cryptographically valid until 10:15 unless your architecture has a server-side revocation mechanism or some other way to reject it earlier.</p><p>This is one of the fundamental trade-offs of stateless access tokens.</p><h3>That’s why access tokens are generally short-lived</h3><p>Instead of:</p><pre>Access Token<br>Valid for 30 days</pre><p>you normally use a relatively short-lived access token.</p><p>Conceptually:</p><pre>Login<br>  |<br>  +---- Access Token<br>  |<br>  +---- Refresh Token</pre><p>The access token is used to access APIs.</p><p>The refresh token is used to obtain a new access token, according to the authorization server’s policy.</p><p>So when the access token expires:</p><pre>Access Token<br>     |<br>     X<br>   expired</pre><p>the client needs to obtain another one.</p><h3>Logout with refresh tokens</h3><p>A more complete logout can look like:</p><pre>User<br> |<br> | Logout<br> v<br>Client<br> |<br> +---- Delete Access Token<br> |<br> +---- Stop using Refresh Token<br> |<br> v<br>Authorization Server<br> |<br> +---- Revoke / invalidate refresh credential</pre><p>The exact logout and revocation behavior depends on the authorization system you’re using.</p><p>The important idea is:</p><p><strong>Deleting the access token from the client prevents the normal client from using it.</strong></p><p><strong>Revoking the refresh credential prevents the client from obtaining new access tokens through that credential.</strong></p><p>And the old access token naturally becomes unusable when it expires.</p><h3>So the complete architecture looks like this</h3><p>Now let’s put everything together.</p><pre>                         +-----------------------+<br>                         | Authorization Server  |<br>                         |                       |<br>                         | PRIVATE KEY           |<br>                         +-----------+-----------+<br>                                     |<br>                                     | Sign<br>                                     v<br>                                    JWT<br>                                     |<br>                                     v<br>                                  Client<br>                                     |<br>                                     | Bearer JWT<br>                                     v<br>                         +-----------------------+<br>                         |      API Gateway      |<br>                         |                       |<br>                         | PUBLIC KEY         |<br>                         | Validate JWT          |<br>                         +-----------+-----------+<br>                                     |<br>                              Valid token<br>                                     |<br>              +----------------------+----------------------+<br>              |                      |                      |<br>              v                      v                      v<br>       +-------------+       +-------------+       +-------------+<br>       | User        |       | Employee    |       | Payroll     |<br>       | Service     |       | Service     |       | Service     |<br>       |             |       |             |       |             |<br>       | PUBLIC KEY  |       | PUBLIC KEY  |       | PUBLIC KEY  |<br>       | Verify JWT  |       | Verify JWT  |       | Verify JWT  |<br>       +-------------+       +-------------+       +-------------+<br>              |                      |                      |<br>              +----------------------+----------------------+<br>                                     |<br>                              Other Services<br>                                     |<br>                              Verify JWT<br>                                     |<br>                                     v<br>                                  Database</pre><p>The pattern continues for all 10 services.</p><h3>The request lifecycle in one minute</h3><p>Let’s make the whole thing extremely simple.</p><p>User logs in:</p><pre>User<br> ↓<br>Authorization Server<br> ↓<br>JWT signed with PRIVATE KEY<br> ↓<br>Client</pre><p>Client calls the API:</p><pre>Client<br> ↓<br>JWT<br> ↓<br>API Gateway</pre><p>Gateway:</p><pre>Gateway<br> ↓<br>PUBLIC KEY<br> ↓<br>Verify JWT<br> ↓<br>Check issuer<br> ↓<br>Check audience<br> ↓<br>Check expiration<br> ↓<br>Check permissions</pre><p>If valid:</p><pre>Gateway<br> ↓<br>JWT<br> ↓<br>Microservice</pre><p>Microservice:</p><pre>Microservice<br> ↓<br>PUBLIC KEY<br> ↓<br>Verify JWT again<br> ↓<br>Check required permission<br> ↓<br>Business logic<br> ↓<br>Database</pre><p>The private key never leaves the Authorization Server.</p><h3>The four rules I would remember</h3><p>If you forget everything else, remember these four things.</p><h3>1. Authorization Server owns the private key</h3><pre>PRIVATE KEY <br>      ↓<br>    SIGN<br>      ↓<br>     JWT</pre><h3>2. JWT travels with the request</h3><pre>Client<br>  ↓<br>Gateway<br>  ↓<br>Microservice</pre><h3>3. Gateway and protected services verify using the public key</h3><pre>PUBLIC KEY <br>      ↓<br>   VERIFY<br>      ↓<br>     JWT</pre><h3>4. Logout is different from session logout</h3><pre>Logout<br>  ↓<br>Client deletes access token<br>  ↓<br>Refresh credential is revoked/inactivated when applicable<br>  ↓<br>Short-lived access token eventually expires</pre><p>If you need immediate invalidation of an already-issued access token, you need an additional revocation/introspection or deny-list strategy; that is a deliberate trade-off because it makes the system less purely stateless.</p><h3>The architecture I would actually keep in my head</h3><p>Don’t think:</p><blockquote><em>“JWT is just a token.”</em></blockquote><p>Think about the complete chain:</p><pre>             PRIVATE KEY<br>                   |<br>                   | Sign<br>                   ↓<br>                  JWT<br>                   |<br>                   | travels<br>                   ↓<br>                CLIENT<br>                   |<br>                   | JWT<br>                   ↓<br>             API GATEWAY<br>                   |<br>             PUBLIC KEY<br>                   |<br>                Verify<br>                   |<br>                   ↓<br>             MICRO SERVICE<br>                   |<br>             PUBLIC KEY<br>                   |<br>                Verify<br>                   |<br>                   ↓<br>             Authorization<br>                   |<br>                   ↓<br>              Business Logic<br>                   |<br>                   ↓<br>                Database</pre><p>That’s the whole story.</p><p>The <strong>private key creates the trust</strong>.</p><p>The <strong>JWT carries the identity and permissions</strong>.</p><p>The <strong>public key verifies that trust</strong>.</p><p>The <strong>Gateway rejects bad requests early</strong>.</p><p>The <strong>microservice verifies the request again because it is its own security boundary</strong>.</p><p>And <strong>logout is handled differently from traditional server-side sessions because a JWT access token can remain cryptographically valid until it expires unless you introduce a mechanism for earlier revocation</strong>.</p><p>Once this mental model is clear, JWT in a 10-service architecture is not really complicated.</p><p>It is simply:</p><blockquote><strong><em>Issue → Sign → Send → Verify at Gateway → Forward → Verify at Service → Authorize → Execute.</em></strong></blockquote><h3>Why I started reading the actual standards</h3><p>While working on this, I had a lot of questions about what should actually happen in a microservices architecture. Instead of just following our old implementation, I wanted to see how this problem is handled in real systems.</p><p>So I started reading the actual standards and engineering documentation.</p><p>First, I read <strong>RFC 9068</strong>. It is an IETF standard for JWT access tokens. The important part for this discussion is that it explains how a resource server should validate a JWT. It talks about checking things like the issuer (iss), audience (aud), signature, and expiration (exp). It also explains how the Authorization Server can publish the keys that resource servers use to validate tokens.</p><p><a href="https://www.rfc-editor.org/rfc/rfc9068.html?utm_source=chatgpt.com">Read RFC 9068 — JWT Access Token Profile</a></p><p>Then I looked at <strong>Microsoft’s API Gateway guidance</strong> to understand what changes when APIs are placed behind a Gateway. It helped me look at the Gateway as an additional security layer instead of assuming that the Gateway should become the only place responsible for security.</p><p><a href="https://learn.microsoft.com/en-us/entra/msidweb/advanced/api-gateways?utm_source=chatgpt.com">Read Microsoft’s API Gateway guidance</a></p><p>I also looked at <strong>Cloudflare’s documentation</strong> to see how a large production platform handles application authentication and tokens.</p><p><a href="https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/application-token/?utm_source=chatgpt.com">Read Cloudflare’s Application Token documentation</a></p><h3>What I learned from this</h3><p>The main lesson for me was simple:</p><p><strong>Before building an important architecture, first check how the problem is solved by the standards and by companies that have already built systems at scale.</strong></p><p>This doesn’t mean we should copy Microsoft, Cloudflare, AWS, or anyone else blindly. Our requirements may be different.</p><p>The idea is to understand <strong>why</strong> they are doing something, what problem they are solving, and then decide what makes sense for our own system.</p><p>So instead of:</p><pre>Think → Code → Find problems → Redesign</pre><p>I prefer:</p><pre>Read the standard<br>       ↓<br>Study real-world implementations<br>       ↓<br>Understand why<br>       ↓<br>Design<br>       ↓<br>Then code</pre><p>Sometimes reading the right RFC or engineering documentation for an hour can save days of implementing the wrong architecture.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=392ed6d78fd3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Debug a Production Issue Without Panicking]]></title>
            <link>https://medium.com/@himanshusingour7/how-to-debug-a-production-issue-without-panicking-45a75c8bc21c?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/45a75c8bc21c</guid>
            <category><![CDATA[de]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[engineering-newsletters]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Thu, 20 Aug 2026 06:43:02 GMT</pubDate>
            <atom:updated>2026-08-20T06:52:49.596Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xRtW5MBI-Gwo44c_fDreIA.png" /></figure><p>It was around 2 AM when my phone rang.</p><p>I was half asleep, so for a few seconds I just looked at the screen, hoping whoever was calling would call back in the morning.</p><p>Then I saw the team name. I picked it up.</p><h4>“Production mein issue hai. Payment requests fail ho rahi hain.”</h4><p>Bas. Neend gayi.</p><p>I opened my laptop and joined the call. Everyone was already trying to figure things out. Someone was checking logs, someone was looking at the database, and someone was asking about the latest deployment. And honestly, my first thought wasn’t some amazing debugging strategy.</p><p>It was simply, <strong>“Yaar, ab kya hua?”</strong></p><p>That’s the thing about production issues. When something breaks on your local machine, you have time. You can add logs, put breakpoints, restart the application, change things and try again.</p><p>Production is different.</p><p>There are real users on the other side. Someone is trying to make a payment. Someone is waiting for an order. Someone is staring at an error message. And while you’re trying to understand the problem, people are waiting for an answer.</p><p>That’s where I learned one of the most important things about production debugging:</p><p><strong>Don’t panic. And don’t start fixing things before you understand what is actually broken.</strong></p><h3>My First Instinct Used to Be Wrong</h3><p>Earlier, whenever I saw a production issue, I would immediately open the code.</p><p>API failing? Open the controller.</p><p>Then the service.</p><p>Then the repository.</p><p>Then the database query.</p><p>Ten minutes later, I would have twenty tabs open and still wouldn’t know what was happening.</p><p>The problem wasn’t that I couldn’t debug.</p><p>I was just starting from the wrong place.</p><p>Instead of asking <strong>“Where is the bug?”</strong>, I should have been asking <strong>“What exactly is happening?”</strong></p><p>So that night, I started with the simplest thing: the numbers.</p><p>How many requests were failing?</p><p>When did they start failing?</p><p>Were all payments failing?</p><p>Or only some?</p><p>That immediately gave us an interesting clue.</p><p>Not every payment was failing.</p><p>Some were going through perfectly.</p><p>Now the problem wasn’t “payment is down.”</p><p>Something was failing under a particular condition.</p><p>And suddenly, the problem became much smaller.</p><h3>Don’t Trust the First Explanation</h3><p>During production incidents, someone will almost always say something like:</p><p>“Database down hai.”</p><p>“API broken hai.”</p><p>“Payment service is down.”</p><p>I’ve learned not to take these statements as facts.</p><p>Usually, they’re just someone’s observation.</p><p>If a payment fails, it doesn’t necessarily mean the payment service is broken. Maybe the database is fine. Maybe the API is fine. Maybe a third-party service is returning something unexpected.</p><p>So now, whenever I hear <strong>“X is broken”</strong>, my first reaction is:</p><p><strong>“Okay, let’s verify that.”</strong></p><p>That one habit can save a lot of time.</p><h3>Start With the Timeline</h3><p>The next thing I usually check is the timeline.</p><p>When did the problem actually start? And more importantly, <strong>what changed just before it started?</strong></p><p>Was there a deployment? A configuration change? A database migration? A traffic spike? A change in another service?</p><p>Production systems have a lot of moving parts, and sometimes your code hasn’t changed at all.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*69NgdV3mfAyULwaE8wkp5w.png" /></figure><p>Maybe another service was deployed.</p><blockquote><em>Maybe traffic suddenly increased.</em></blockquote><blockquote><em>Maybe a scheduled job started behaving differently.</em></blockquote><blockquote><em>Maybe an external API started responding slowly</em>.</blockquote><p>That night, we noticed that the failures had started shortly after a deployment. Interesting. But I didn’t want to immediately say, <strong>“Deployment caused it.”</strong></p><p>It was a clue, not a conclusion.</p><h3>The Production Debugging Flow</h3><p>This is roughly how I approach a production issue now. I start broad, collect evidence, and slowly narrow the problem down until I reach the actual failure point.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8C8m81NYZkUNoJoGQttEag.png" /></figure><h3>Follow One Failing Request</h3><p>At this point, instead of looking at thousands of logs, I picked one failing request. I wanted to follow its entire journey.</p><p>The request reached our API. The business logic ran. The database responded normally. Then our service called another service. And that’s where things started looking strange.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LGt6WWxMDZgqsNnteOPqoQ.png" /></figure><p>This is where I usually step back and look at the bigger picture. A production issue rarely gives you the answer from one place.</p><p>I look at the timeline, logs, metrics and request trace together, then compare the evidence before deciding what the actual root cause is.</p><p>The downstream service wasn’t completely down. It was responding, but in one particular scenario, the response wasn’t what our application expected.</p><p>That changed everything.</p><p>We weren’t dealing with a completely broken application.</p><p>We had a specific failure happening between two services.</p><p>This is something production teaches you pretty quickly: your application doesn’t live alone. It depends on databases, queues, other services, external APIs and infrastructure.</p><p>Sometimes your code is perfectly fine.</p><p>Something around it isn’t.</p><h3>Find One That Works</h3><p>One of the simplest things I do during debugging is compare a failing request with a successful request.</p><p>Same API?</p><p>Same type of user?</p><p>Same data?</p><p>Same region?</p><p>Same request?</p><p>Same downstream response?</p><p>Usually, there is a difference somewhere.</p><p>Maybe one particular data combination is causing the issue.</p><p>Maybe only older records fail.</p><p>Maybe only a particular user flow triggers it.</p><p>The moment you find that difference, the problem becomes much easier.</p><p>Instead of saying:</p><p><strong>“The payment system is broken.”</strong></p><p>You can say:</p><p><strong>“Payments fail when this specific condition occurs.”</strong></p><p>That’s a much better problem to have.</p><h3>Logs Should Tell You a Story</h3><p>I used to think more logs meant easier debugging.</p><p>Not really.</p><p>I’ve seen systems where a single request generates hundreds of log lines. Everything is logged, but when production breaks, finding the useful information becomes harder.</p><p>What you actually want is a story.</p><p>Which request was this?</p><p>What operation was happening?</p><p>Which service handled it?</p><p>Which dependency was called?</p><p>What happened after that?</p><p>This is where correlation IDs are extremely useful.</p><p>If a request travels through multiple services, you should be able to follow that request across the system.</p><p>At 2 AM, you don’t want more information.</p><p>You want the <strong>right information</strong>.</p><h3>Don’t Change Everything at Once</h3><p>This is probably the easiest mistake to make when everyone is waiting for you.</p><p>You increase a timeout.</p><p>Restart the service.</p><p>Change some configuration.</p><p>Modify the query.</p><p>Deploy again.</p><p>And suddenly everything works.</p><p>Great.</p><p>But what actually fixed it?</p><p>You don’t know.</p><p>Maybe the restart helped. Maybe the configuration change helped. Maybe the external service recovered at the same time.</p><p>That’s why I try to make one meaningful change at a time.</p><p>Change something.</p><p>Observe.</p><p>Measure.</p><p>Then move forward.</p><p>Otherwise, you might fix the problem without understanding it.</p><p>And the next time it happens, you’re back at the beginning.</p><h3>Sometimes Rollback Is the Right Fix</h3><p>There is sometimes a strange ego around deployments.</p><p>Engineers don’t want to rollback because it feels like admitting that the deployment was wrong.</p><p>But production doesn’t care about your ego.</p><p>If a recent deployment is strongly connected to the incident and rollback is safe, rollback.</p><p>The goal during an incident is not to prove that your code is perfect.</p><p>The goal is to get users back to a stable system.</p><p>You can investigate the real root cause afterward.</p><p><strong>Production first. Ego later.</strong></p><h3>The Hardest Part Is Staying Calm</h3><p>Honestly, the technical problem isn’t always the hardest part.</p><p>The pressure is.</p><p>Someone asks, “Any update?”</p><p>You say you’re checking.</p><p>Five minutes later:</p><p>“Any update?”</p><p>Another team is waiting. Someone wants to know the impact. Meanwhile, you’re staring at the logs thinking, <strong>“I still don’t know what’s happening.”</strong></p><p>I’ve been there.</p><p>And I’ve learned that not knowing the answer doesn’t mean you need to start moving faster.</p><p>Sometimes you need to stop for thirty seconds.</p><p>Ask yourself:</p><p><strong>What do I know?</strong></p><p><strong>What don’t I know?</strong></p><p><strong>What have I already ruled out?</strong></p><p><strong>What’s the next thing I can check?</strong></p><p>That’s enough.</p><p>You don’t need to solve the whole incident in your head.</p><p>You just need to find the next useful clue.</p><h3>The Problem Usually Becomes Smaller</h3><p>At 2 AM, the problem looked huge.</p><p><strong>“Payment is failing in production.”</strong></p><p>But after checking the metrics, looking at the timeline, following one request and comparing it with a successful request, the problem became much smaller.</p><p>It wasn’t the entire payment system.</p><p>It wasn’t the database.</p><p>It wasn’t even the whole API.</p><p>It was a specific interaction between services under a specific condition.</p><p>That’s how I think about debugging now.</p><p>You don’t magically find the answer.</p><p>You keep removing possibilities.</p><p>One by one.</p><p>Until the giant production problem becomes one service, one request, one dependency and one bug.</p><p>And that’s when debugging becomes much easier.</p><h3>Fixing the Bug Isn’t the End</h3><p>Once everything starts working again, it’s tempting to close the laptop and forget the whole thing.</p><p>But that’s actually when the important questions start.</p><p>Why did this happen?</p><p>Why didn’t we catch it earlier?</p><p>Why didn’t our monitoring detect it?</p><p>Could we have handled the failure better?</p><p>Do we need better validation?</p><p>Better logging?</p><p>A timeout?</p><p>A circuit breaker?</p><p>A test?</p><p>The goal isn’t just to fix today’s incident.</p><p>It’s to make sure the same problem doesn’t wake you up at 2 AM again.</p><h3>What I Finally Learned</h3><p>I used to think a good engineer was someone who could look at an error and immediately know the answer.</p><p>I don’t think that anymore.</p><p>The engineers I respect most aren’t the ones who know everything.</p><p>They’re the ones who stay calm when they <strong>don’t</strong> know.</p><p>They don’t guess.</p><p>They don’t randomly change five things.</p><p>They don’t assume the first error message is the root cause.</p><p>They simply keep asking better questions.</p><p>Did the request reach the service?</p><p>Did the database respond?</p><p>Did the downstream service respond?</p><p>When did the problem start?</p><p>What changed?</p><p>Why did this request fail while another one worked?</p><p>Slowly, the huge problem becomes smaller.</p><p>And eventually, you find the answer.</p><p>So the next time your phone rings at 2 AM and someone says, <strong>“Production mein issue hai,”</strong> don’t immediately start changing things.</p><p>Take a breath.</p><p>Understand what is actually happening.</p><p>Follow one failing request.</p><p>Find one that worked.</p><p>Compare them.</p><p>Reduce the possibilities.</p><p>Then fix the thing that is actually broken.</p><p>Because production debugging isn’t about being the smartest person in the room.</p><p>It’s about staying calm enough to figure out what the system is trying to tell you.</p><p>And honestly, that’s one of the most valuable engineering skills I’ve learned.</p><h3>Before You Go</h3><p>One more thing.</p><p>If you’re serious about becoming a better software engineer, I’m building something that might be useful for you.</p><p>Instead of putting everything into one huge learning platform, I’ve created focused learning paths for different stages of an engineer’s journey.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cBOP3aOQ2oNqy4OwfJ5yWQ.png" /></figure><p><strong>Master AI Engineering</strong><br>Learn how to build AI-powered applications, understand AI systems, work with LLMs, agents, RAG, and take AI from an idea to something that actually works.</p><p>Master AI Engineering: <a href="https://algorithmxlr8.io/ai/engineering/home">https://algorithmxlr8.io/ai/engineering/home</a></p><p><strong>Master DevOps Engineering</strong><br>Understand the engineering behind deployments, containers, CI/CD, cloud infrastructure, monitoring, scalability, and running applications reliably in production.</p><p>Master DevOps Engineering: <a href="https://algorithmxlr8.io/devops/engineering/home">https://algorithmxlr8.io/devops/engineering/home</a></p><p><strong>Master Software Engineer Interviews</strong><br>DSA, LLD, HLD, System Design and the kind of problems you’re actually expected to solve in software engineering interviews.</p><p>Master Software Engineer Interviews: <a href="https://algorithmxlr8.io/">https://algorithmxlr8.io/</a></p><p>The goal isn’t just to help you <strong>clear an interview</strong>.</p><p>It’s to help you become the engineer who actually understands <strong>what’s happening behind the code, how systems work, and how to build things properly.</strong></p><p>If that sounds like the kind of engineer you want to become, <strong>come join me on the journey.</strong></p><p>Explore: <a href="https://algorithmxlr8.io/">https://algorithmxlr8.io/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=45a75c8bc21c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Understand a Large Codebase Without Losing Your Mind]]></title>
            <link>https://medium.com/@himanshusingour7/how-to-understand-a-large-codebase-without-losing-your-mind-6ca334a643f6?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/6ca334a643f6</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[de]]></category>
            <category><![CDATA[complexity]]></category>
            <category><![CDATA[ai-in-softwareengineering]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Tue, 11 Aug 2026 10:27:09 GMT</pubDate>
            <atom:updated>2026-08-11T10:27:09.839Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WHNjiH8diqeRAExPWNKcOA.png" /></figure><p>I still remember the first time I opened a genuinely large codebase.</p><p>I had worked on plenty of projects before. I knew Java. I knew Spring Boot. I knew APIs, databases, queues, Docker, AWS, all the usual things.</p><p>So when someone said, <strong>“You’ll need to understand this repository before making the change,”</strong> I thought:</p><p><em>Okay. Give me a couple of hours.</em></p><p>Then I opened the repository.</p><p>There were hundreds of folders.</p><p>controller</p><p>service</p><p>repository</p><p>config</p><p>client</p><p>consumer</p><p>producer</p><p>handler</p><p>factory</p><p>strategy</p><p>processor</p><p>scheduler</p><p>utils</p><p>And then there were folders whose names made absolutely no sense.</p><p>I opened one class.</p><p>It called another class.</p><p>That class called another service.</p><p>That service called a client.</p><p>The client published an event.</p><p>The event was consumed somewhere else.</p><p>That consumer triggered another service.</p><p>That service updated the database.</p><p>And somewhere in the middle, there was a Redis cache.</p><p>I closed the file.</p><p>Opened another one.</p><p>Same story.</p><p>After an hour, I had read a lot of code.</p><p>But I understood <strong>nothing</strong>.</p><p>And that’s when I learned one of the most important lessons of working with large software systems:</p><blockquote><strong><em>You don’t understand a large codebase by reading more code. You understand it by building the right mental model.</em></strong></blockquote><p>That completely changed how I approach unfamiliar repositories.</p><h3>The Biggest Mistake: Starting With the Code</h3><p>When developers join a new project, the first instinct is usually:</p><p><strong>“Let me start reading the code.”</strong></p><p>That’s exactly what I used to do.</p><p>Open UserController.</p><p>Read 200 lines.</p><p>Open UserService.</p><p>Read 400 lines.</p><p>Open UserRepository.</p><p>Read 100 lines.</p><p>Then jump to PaymentService.</p><p>Then OrderService.</p><p>Then some random utility.</p><p>After three hours, you feel productive because you have seen thousands of lines.</p><p>But if someone asks:</p><p><strong>“So how does an order actually get created?”</strong></p><p>You have no idea.</p><p>That’s the trap.</p><p>A large codebase is not a book.</p><p>You don’t read it from page 1 to the last page.</p><p>A large codebase is more like a <strong>city</strong>.</p><p>If you enter a new city, you don’t walk into the first building and start studying its walls.</p><p>First, you look at the map.</p><p>You figure out:</p><p>Where is the airport?</p><p>Where is downtown?</p><p>Where are the major roads?</p><p>Where are the important neighborhoods?</p><p>Only then do you start exploring individual buildings.</p><p>A codebase works exactly the same way.</p><h3>Step 1: Don’t Read the Code. Find the Business.</h3><p>Before looking at classes, ask:</p><p><strong>What does this system actually do?</strong></p><p>Imagine you join an e-commerce company.</p><p>You are given a repository called:</p><p>commerce-platform</p><p>You could start with:</p><pre>src/<br> ├── controller/<br> ├── service/<br> ├── repository/<br> ├── config/<br> ├── consumer/<br> ├── producer/<br> └── client/</pre><p>But instead, ask a completely different question:</p><blockquote><strong><em>What happens when a customer places an order?</em></strong></blockquote><p>Now you have a story.</p><p>Customer opens the application.</p><p>They add products to the cart.</p><p>They click <strong>Buy Now</strong>.</p><p>The backend receives the request.</p><p>An order is created.</p><p>Payment is initiated.</p><p>Inventory is reserved.</p><p>The customer receives confirmation.</p><p>That’s already more useful than reading 500 classes.</p><p>Because now you’re not trying to understand the entire system.</p><p>You’re trying to understand <strong>one journey through the system</strong>.</p><p>And that journey becomes your entry point.</p><h3>Step 2: Find the Entry Point</h3><p>Every important operation has somewhere it enters the system.</p><p>For an HTTP application, it might be:</p><pre>POST /orders</pre><p>Search for it.</p><p>Maybe you find:</p><pre>@PostMapping(&quot;/orders&quot;)<br>public OrderResponse createOrder(<br>        @RequestBody CreateOrderRequest request) {<br>return orderService.createOrder(request);<br>}</pre><p>Perfect.</p><p>You now have your first door into the system.</p><p>Don’t immediately understand every line.</p><p>Just follow the path.</p><pre>Controller<br>    ↓<br>Service<br>    ↓<br>Repository<br>    ↓<br>Database</pre><p>Maybe the real system is more complicated:</p><pre>Controller<br>    ↓<br>OrderService<br>    ↓<br>InventoryService<br>    ↓<br>PaymentService<br>    ↓<br>EventPublisher<br>    ↓<br>Kafka<br>    ↓<br>OrderConsumer<br>    ↓<br>NotificationService</pre><p>Now something interesting happens.</p><p>You are no longer looking at <strong>classes</strong>.</p><p>You’re looking at a <strong>story</strong>.</p><p>And stories are much easier for humans to remember.</p><h3>Step 3: Trace One Request End-to-End</h3><p>This is probably the most powerful technique I’ve learned.</p><p>Pick one important operation.</p><p>For example:</p><p><strong>“Create Order.”</strong></p><p>Then trace it from beginning to end.</p><p>Write it down.</p><p>Literally.</p><pre>POST /order<br>↓<br>OrderController<br>        ↓<br>OrderService.createOrder()<br>        ↓<br>InventoryService.reserve()<br>        ↓<br>PaymentService.charge()<br>        ↓<br>OrderRepository.save()<br>        ↓<br>Kafka → OrderCreatedEvent<br>        ↓<br>NotificationConsumer<br>        ↓<br>EmailService</pre><p>Suddenly the giant repository doesn’t look so scary anymore.</p><p>You have discovered one path through the forest.</p><p>Now do the same for:</p><p><strong>Cancel Order</strong></p><pre>DELETE /orders/{id}<br>↓<br>OrderController<br>        ↓<br>OrderService.cancel()<br>        ↓<br>PaymentService.refund()<br>        ↓<br>InventoryService.release()<br>        ↓<br>OrderRepository.update()<br>        ↓<br>OrderCancelledEvent</pre><p>Now you understand two important business flows.</p><p>And something magical starts happening.</p><p>The same classes appear again.</p><p>You begin recognizing them.</p><p><em>“Oh, I’ve already seen OrderService.”</em></p><p><em>“I’ve already seen PaymentService.”</em></p><p><em>“So this event is also consumed by NotificationService.”</em></p><p>That’s how a large codebase slowly becomes familiar.</p><h3>Step 4: Build Your Own Map</h3><p>One mistake I see engineers make is trying to remember everything in their head.</p><p>Don’t.</p><p>Create a map.</p><p>It can be something as simple as:</p><pre>                     ┌──────────────┐<br>                     │   Client     │<br>                     └──────┬───────┘<br>                            ↓<br>                     ┌──────────────┐<br>                     │ Controller   │<br>                     └──────┬───────┘<br>                            ↓<br>                     ┌──────────────┐<br>                     │   Service    │<br>                     └───┬──────┬───┘<br>                         ↓      ↓<br>                  ┌─────────┐ ┌─────────┐<br>                  │  DB     │ │ Payment │<br>                  └─────────┘ └────┬────┘<br>                                   ↓<br>                                Kafka<br>                                   ↓<br>                              Consumers</pre><p>It doesn’t need to be beautiful.</p><p>It needs to be <strong>useful</strong>.</p><p>Personally, I like writing three things for every unfamiliar system:</p><h3>1. What comes in?</h3><pre>HTTP<br>Kafka<br>Scheduler<br>External API</pre><h3>2. What happens in the middle?</h3><pre>Validation<br>Business logic<br>Database<br>Cache<br>External services<br>Events</pre><h3>3. What goes out?</h3><pre>HTTP response<br>Kafka event<br>Email<br>Database update<br>External API call</pre><p>Once you can answer those three questions, the system becomes much easier to navigate.</p><h3>Step 5: Understand the Data Before the Classes</h3><p>Here’s another mistake I made early in my career.</p><p>I spent hours understanding services.</p><p>But I didn’t understand the data.</p><p>That’s backwards.</p><p>Suppose you’re working on a payment system.</p><p>Before understanding PaymentService.java, find out:</p><p><strong>What is a Payment?</strong></p><p>Maybe the database looks something like:</p><pre>Payment<br>id<br>orderId<br>userId<br>amount<br>currency<br>status<br>transactionId<br>createdAt<br>updatedAt</pre><p>Now the code starts making sense.</p><p>You see:</p><pre>payment.setStatus(PaymentStatus.SUCCESS);</pre><p>You know why it exists.</p><p>You see:</p><pre>paymentRepository.findByOrderId(orderId);</pre><p>You understand what relationship is being used.</p><p>You see:</p><pre>transactionId</pre><p>And you immediately think:</p><p><em>“This probably connects our payment record with the external payment provider.”</em></p><p>Without understanding the data, code is just syntax.</p><p>With the data, code starts telling a story.</p><h3>Step 6: Find the Database Tables</h3><p>Whenever I enter a new backend project, one of the first things I want to understand is:</p><p><strong>What are the important entities?</strong></p><p>For example:</p><pre>User<br>Order<br>Product<br>Payment<br>Inventory<br>Shipment</pre><p>Then ask:</p><pre>User<br>  ↓<br>Order<br>  ↓<br>Payment<br>  ↓<br>Shipment</pre><p>Maybe:</p><pre>Order<br> ├── userId<br> ├── paymentId<br> └── shipmentId</pre><p>Now you have another mental model.</p><p>You understand not only <strong>what the code does</strong>, but also <strong>what the system is storing</strong>.</p><p>And this becomes extremely useful when debugging.</p><p>Because many production bugs eventually become:</p><blockquote><em>“Something went wrong between these two pieces of data.”</em></blockquote><h3>Step 7: Don’t Ignore Configuration</h3><p>This one looks boring.</p><p>It isn’t.</p><p>I’ve seen engineers spend hours trying to understand application behavior while completely ignoring:</p><pre>application.yml<br>application.properties<br>.env<br>Dockerfile<br>docker-compose.yml</pre><p>Configuration often tells you more about a system than the Java classes.</p><p>Look for:</p><pre>Database<br>Redis<br>Kafka<br>S3<br>AWS<br>External APIs<br>Feature flags<br>Timeouts<br>Retries<br>Thread pools<br>Connection pools</pre><p>Suppose you find:</p><pre>payment:<br>  timeout: 3000<br>kafka:<br>  retries: 3<br>redis:<br>  ttl: 3600</pre><p>Now you already know something about the architecture.</p><p>The system talks to a payment provider.</p><p>It uses Kafka.</p><p>It uses Redis.</p><p>The payment call has a timeout.</p><p>Kafka retries failures.</p><p>Redis data expires after an hour.</p><p>You just learned a lot without reading hundreds of classes.</p><h3>Step 8: Find the External Systems</h3><p>Large systems almost never live alone.</p><p>They talk to other systems.</p><p>Your codebase might interact with:</p><pre>Payment Gateway<br>Kafka<br>Redis<br>PostgreSQL<br>MongoDB<br>S3<br>Elasticsearch<br>Notification Service<br>Identity Service</pre><p>Find those integrations.</p><p>Search for things like:</p><pre>RestTemplate<br>WebClient<br>FeignClient<br>KafkaTemplate<br>RedisTemplate<br>S3Client<br>MongoRepository<br>JpaRepository</pre><p>Then ask:</p><p><strong>Why does this system depend on that system?</strong></p><p>That’s important.</p><p>Don’t just memorize:</p><blockquote><em>“We use Kafka.”</em></blockquote><p>Understand:</p><blockquote><em>“We use Kafka because order processing doesn’t need to wait for notification processing.”</em></blockquote><p>Now you’ve understood the <strong>reason</strong>, not just the technology.</p><p>And reasons are easier to remember.</p><h3>Step 9: Use Git Like a Detective</h3><p>This is one of the most underrated techniques.</p><p>When you don’t understand why some weird code exists, don’t stare at it for two hours.</p><p>Check Git history.</p><p>For example:</p><pre>git log</pre><p>Or:</p><pre>git blame PaymentService.java</pre><p>You might discover:</p><pre>Added retry logic after payment provider timeout issue</pre><p>Suddenly that strange-looking code makes sense.</p><p>Maybe you find:</p><pre>if (attempt &gt; 2) {<br>    throw new PaymentException();<br>}</pre><p>At first you think:</p><p><em>“Why only two retries?”</em></p><p>Git history might tell you:</p><p><em>“Because the payment provider starts rate-limiting requests after three attempts.”</em></p><p>Boom.</p><p>The code wasn’t random.</p><p>There was a production incident behind it.</p><p>This is why mature codebases sometimes look messy.</p><p>You’re not just reading software.</p><p>You’re reading <strong>the history of decisions</strong>.</p><h3>Step 10: Read Tests Before Implementation</h3><p>This changed my life.</p><p>Suppose you find:</p><pre>OrderService.createOrder()</pre><p>You could open the implementation.</p><p>Or you could first search:</p><pre>OrderServiceTest</pre><p>Tests often tell you what the business actually expects.</p><p>For example:</p><pre>shouldNotCreateOrderWhenInventoryUnavailable()<br>shouldRefundPaymentWhenOrderCancellationFails()<br>shouldRetryPaymentWhenProviderTimesOut()<br>shouldNotDuplicateOrderForSameIdempotencyKey()</pre><p>Look at those test names.</p><p>You just discovered important business rules.</p><p>And you didn’t need to read 500 lines of implementation.</p><p>Tests are often the <strong>closest thing to executable documentation</strong>.</p><h3>Step 11: Learn the “Happy Path” First</h3><p>Don’t start with exceptions.</p><p>Don’t start with every edge case.</p><p>Don’t start with the most complicated class.</p><p>First understand:</p><p><strong>What happens when everything goes right?</strong></p><p>For an order:</p><pre>Request<br> ↓<br>Validate<br> ↓<br>Create Order<br> ↓<br>Reserve Inventory<br> ↓<br>Charge Payment<br> ↓<br>Save Order<br> ↓<br>Publish Event<br> ↓<br>Send Confirmation</pre><p>That’s your happy path.</p><p>Once you understand that, start asking:</p><p><strong>What happens if payment fails?</strong></p><pre>Payment fails<br>      ↓<br>Retry<br>      ↓<br>Still fails<br>      ↓<br>Release inventory<br>      ↓<br>Mark order FAILED<br>      ↓<br>Return error</pre><p>Then:</p><p><strong>What happens if Kafka is down?</strong></p><p>Then:</p><p><strong>What happens if the request is sent twice?</strong></p><p>Then:</p><p><strong>What happens if the database succeeds but event publishing fails?</strong></p><p>This is how you move from basic understanding to real engineering understanding.</p><h3>Step 12: Look for the Weird Parts</h3><p>Once you’ve understood the normal flow, start looking for things that make you say:</p><p><strong>“Why the hell are they doing this?”</strong></p><p>Those places are gold.</p><p>Maybe you find:</p><pre>Thread.sleep(500);</pre><p>Why?</p><p>Maybe you find:</p><pre>cache.put(key, value, 300);</pre><p>Why 300?</p><p>Maybe you find:</p><pre>if (retryCount &lt; 3)</pre><p>Why three?</p><p>Maybe you find:</p><pre>@Transactional</pre><p>Why is the transaction boundary here?</p><p>Maybe you find:</p><pre>eventPublisher.publish(...)</pre><p>inside a database transaction.</p><p>Now you have interesting questions.</p><p>And these questions often lead you toward the most important architectural decisions in the system.</p><h3>Step 13: Don’t Try to Understand Every Class</h3><p>This is probably the most important thing in this entire article.</p><p>You don’t need to understand 100% of the codebase.</p><p>You need to understand the <strong>20% that matters for your task</strong>.</p><p>Imagine you receive this ticket:</p><blockquote><em>“Fix duplicate payments when the client retries the request.”</em></blockquote><p>You don’t need to understand:</p><pre>UserProfileService<br>RecommendationEngine<br>SearchService<br>NotificationService<br>AnalyticsService<br>ReportingService</pre><p>You need to find:</p><pre>Payment API<br>      ↓<br>Payment Service<br>      ↓<br>Payment Provider<br>      ↓<br>Database</pre><p>Then ask:</p><p><strong>Where is the request ID?</strong></p><p><strong>Where is idempotency handled?</strong></p><p><strong>Where is the payment persisted?</strong></p><p><strong>What happens when the same request comes twice?</strong></p><p>Your understanding should be <strong>task-driven</strong>.</p><p>Not repository-driven.</p><h3>A Real Example</h3><p>Let’s say you join a company and receive this bug:</p><blockquote><em>“Customers are sometimes charged twice when they click Pay multiple times.”</em></blockquote><p>You open the repository.</p><p>You don’t start reading everything.</p><p>You start with:</p><pre>POST /payments</pre><p>You find:</p><pre>PaymentController<br>       ↓<br>PaymentService<br>       ↓<br>PaymentGateway<br>       ↓<br>PaymentRepository</pre><p>Then you ask:</p><p><strong>What happens when the same request arrives twice?</strong></p><p>You find:</p><pre>public PaymentResponse pay(PaymentRequest request) {<br>paymentGateway.charge(<br>        request.getAmount()<br>    );<br>    Payment payment = new Payment();<br>    payment.setOrderId(request.getOrderId());<br>    paymentRepository.save(payment);<br>    return PaymentResponse.success();<br>}</pre><p>And suddenly you see the problem.</p><p>The system charges first.</p><p>Then saves the payment.</p><p>There is no idempotency check.</p><p>So:</p><pre>Request #1<br>    ↓<br>Charge ₹1000<br>    ↓<br>Save payment</pre><p>Then the user retries:</p><pre>Request #2<br>    ↓<br>Charge ₹1000 AGAIN<br>    ↓<br>Save another payment</pre><p>The customer loses ₹2000.</p><p>You didn’t understand the entire repository.</p><p>You didn’t need to.</p><p>You understood the <strong>payment journey</strong>.</p><p>And that’s enough to solve the problem.</p><h3>The 30-Minute Rule</h3><p>When I enter an unfamiliar codebase, I now give myself a rule:</p><p><strong>Don’t try to become an expert in the first 30 minutes.</strong></p><p>The goal of the first 30 minutes is only to answer:</p><pre>What does this system do?<br>Where does a request enter?<br>What are the major services?<br>Where is the database?<br>What external systems exist?<br>Where are the important business flows?<br>What part is relevant to my task?</pre><p>That’s it.</p><p>If you can answer those questions, you’ve already won.</p><h3>The “Breadcrumb” Technique</h3><p>Here’s something I use constantly.</p><p>When you find an important method, don’t read everything around it.</p><p>Follow the breadcrumbs.</p><p>Suppose:</p><pre>orderService.createOrder()</pre><p>calls:</p><pre>inventoryService.reserve()</pre><p>Follow that.</p><p>Then:</p><pre>paymentService.charge()</pre><p>Follow that.</p><p>Then:</p><pre>eventPublisher.publish()</pre><p>Follow that.</p><p>Then:</p><pre>OrderCreatedEvent</pre><p>Search where it’s consumed.</p><p>Maybe you discover:</p><pre>OrderCreatedEvent<br>        ↓<br>InventoryConsumer<br>        ↓<br>AnalyticsConsumer<br>        ↓<br>NotificationConsumer</pre><p>One search leads to another.</p><p>That’s how you navigate a large repository.</p><p>Not randomly.</p><p><strong>Breadcrumb by breadcrumb.</strong></p><h3>Ask “Why?” Five Times</h3><p>Sometimes understanding code requires more than knowing what it does.</p><p>You need to understand why it exists.</p><p>For example:</p><p><strong>Why are we using Redis?</strong></p><p>Because database queries are slow.</p><p><strong>Why are database queries slow?</strong></p><p>Because this endpoint gets huge traffic.</p><p><strong>Why does it get huge traffic?</strong></p><p>Because it’s called every time the user opens the dashboard.</p><p><strong>Why don’t we calculate the data once?</strong></p><p>Because the data changes frequently.</p><p>Now you understand something much deeper:</p><p>Redis isn’t there because:</p><blockquote><em>“Redis is cool.”</em></blockquote><p>It’s there because of a specific performance requirement.</p><p>That’s the difference between <strong>knowing a system</strong> and <strong>understanding a system</strong>.</p><h3>Eventually, the Codebase Starts Talking to You</h3><p>This is the beautiful part.</p><p>At first:</p><pre>OrderService<br>PaymentService<br>InventoryService<br>KafkaConsumer<br>RedisConfig</pre><p>look like random names.</p><p>After a few days, they become familiar.</p><p>You see:</p><pre>OrderCreatedEvent</pre><p>and immediately think:</p><p><em>“Okay, something happened after an order was created.”</em></p><p>You see:</p><pre>@KafkaListener</pre><p>and think:</p><p><em>“This isn’t part of the synchronous request. Something is happening asynchronously.”</em></p><p>You see:</p><pre>@Transactional</pre><p>and think:</p><p><em>“Okay, these database operations probably need to succeed or fail together.”</em></p><p>You see:</p><pre>@Cacheable</pre><p>and think:</p><p><em>“This data is probably expensive to calculate or fetch.”</em></p><p>The code stops looking like thousands of unrelated lines.</p><p>It starts looking like a system.</p><h3>My Exact Process Today</h3><p>If you give me a repository I’ve never seen before, I don’t randomly open files anymore.</p><p>I usually go in this order:</p><pre>1. README<br>      ↓<br>2. Project structure<br>      ↓<br>3. Application entry point<br>      ↓<br>4. Configuration<br>      ↓<br>5. Database/entities<br>      ↓<br>6. API endpoints<br>      ↓<br>7. One important business flow<br>      ↓<br>8. External integrations<br>      ↓<br>9. Events / queues<br>      ↓<br>10. Tests<br>      ↓<br>11. Git history<br>      ↓<br>12. Task-specific code</pre><p>And while doing this, I keep one document open.</p><p>I call it:</p><p><strong>“My Mental Model.”</strong></p><p>Inside it, I keep only:</p><pre>System purpose<br>Major components<br>Important APIs<br>Important database entities<br>External dependencies<br>Important events<br>Main business flows<br>Things I don&#39;t understand yet</pre><p>That last section is extremely important.</p><p>Because instead of pretending I understand something, I write:</p><pre>TODO:<br>Why do we publish OrderCreated twice?<br>TODO:<br>Why is Redis used here?<br>TODO:<br>Why does payment retry three times?<br>TODO:<br>Why is this transaction boundary here?</pre><p>Now I have questions to investigate.</p><p>That’s much better than having confusion floating around in my head.</p><p>The biggest shift happens when you stop asking:</p><blockquote><strong><em>“How can I understand this entire codebase?”</em></strong></blockquote><p>and start asking:</p><blockquote><strong><em>“What story is this code trying to tell me?”</em></strong></blockquote><p>Because every large codebase has a story.</p><p>A request comes in.</p><p>Something validates it.</p><p>Some business decision happens.</p><p>Data changes.</p><p>Maybe another service gets called.</p><p>Maybe an event is published.</p><p>Maybe another system reacts.</p><p>Maybe the user gets a response.</p><p>That’s the story.</p><p>Your job as an engineer isn’t to memorize every class.</p><p>Your job is to <strong>reconstruct that story</strong>.</p><p>Once you know the story, the classes become characters.</p><p>The APIs become entry points.</p><p>The database becomes the memory.</p><p>The queues become the communication system.</p><p>The external services become the outside world.</p><p>The logs become the clues.</p><p>And Git history becomes the backstory.</p><p>Suddenly, the repository that looked like a monster yesterday starts looking like something you can actually reason about.</p><p>And that’s when you know you’ve crossed the line from:</p><p><strong>“I am reading this code.”</strong></p><p>to:</p><p><strong>“I understand this system.”</strong></p><p>That is the real skill.</p><p>Not knowing every file.</p><p>Not memorizing every class.</p><p>Not reading 10,000 lines a day.</p><p><strong>It’s knowing where to look, what to follow, what questions to ask, and how to turn thousands of lines of code into one simple story.</strong></p><h3>One Last Thing</h3><p>And one more thing I want to say.</p><p>Nothing is actually that complex.</p><p>Most of the time, <strong>our mind makes it complex before the problem even becomes complex.</strong> We see a large codebase, a new technology, system design, AI, distributed systems, or an unfamiliar architecture, and immediately think, <em>“This is too difficult.”</em></p><p>But it isn’t.</p><p>You just need to make your mind more <strong>flexible, lean, and adaptable</strong>.</p><p>Don’t try to understand everything at once. Don’t try to memorize everything. Just follow what you are reading, understand one thing at a time, connect it with the previous thing, and keep moving.</p><p>Eventually, the things that looked confusing in the beginning start becoming obvious.</p><p>And if you are preparing for an <strong>AI Engineer</strong> or <strong>Software Engineer</strong> role, don’t try to learn everything randomly. Start exploring the right concepts, understand how they connect, and follow a systematic learning path.</p><p>Once your learning becomes systematic, your confidence naturally starts growing.</p><p>You don’t need to become a genius.</p><p>You just need to keep learning, keep exploring, and keep making your mind more adaptable.</p><p>That’s how complicated systems slowly become simple.</p><p>And if you want to take that journey further:</p><p><strong>If you want to master your Software Engineering interviews: </strong><a href="https://algorithmxlr8.io/">https://algorithmxlr8.io/</a></p><p><strong>If you want to master your AI Engineering interviews: </strong><a href="https://algorithmxlr8.io/">https://algorithmxlr8.io/</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7b2B3IrBDWnsIKCimwcE5Q.png" /></figure><p>Keep learning.</p><p>Keep exploring.</p><p>And most importantly, <strong>don’t let your mind convince you that something is difficult before you have actually tried to understand it.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ca334a643f6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Learned AI Engineering]]></title>
            <link>https://medium.com/@himanshusingour7/how-i-learned-ai-engineering-443649cc9295?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/443649cc9295</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[de]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Sun, 09 Aug 2026 08:03:42 GMT</pubDate>
            <atom:updated>2026-08-09T08:03:42.214Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FNkT9YxvH5RpimHkNVNWkg.png" /></figure><p>I still remember when I first started getting serious about AI.</p><p>At that time, AI was everywhere. Every second person was talking about ChatGPT, LLMs, RAG, agents and the next big AI framework.</p><p>I was already working as a software engineer, so I initially thought this would be easy for me. I knew how to build APIs, work with databases, write backend services and think about scalable systems. I thought I just needed to learn how to call an LLM.</p><p>I was wrong.</p><p>The first few days were actually exciting. I started with Python because most of the AI ecosystem was built around it. I already knew programming, so Python itself wasn’t the difficult part.</p><p>But then I started seeing things like embeddings, transformers, vector databases, RAG, LangChain, LangGraph, agents, memory, tool calling and MCP. Every time I understood one thing, I discovered three more things.</p><p>That was probably the first problem I faced.</p><p>I wasn’t struggling because AI was impossible to learn. I was struggling because I didn’t know <strong>what I should learn first</strong>.</p><p>So instead of randomly jumping between YouTube videos, blogs and new AI frameworks, I decided to step back and look at AI Engineering from an engineer’s perspective.</p><p>I asked myself a simple question:</p><p><strong>If I had to build a real AI product from scratch, what would I actually need to know?</strong></p><p>That question changed everything.</p><h3>I Started With Things I Already Knew</h3><p>I didn’t start my AI journey by trying to understand every mathematical detail behind neural networks. I started from the engineering side.</p><p>I went back to <strong>Python</strong>, because I wanted to become comfortable building AI applications with it. Then I made sure I was comfortable with things that are easy to ignore when you’re excited about AI: <strong>Git</strong>, APIs, HTTP, JSON, databases, SQL, asynchronous programming, Docker and basic cloud concepts.</p><p>At first, these topics didn’t feel like AI.</p><p>I remember thinking, “Why am I learning Git and Docker again? I came here to learn AI.”</p><p>But later I understood why.</p><p>Suppose you build an AI application that works perfectly on your laptop. Now imagine someone else needs to run it. Your application needs an API. It needs configuration. It needs a database. It needs deployment. It needs logging. It needs error handling. It needs version control.</p><p>The LLM is only one part of the application.</p><p>That realization became very important for me.</p><p>I stopped thinking about AI as a separate world and started looking at it as another type of software system.</p><h3>Then I Went Back to Machine Learning</h3><p>After getting comfortable with the engineering foundations, I started going deeper into <strong>Machine Learning</strong>.</p><p>I didn’t want to become a research scientist. My goal was to understand what was happening underneath the tools I was using.</p><p>I learned about data, features, training, validation, models, overfitting and evaluation. Then I moved towards <strong>Deep Learning</strong> and started understanding neural networks and how models learn patterns from data.</p><p>This was interesting because I had spent years writing software where I explicitly told the computer what to do.</p><p>With traditional programming, I could write:</p><p>“If this happens, do this.”</p><p>Machine Learning felt different.</p><p>Instead of manually writing every rule, I was giving the system data and allowing a model to learn patterns.</p><p>That difference was important to understand before jumping into modern LLM applications.</p><h3>Then I Found Transformers</h3><p>The next big step for me was understanding <strong>Transformers</strong>.</p><p>Before that, LLMs felt almost magical.</p><p>You type a question.</p><p>The model understands it.</p><p>It generates an answer.</p><p>But when I started learning about tokens, embeddings, attention and transformers, the magic started becoming engineering.</p><p>I still didn’t understand every mathematical detail, and I didn’t need to.</p><p>What I wanted was a mental model.</p><p>I wanted to understand what happens between:</p><p><strong>Text → Model → Output</strong></p><p>That foundation made it much easier for me to understand modern LLMs.</p><h3>Then I Started Building With LLMs</h3><p>Once I understood the basics, I started using LLM APIs.</p><p>This part was fun.</p><p>You could write a small amount of code and suddenly have an application that could summarize text, answer questions, extract structured information or generate content.</p><p>But after building a few simple applications, I hit another problem.</p><p>The model didn’t know my data.</p><p>I could ask it general questions, but what if I wanted it to answer questions about my own documents?</p><p>What if those documents were private?</p><p>What if the information changed every week?</p><p>What if I had thousands of documents?</p><p>Putting everything inside the prompt obviously wasn’t going to work.</p><p>That was when I discovered <strong>RAG</strong>.</p><h3>RAG Was a Big Turning Point</h3><p>RAG completely changed how I thought about AI applications.</p><p>Instead of:</p><p><strong>Question → LLM → Answer</strong></p><p>the system could become:</p><p><strong>Question → Retrieve relevant information → LLM → Answer</strong></p><p>That sounds simple when you write it like that.</p><p>But when I actually started building one, I realized how many engineering decisions were hiding underneath.</p><p>How should I split a document?</p><p>How large should a chunk be?</p><p>Should I keep metadata?</p><p>How should I create embeddings?</p><p>Where should I store them?</p><p>How many documents should I retrieve?</p><p>What if the retrieved documents are wrong?</p><p>What if the answer isn’t present in the knowledge base?</p><p>What if the document changes?</p><p>Suddenly my simple RAG application wasn’t so simple anymore.</p><p>And honestly, this is where I started learning much faster.</p><p>Because I wasn’t learning RAG from a definition anymore.</p><p>I was learning it because my own application was giving me bad answers.</p><h3>I Started Understanding Embeddings and Vector Databases</h3><p>To make RAG work properly, I needed to understand <strong>embeddings</strong>.</p><p>At first, the idea felt strange.</p><p>How can a piece of text become numbers?</p><p>And how can those numbers help me find similar information?</p><p>I started experimenting with embeddings and <strong>vector databases</strong>.</p><p>Then I understood the basic idea: instead of searching only for exact words, we could represent information in a form that allowed us to find semantically similar content.</p><p>That opened another area of learning.</p><p>Vector search.</p><p>Similarity.</p><p>Metadata filtering.</p><p>Indexing.</p><p>Retrieval.</p><p>Hybrid search.</p><p>And once again, I realized that the AI application was not just an LLM call.</p><p>There was an entire retrieval system around it.</p><h3>Then I Started Building AI APIs</h3><p>At this point I wanted to move beyond notebooks and small experiments.</p><p>I wanted to build proper AI backend services.</p><p>That’s where <strong>FastAPI</strong> became useful.</p><p>I started thinking about an AI application like any other backend system.</p><blockquote>There is an API.</blockquote><blockquote>There is validation.</blockquote><blockquote>There are services.</blockquote><blockquote>There is a database.</blockquote><blockquote>There are external dependencies.</blockquote><blockquote>There are failures.</blockquote><blockquote>There are timeouts.</blockquote><blockquote>There are retries.</blockquote><blockquote>There are logs.</blockquote><blockquote>There are users.</blockquote><p>The difference is that somewhere inside the system, there is an LLM making probabilistic decisions.</p><p>That difference creates a completely new set of engineering challenges.</p><p>For example, in a normal API, I can usually predict what a function will return.</p><p>With an LLM, the output can change.</p><p>It can be correct.</p><p>It can be incomplete.</p><p>It can misunderstand the request.</p><p>It can hallucinate.</p><p>It can return something in the wrong format.</p><p>So I started thinking about validation and reliability much more seriously.</p><h3>Then Agents Started Getting Interesting</h3><p>After building RAG systems, I started asking another question.</p><p>What if the AI could actually <strong>do something</strong> instead of just answering?</p><p>What if I gave it a calculator?</p><p>What if I gave it a database?</p><p>What if it could call an API?</p><p>What if it could search something?</p><p>What if it could decide which tool to use?</p><p>That led me into <strong>AI Agents</strong> and <strong>tool calling</strong>.</p><p>The first time I built a simple tool-calling workflow, it felt very different from a chatbot.</p><p>The model wasn’t just generating text.</p><p>It was deciding what action should happen next.</p><p>But again, the moment I started building more complicated workflows, things became messy.</p><p>What happens when the tool fails?</p><p>What happens when the model calls the wrong tool?</p><p>What happens when the agent keeps repeating the same action?</p><p>Where do we store state?</p><p>How do we retry?</p><p>When should a human take over?</p><p>Those questions pushed me deeper into agent engineering.</p><h3>LangGraph Changed My Mental Model</h3><p>When I started learning <strong>LangGraph</strong>, something clicked.</p><p>Instead of thinking about an agent as some magical autonomous AI, I could think about it as a workflow.</p><p>There is state.</p><p>There are nodes.</p><p>There are decisions.</p><p>There are edges.</p><p>There can be loops.</p><p>There can be retries.</p><p>There can be human intervention.</p><p>That was much easier for me to reason about as a software engineer.</p><p>I started building workflows where one step would retrieve information, another would call a tool, another would validate the result and another would decide what should happen next.</p><p>The more I built, the more I realized that a good AI agent is not about giving the model unlimited freedom.</p><p>It’s about designing the right boundaries around it.</p><h3>Then I Started Thinking About Memory</h3><p>One problem became obvious after building conversational systems.</p><p>The AI forgets.</p><p>You can have a long conversation with a system, start a new session and suddenly it knows nothing.</p><p>That made me curious about <strong>AI memory</strong>.</p><p>What should an AI remember?</p><p>Should it remember everything?</p><p>Probably not.</p><p>Should it remember user preferences?</p><p>Maybe.</p><p>Should it remember previous tasks?</p><p>Sometimes.</p><p>Should memories expire?</p><p>Probably.</p><p>Where should memories be stored?</p><p>How should they be retrieved?</p><p>These questions made me realize that memory is not just “store the chat history.”</p><p>It is another engineering problem.</p><h3>Then Came MCP</h3><p>As I continued exploring AI agents and tools, I came across <strong>MCP</strong>.</p><p>What interested me wasn’t just the protocol itself.</p><p>It was the idea behind it.</p><p>AI systems need to interact with external tools and data.</p><p>Instead of every AI application creating completely different integrations, there could be a standardized way for models and applications to discover and use capabilities.</p><p>That made me think about AI applications differently again.</p><p>The future AI application isn’t just a chatbot sitting inside a box.</p><p>It can interact with databases, APIs, files, developer tools and other systems.</p><p>The model becomes one part of a much larger ecosystem.</p><h3>Then Reality Hit: AI Can Be Wrong</h3><p>This was probably one of the most important lessons I learned.</p><p>A demo can look amazing.</p><p>A production system is different.</p><p>You can build a RAG system that works perfectly on five documents.</p><p>Then you put 50,000 documents into it and everything changes.</p><p>You can build an agent that works perfectly ten times.</p><p>Then it gets a slightly different request and enters a loop.</p><p>You can write the perfect prompt.</p><p>Then the model gives you an unexpected answer.</p><p>That forced me to learn about <strong>AI evaluation</strong>.</p><p>I started thinking about questions like:</p><blockquote>How do I know my retrieval is good?</blockquote><blockquote>How do I know the answer is correct?</blockquote><blockquote>How do I detect hallucinations?</blockquote><blockquote>How do I compare two versions of a prompt?</blockquote><blockquote>How do I know whether a new model is actually better?</blockquote><p>Traditional unit tests aren’t enough for every AI problem.</p><p>AI systems need their own evaluation strategy.</p><p>That was another major shift in my thinking.</p><h3>Then I Started Thinking About Production</h3><p>Once you build enough AI applications, you eventually stop asking:</p><p><strong>“Can I make this work?”</strong></p><p>and start asking:</p><p><strong>“Can I make this reliable?”</strong></p><p>That’s a completely different question.</p><p>Now you start thinking about latency.</p><p>Token costs.</p><p>Caching.</p><p>Retries.</p><p>Timeouts.</p><p>Rate limits.</p><p>Streaming.</p><p>Logging.</p><p>Monitoring.</p><p>Tracing.</p><p>Security.</p><p>Authentication.</p><p>Deployment.</p><p>Scaling.</p><p>Model selection.</p><p>Fallbacks.</p><p>This is where my software engineering background became extremely useful.</p><p>Because AI may be new, but production engineering problems are not.</p><p>An AI application still needs good architecture.</p><p>It still needs good APIs.</p><p>It still needs proper databases.</p><p>It still needs observability.</p><p>It still needs security.</p><p>It still needs testing.</p><p>It still needs people who understand what happens when something goes wrong at 2 AM.</p><h3>I Also Made Plenty of Mistakes</h3><p>One thing I don’t want to hide is that I wasted a lot of time.</p><p>I jumped between frameworks.</p><p>I watched tutorials without building anything.</p><p>I sometimes learned a tool before understanding the problem it was solving.</p><p>I built small demos that looked impressive for five minutes but taught me very little.</p><p>There were also times when I thought I understood something because I could explain the definition.</p><p>Then I tried building it.</p><p>And got stuck.</p><p>That was a good lesson.</p><p>There is a huge difference between knowing:</p><p><strong>“A vector database stores embeddings.”</strong></p><p>and actually debugging why your retrieval system is returning irrelevant documents.</p><p>There is a difference between knowing:</p><p><strong>“Agents can call tools.”</strong></p><p>and debugging an agent that keeps calling the same tool again and again.</p><p>There is a difference between knowing:</p><p><strong>“RAG reduces hallucinations.”</strong></p><p>and actually discovering that bad retrieval can make the final answer even worse.</p><p>Building exposes those gaps very quickly.</p><h3>Eventually I Stopped Learning AI as Separate Topics</h3><p>This was probably the biggest change in my learning.</p><p>Earlier, I saw everything separately.</p><p>Python was one thing.</p><p>Machine Learning was another.</p><p>LLMs were another.</p><p>RAG was another.</p><p>Agents were another.</p><p>Vector databases were another.</p><p>FastAPI was another.</p><p>MCP was another.</p><p>Now I see them as pieces of one system.</p><p>A user sends a request.</p><p>The API receives it.</p><p>The application decides what needs to happen.</p><p>Maybe it retrieves information.</p><p>Maybe it calls a tool.</p><p>Maybe it uses memory.</p><p>Maybe an agent workflow is required.</p><p>The model generates a response.</p><p>The response gets validated.</p><p>The system records what happened.</p><p>Then we evaluate whether the system actually did a good job.</p><p>Suddenly all those individual topics started making sense together.</p><h3>What Actually Helped Me Learn</h3><p>If I had to choose one thing that helped me the most, it wouldn’t be a course or a particular framework.</p><p>It would be <strong>building things</strong>.</p><p>Whenever I learned something, I tried to build something small around it.</p><p>Learned RAG?</p><p>Build one.</p><p>Learned tool calling?</p><p>Build one.</p><p>Learned agents?</p><p>Build one.</p><p>Learned memory?</p><p>Build one.</p><p>Learned MCP?</p><p>Build one.</p><p>Learned evaluation?</p><p>Add evaluation to an existing project.</p><p>The project didn’t need to be huge.</p><p>Sometimes a small working project taught me more than spending an entire weekend watching tutorials.</p><p>The pattern became very simple:</p><p><strong>Learn → Build → Break → Debug → Understand → Build again.</strong></p><p>That’s how the knowledge started sticking.</p><h3>I Also Started Explaining What I Learned</h3><p>Another thing that helped me was writing about these concepts.</p><p>When you explain something to another engineer, you quickly discover what you don’t understand.</p><p>You think you understand RAG.</p><p>Then someone asks:</p><p>“Why this chunk size?”</p><p>And you realize you never really thought about it.</p><p>You think you understand agents.</p><p>Then someone asks:</p><p>“What happens when the tool fails?”</p><p>And suddenly you have another rabbit hole to explore.</p><p>Writing and teaching forced me to go one level deeper.</p><p>That’s also one of the reasons I started organizing these topics on AlgorithmXlr8.</p><p>I didn’t want AI Engineering to feel like a collection of random technologies.</p><p>I wanted to create a path where someone could start from the fundamentals and gradually reach real AI systems.</p><h3>My Biggest Lesson</h3><p>Looking back, I don’t think I learned AI Engineering by following one perfect roadmap.</p><p>I learned it by repeatedly getting stuck.</p><p>I learned Python because I needed it to build something.</p><p>I learned RAG because my LLM didn’t know my data.</p><p>I learned vector databases because I needed better retrieval.</p><p>I learned agents because I wanted the AI to take actions.</p><p>I learned LangGraph because agent workflows became difficult to manage.</p><p>I learned memory because conversations needed context.</p><p>I learned MCP because AI systems needed better access to tools.</p><p>I learned evaluation because “it seems to work” wasn’t good enough.</p><p>And I learned production engineering because eventually every demo needs to survive outside your laptop.</p><p>That’s what made AI Engineering interesting to me.</p><p>It isn’t just about AI.</p><p>It is about bringing everything together.</p><p>Software Engineering.</p><p>Data.</p><p>Machine Learning.</p><p>LLMs.</p><p>Backend Engineering.</p><p>Systems.</p><p>Infrastructure.</p><p>And a lot of experimentation.</p><h3>If I Were Starting Again</h3><p>If I were starting AI Engineering from zero today, I wouldn’t try to learn everything at once.</p><p>I’d first get comfortable with <strong>Python, Git, APIs, databases and basic software engineering</strong>.</p><p>Then I’d learn the foundations of <strong>Machine Learning and Deep Learning</strong>.</p><p>Then I’d understand <strong>LLMs and Transformers</strong>.</p><p>Then I’d build a <strong>RAG system</strong>.</p><p>Then I’d learn <strong>embeddings, vector databases and retrieval</strong> properly.</p><p>Then I’d build <strong>AI APIs with FastAPI</strong>.</p><p>Then I’d move into <strong>tool calling and AI Agents</strong>.</p><p>After that I’d learn <strong>LangGraph, state and workflows</strong>.</p><p>Then <strong>memory and MCP</strong>.</p><p>Then I’d spend serious time on <strong>evaluation, guardrails, reliability and production AI</strong>.</p><p>But I wouldn’t spend months learning each topic before building.</p><p>I’d learn enough.</p><p>Then build.</p><p>Then let the problems tell me what I need to learn next.</p><h3>The Journey Isn’t Finished</h3><p>Even after learning all of this, I don’t consider myself “done” with AI Engineering.</p><p>That’s probably the biggest difference between learning a technology and becoming an engineer.</p><p>There is always another problem.</p><p>A better retrieval strategy.</p><p>A better model.</p><p>A cheaper inference setup.</p><p>A more reliable agent.</p><p>A better evaluation method.</p><p>A new protocol.</p><p>A new architecture.</p><p>A new production problem.</p><p>And that’s okay.</p><p>I don’t think the goal is to finish AI Engineering.</p><p>The goal is to become good enough at engineering that when a new AI technology appears, you can understand where it fits, why it exists and when you should actually use it.</p><p>That’s the mindset I’m trying to build.</p><p>Don’t chase every new model.</p><p>Don’t learn every framework just because it’s trending.</p><p>Don’t build another chatbot just to say you built an AI project.</p><p>Understand the fundamentals.</p><p>Build real things.</p><p>Break them.</p><p>Debug them.</p><p>Measure them.</p><p>And keep going.</p><p>That’s how I learned AI Engineering.</p><p>And honestly, I’m still learning.</p><h3>Want to Start Your AI Engineering Journey?</h3><p>If you want to start learning AI Engineering and follow the same kind of path I followed, I’ve put the complete learning journey on my platform, <strong>AlgorithmXlr8</strong>.io</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bpOdK6EYTn4OIWQ15pb3qQ.png" /></figure><p>I’ve tried to structure it around the same question I had when I started: <strong>what should I learn first, what should I learn next, and how do all these pieces actually connect?</strong></p><p>You can start with the fundamentals and gradually move towards Machine Learning, LLMs, RAG, AI Agents, workflows, memory, MCP and the other concepts required to build real AI systems.</p><p>If you’re also trying to figure out where to start with AI Engineering, you can start here:</p><p><a href="https://algorithmxlr8.io/ai/engineering/home"><strong>https://algorithmxlr8.io</strong></a></p><p>I’ve learned these concepts by building, breaking, debugging and going back to the fundamentals. I’ve tried to put that same approach into the platform so you don’t have to spend months jumping randomly between different resources.</p><p>If you’re starting your AI Engineering journey, you can start here too.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=443649cc9295" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I Built My First RAG System Because My Dad Asked One Simple Question]]></title>
            <link>https://medium.com/@himanshusingour7/i-built-my-first-rag-system-because-my-dad-asked-one-simple-question-16c6e3e115cd?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/16c6e3e115cd</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[algorithmxlr8]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Thu, 06 Aug 2026 16:18:21 GMT</pubDate>
            <atom:updated>2026-08-06T16:18:21.347Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-_aEsTij5Z1j-Ro1MqoXPg.png" /></figure><p>Last Sunday, I was sitting at home with my laptop.</p><p>My father walked in and asked,</p><blockquote><em>Beta, what exactly do you build all day?</em></blockquote><p>I smiled.</p><p>I said,</p><blockquote><em>AI.</em></blockquote><p>He looked confused.</p><p>Then he asked another question.</p><blockquote><em>If AI is so intelligent, can it answer questions about our family’s documents?</em></blockquote><p>I confidently opened ChatGPT.</p><p>I uploaded nothing.</p><p>Then I asked,</p><blockquote><em>“What is my electricity bill for last month?”</em></blockquote><p>The AI gave a beautiful answer.</p><p>It was also completely wrong.</p><p>My father laughed.</p><blockquote><em>“So this intelligent AI doesn’t even know our own documents?”</em></blockquote><p>That one sentence stayed in my head.</p><h3>The Real Problem</h3><p>Most people think an AI knows everything.</p><p>It doesn’t.</p><p>An LLM is like a student who studied millions of books before the exam.</p><p>But once the exam starts…</p><p>The books are taken away.</p><p>Now the student has to answer only from memory.</p><p>If you ask,</p><blockquote><em>“Who won the Cricket World Cup 2011?”</em></blockquote><p>Easy.</p><p>If you ask,</p><blockquote><em>“What’s written on page 18 of my company’s HR policy?”</em></blockquote><p>It has no idea.</p><p>Sometimes it says,</p><blockquote><em>“I don’t know.”</em></blockquote><p>Sometimes…</p><p>It confidently makes things up.</p><p>That’s called a hallucination. RAG was created to reduce those unsupported answers by grounding responses in external information.</p><h3>Then I Thought…</h3><p>What if the student was allowed to open the library before answering?</p><p>Not the whole library.</p><p>Just the few books related to the question.</p><p>Now imagine the process.</p><p>You ask,</p><blockquote><em>“How many casual leaves do employees get?”</em></blockquote><p>Instead of guessing…</p><p>Someone first walks into the library.</p><p>Searches the HR policy.</p><p>Finds the correct page.</p><p>Brings it back.</p><p>Only then does the student answer.</p><p>That’s exactly what RAG does.</p><h3>A Simple Real-Life Example</h3><p>Imagine your mother keeps every recipe in a notebook.</p><p>One day you ask,</p><blockquote><em>“How do we make paneer butter masala?”</em></blockquote><p>You don’t remember.</p><p>So you open the notebook.</p><p>Find the recipe.</p><p>Read it.</p><p>Then cook.</p><p>You didn’t magically know the recipe.</p><p>You retrieved it first.</p><p>That’s Retrieval.</p><p>Then you used that information to create the answer.</p><p>That’s Generation.</p><p>Together…</p><p>Retrieval-Augmented Generation.</p><h3>How I Built It</h3><p>I didn’t start with AI.</p><p>I started with documents.</p><p>I collected PDFs.</p><p>Company policies.</p><p>Technical documentation.</p><p>Product manuals.</p><p>Articles.</p><p>Then I broke every document into smaller pieces.</p><p>Because finding one paragraph is much easier than searching a 500-page PDF.</p><p>Next…</p><p>Every small paragraph became a numerical representation called an embedding.</p><p>Think of it like giving every paragraph its own GPS coordinates.</p><p>Similar ideas end up close together.</p><p>Different ideas stay far apart.</p><p>These embeddings were stored inside a vector database.</p><p>Now my documents became searchable by meaning instead of exact words. This semantic-search pattern is one of the core ideas behind modern RAG systems.</p><h3>What Happens When Someone Asks a Question?</h3><p>Suppose someone types,</p><blockquote><em>“How many sick leaves can I take?”</em></blockquote><p>The system doesn’t send that question directly to the LLM.</p><p>Instead…</p><p>The question is converted into an embedding.</p><p>The vector database searches for paragraphs with similar meaning.</p><p>It finds the most relevant chunks.</p><p>Those chunks are sent to the LLM.</p><p>The LLM reads them.</p><p>Then answers using only that information.</p><p>Not memory.</p><p>Evidence.</p><h3>The Biggest Difference</h3><p>Without RAG: Question → LLM → Guess</p><p>With RAG: Question → Search Documents → Retrieve Information → LLM → Accurate Answer</p><p>One extra step.</p><p>A huge difference.</p><h3>The Funny Part</h3><p>After building it…</p><p>I went back to my father.</p><p>This time he asked,</p><blockquote><em>“What’s written in our electricity bill?”</em></blockquote><p>The AI searched the uploaded bill.</p><p>Read the exact amount.</p><p>Answered correctly.</p><p>My father smiled.</p><blockquote><em>“Now this feels intelligent.”</em></blockquote><p>That was the moment I understood.</p><p>RAG doesn’t make an AI smarter.</p><p>It gives the AI access to the right information before it speaks.</p><h3>Final Thought</h3><p>When people hear “RAG,” they often imagine a complicated AI architecture.</p><p>But at its heart, it’s surprisingly simple.</p><p>Think of three roles:</p><ul><li><strong>The Library</strong> → Your documents.</li><li><strong>The Librarian</strong> → Finds the right pages.</li><li><strong>The Teacher</strong> → Reads those pages and explains them in simple language.</li></ul><p>That’s all a RAG system really is. (<a href="https://algorithmxlr8.io/ai/engineering/home/rag-vector-search/rag-fundamentals/what-is-rag">https://algorithmxlr8.io/ai/engineering/home/rag-vector-search/rag-fundamentals/what-is-rag</a>)</p><p>And once you understand it this way, building one feels much less intimidating.</p><h3>Want to Learn AI Engineering Step by Step?</h3><p>Programming, Math &amp; Data Foundations<br>│<br>├── Statistics &amp; Probability<br>├── NumPy &amp; Pandas<br>└── Data Cleaning &amp; Visualization<br>│<br>Machine Learning &amp; Deep Learning<br>│<br>├── Machine Learning Fundamentals<br>├── Deep Learning Fundamentals<br>└── PyTorch<br>│<br>LLM Engineering &amp; Applications<br>│<br>├── Prompt Engineering<br>├── RAG &amp; Vector Search<br>├── Fine-Tuning<br>├── MCP<br>└── Hugging Face<br>│<br>AI Agents &amp; Orchestration<br>│<br>├── AI Agents &amp; Tool Calling<br>└── LangChain &amp; LangGraph<br>│<br>Deployment, Safety &amp; Production<br>│<br>├── LLMOps<br>├── AI Safety &amp; Evaluation<br>└── Security</p><p>Explore the complete at: <a href="https://algorithmxlr8.io/">https://algorithmxlr8.io/</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JgDex61H-GGDCvVsLSK5QA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=16c6e3e115cd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Before I Switched From My 9–5, I Did This]]></title>
            <link>https://medium.com/@himanshusingour7/before-i-switched-from-my-9-5-i-did-this-bf8a31212342?source=rss-81912d0c6ef8------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf8a31212342</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[corporate-culture]]></category>
            <category><![CDATA[de]]></category>
            <dc:creator><![CDATA[Himanshu Singour]]></dc:creator>
            <pubDate>Mon, 20 Jul 2026 07:34:47 GMT</pubDate>
            <atom:updated>2026-07-20T07:34:47.498Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vDwVs6ZnIvtqxdrwnQTJvw.png" /></figure><blockquote>Everyone talks about resigning. Very few people talk about the preparation that happens months before that decision.</blockquote><h3>The Thought Stayed in My Mind for a Long Time</h3><p>I still remember the first time I seriously thought about leaving my 9–5 job.</p><p>It wasn’t because I had a bad manager.</p><p>It wasn’t because I hated my work.</p><p>It wasn’t even because I wanted to become an entrepreneur overnight.</p><p>The thought came from something much simpler.</p><p>Every evening after work, I would open my laptop again. Not because someone asked me to, but because I genuinely wanted to build something of my own.</p><p>Some days it was a small backend project.</p><p>Some days it was a DSA platform.</p><p>Sometimes I would just spend two hours reading about distributed systems or improving my engineering skills.</p><p>I started noticing something.</p><p>No matter how tired I was after office hours, I still found myself opening my laptop again.</p><p>That’s when I realized this wasn’t just a hobby anymore.</p><p>It was becoming something much bigger.</p><p>But even then, I never thought, <em>“I’ll resign next month.”</em></p><p>Instead, I asked myself a different question.</p><p><strong>“What needs to happen before I can even think about leaving?”</strong></p><p>Looking back, that single question probably saved me from making a very emotional decision.</p><h3>Watching People Quit Made Me Realize Something</h3><p>Around the same time, I started seeing a lot of posts on LinkedIn and Twitter.</p><p>Someone would announce,</p><p><em>“Today is my last working day.”</em></p><p>Another person would post a picture of their resignation letter.</p><p>A few weeks later they would announce their startup.</p><p>It looked exciting.</p><p>For a few days, I also felt like maybe I should just do the same.</p><p>But social media only shows the final chapter.</p><p>Nobody posts about the months of uncertainty before that.</p><p>Nobody talks about wondering whether they’ll have enough money six months later.</p><p>Nobody talks about the nights when they question whether they’re making the biggest mistake of their career.</p><p>The more I thought about it, the more I realized something.</p><p>I wasn’t interested in quitting my job.</p><p>I was interested in building a life where leaving my job became a natural next step.</p><p>Those are two completely different things.</p><h3>I Made One Rule for Myself</h3><p>That weekend, I opened my notebook and wrote down one rule.</p><p><strong>“Don’t resign because you’re frustrated. Resign only when you’re prepared.”</strong></p><p>It sounds simple.</p><p>But it changed the way I looked at everything.</p><p>Whenever I felt like quitting after a stressful day at work, I would read that line again.</p><p>Frustration lasts for a few hours.</p><p>A resignation lasts much longer.</p><p>I promised myself that I would never make a career decision based on one bad week.</p><p>If I ever left, it would be because I had spent months preparing for it.</p><p>Not because I had a bad meeting on Monday morning.</p><h3>My Evenings Started Looking Different</h3><p>Earlier, once work was over, I would relax, watch random videos, scroll through social media, and call it a day.</p><p>Slowly, that changed.</p><p>I gave myself a small target.</p><p>Just two hours.</p><p>No unrealistic schedules.</p><p>No “I’ll study eight hours after office.”</p><p>That never worked.</p><p>Some evenings I worked on a side project.</p><p>Some evenings I learned AWS.</p><p>Some days I practiced DSA.</p><p>Other days I read about System Design or tried to understand a technology I had been avoiding.</p><p>There were many nights when I didn’t feel like doing anything.</p><p>Office had already drained my energy.</p><p>But I made a promise to myself.</p><p>Even if I wasn’t productive for two hours, I would at least sit in front of my laptop.</p><p>Some days those two hours became twenty minutes.</p><p>Some days they became four hours.</p><p>The important part wasn’t the duration.</p><p>It was showing up consistently.</p><h3>I Stopped Waiting for the Perfect Idea</h3><p>One mistake I made in the beginning was thinking I needed an amazing startup idea before I started building.</p><p>So I kept waiting.</p><p>Every week I thought,</p><p><em>“Maybe I’ll get a better idea next month.”</em></p><p>That month never came.</p><p>Eventually, I stopped chasing ideas.</p><p>Instead, I started solving problems I personally cared about.</p><p>If a tool didn’t exist, I built it.</p><p>If I found learning difficult, I created notes.</p><p>If I wanted a better way to study DSA and System Design, I started working on it little by little.</p><p>None of those projects were perfect.</p><p>Some never even got completed.</p><p>But every project taught me something.</p><p>How to deploy applications.</p><p>How to work with cloud services.</p><p>How to design better APIs.</p><p>How to fix production bugs.</p><p>How to deal with users.</p><p>More importantly, they taught me that building consistently matters far more than waiting for the perfect opportunity.</p><h3>Money Was the Conversation Nobody Wanted to Have</h3><p>For a long time, I ignored the financial side of leaving a job.</p><p>I only thought about passion.</p><p>Reality doesn’t work like that.</p><p>Rent doesn’t stop because you’re following your dream.</p><p>Bills don’t disappear.</p><p>Responsibilities don’t disappear.</p><p>I realized that if I wanted the freedom to make bold career decisions, I first needed financial stability.</p><p>So instead of rushing, I started saving.</p><p>Not because I expected to fail.</p><p>Because I wanted peace of mind.</p><p>Knowing that I could survive for several months without depending on my next salary completely changed the way I looked at risk.</p><p>Confidence doesn’t only come from skills.</p><p>Sometimes it comes from knowing you have enough time to recover if things don’t go according to plan.</p><h3>The Biggest Lesson I Learned</h3><p>Today, whenever someone asks me,</p><p><em>“How do I prepare before leaving my 9–5 job?”</em></p><p>I don’t tell them to resign.</p><p>I tell them to prepare until resigning feels obvious.</p><p>Build something while you’re still employed.</p><p>Learn skills that increase your value.</p><p>Save money.</p><p>Create habits that prove you can stay disciplined without someone managing your time.</p><p>If you can’t stay consistent for two hours after office, quitting your job won’t magically make you disciplined.</p><p>Freedom is amazing.</p><p>But freedom without discipline quickly turns into procrastination.</p><h3>Looking Back</h3><p>I’m glad I didn’t leave my job the first time I felt frustrated.</p><p>If I had, it would’ve been an emotional decision.</p><p>Instead, I spent months preparing quietly.</p><p>Nobody noticed those evenings.</p><p>Nobody saw the weekends I spent learning instead of going out.</p><p>Nobody celebrated the small milestones.</p><p>But those small efforts slowly built something much bigger than I had imagined.</p><p>Looking back now, I don’t think resigning was the hardest part.</p><p>Preparing for it was.</p><p>And that’s exactly why the transition felt less like jumping into the unknown and more like taking the next logical step.</p><p>If you’re thinking about switching from your 9–5, don’t ask yourself, <strong>“When should I resign?”</strong></p><p>Ask yourself, <strong>“What can I start building today so that when the day comes, leaving feels like a decision not a gamble?”</strong></p><p>That one question changed everything for me.</p><p>Maybe it’ll do the same for you.</p><h3>If You’re Serious About Making the Switch</h3><p>If you’ve read this far, chances are you’re thinking about something bigger than just changing jobs.</p><p>Maybe you want to become a better Software Engineer.</p><p>Maybe you’re preparing for AI Engineering roles.</p><p>Maybe you’re aiming for DevOps, SRE, or Backend Engineering interviews.</p><p>Whatever your goal is, one thing is true having a structured learning path makes a huge difference.</p><p>One of the biggest mistakes I made early in my career was learning random topics without any direction. I’d jump from one YouTube video to another, bookmark dozens of articles, and buy courses I never finished.</p><p>Progress became much faster once I started following a clear roadmap instead of learning whatever looked interesting that day.</p><p>That’s exactly why I built <strong>AlgorithmXlr8</strong>.</p><p>It isn’t just another collection of videos or interview questions. It’s a structured platform designed to help engineers master Software Engineering, AI Engineering, DevOps, DSA, System Design, and other interview-focused skills through a step-by-step learning path.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*x7f00ohqP58hjv2U.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UFJpbJoTWoFFx_Rx.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Mx_4jnAfl0xiTcee.png" /></figure><p>Everything is organized in the order you should actually learn it, so you always know what to study next instead of wondering where to begin.</p><p>If you’re serious about switching from your 9–5 job, growing as an engineer, or preparing for your next interview, I think you’ll find it genuinely useful.</p><p>You can explore it here: <a href="https://algorithmxlr8.io">https://algorithmxlr8.io</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf8a31212342" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>