<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aman Kumar</title>
    <description>The latest articles on DEV Community by Aman Kumar (@aman_kumar_bdd40f1b711c15).</description>
    <link>https://dev.to/aman_kumar_bdd40f1b711c15</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3548591%2Fa5ac2d01-7dbf-43d0-b88c-135aefc364f5.png</url>
      <title>DEV Community: Aman Kumar</title>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aman_kumar_bdd40f1b711c15"/>
    <language>en</language>
    <item>
      <title>Cursor Rules: Pay More Upfront, Iterate Less Later</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Tue, 10 Feb 2026 03:26:24 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/cursor-rules-pay-more-upfront-iterate-less-later-od9</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/cursor-rules-pay-more-upfront-iterate-less-later-od9</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: The hybrid rules approach that saves 70% on context loading and completes tasks in fewer iterations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Cursor AI is Loading Too Much
&lt;/h2&gt;

&lt;p&gt;Every time you ask Cursor for help, it loads your entire &lt;code&gt;.cursorrules&lt;/code&gt; file—even when most rules aren't relevant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slower responses (processing 5,000+ unnecessary tokens)&lt;/li&gt;
&lt;li&gt;Wasted context budget on rules you don't need&lt;/li&gt;
&lt;li&gt;Loading test patterns when writing docs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;There's a better way.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;Split your rules into two parts:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;AGENTS.md&lt;/strong&gt; (always loaded)
&lt;/h3&gt;

&lt;p&gt;Lightweight file with core principles that apply to every task.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;.cursor/rules/&lt;/strong&gt; (loaded intelligently)
&lt;/h3&gt;

&lt;p&gt;Detailed patterns that load only when relevant to your current file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AGENTS.md&lt;/strong&gt; (in project root):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# My TypeScript Project&lt;/span&gt;

&lt;span class="gu"&gt;## Core Workflow&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; RED → Write failing test
&lt;span class="p"&gt;2.&lt;/span&gt; GREEN → Minimal implementation  
&lt;span class="p"&gt;3.&lt;/span&gt; REFACTOR → Improve quality

&lt;span class="gu"&gt;## Critical Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Tests before implementation
&lt;span class="p"&gt;-&lt;/span&gt; TypeScript strict mode
&lt;span class="p"&gt;-&lt;/span&gt; 80% test coverage

&lt;span class="gu"&gt;## See Rules&lt;/span&gt;
Details: @tdd-workflow @testing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;.cursor/rules/testing.mdc&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Testing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;patterns&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;best&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;practices"&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.test.ts"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Testing Standards&lt;/span&gt;
[Detailed test patterns, examples, edge cases...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cursor always knows your TDD workflow &lt;/li&gt;
&lt;li&gt;When you edit test files, detailed patterns auto-load&lt;/li&gt;
&lt;li&gt;When you edit docs, testing rules stay dormant&lt;/li&gt;
&lt;li&gt;You get smart guidance without constant overhead&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get Started in 5 Minutes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create AGENTS.md&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# [Your Project]&lt;/span&gt;

&lt;span class="gu"&gt;## Workflow&lt;/span&gt;
[Your main development process]

&lt;span class="gu"&gt;## Critical Rules  &lt;/span&gt;
[Top 3-5 non-negotiable rules]

&lt;span class="gu"&gt;## See Rules&lt;/span&gt;
@rule-name-1 @rule-name-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create .cursor/rules/&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .cursor/rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Add focused rule files&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Testing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;patterns"&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.test.ts"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Your detailed testing rules here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Keep AGENTS.md under 50 lines. Everything else goes in &lt;code&gt;.cursor/rules/&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Token Trade-off: More Upfront, Less Overall
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Here's the honest truth&lt;/strong&gt;: Agent Mode with rules uses &lt;strong&gt;MORE tokens per session&lt;/strong&gt; but &lt;strong&gt;FEWER total tokens&lt;/strong&gt; to complete your task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without Rules:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attempt 1: 20K tokens → Wrong architecture
Attempt 2: 30K tokens → Tests need fixing
Attempt 3: 25K tokens → Finally correct
Total: ~75K tokens + frustration + your time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With Rules:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attempt 1: 70k-100k tokens → Done correctly
Total: ~100K tokens + confidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to Use Rules
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use Agent Mode + Rules when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building production features&lt;/li&gt;
&lt;li&gt;Architecture compliance matters&lt;/li&gt;
&lt;li&gt;Consistency is critical&lt;/li&gt;
&lt;li&gt;Your time is valuable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip Rules when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quick prototypes&lt;/li&gt;
&lt;li&gt;Exploring ideas&lt;/li&gt;
&lt;li&gt;Simple one-line changes&lt;/li&gt;
&lt;li&gt;You know exactly what to do&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Smart Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Phase 1: You Think (No Agent Mode)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write down requirements&lt;/li&gt;
&lt;li&gt;Identify edge cases&lt;/li&gt;
&lt;li&gt;Plan architecture&lt;/li&gt;
&lt;li&gt;Token cost: Minimal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 2: Agent Implements (With Rules)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide your spec&lt;/li&gt;
&lt;li&gt;Let AI execute with precision&lt;/li&gt;
&lt;li&gt;Review at checkpoints&lt;/li&gt;
&lt;li&gt;Token cost: Higher, but efficient&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: Rules don't replace your thinking—they ensure AI implements YOUR design correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Repository-Specific Rules Matter
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't copy-paste rules between projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each repository has unique:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File organization patterns&lt;/li&gt;
&lt;li&gt;Testing strategies
&lt;/li&gt;
&lt;li&gt;Architecture decisions&lt;/li&gt;
&lt;li&gt;Team conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Frontend: src/components/, src/hooks/, __tests__/
CLI Tool: src/commands/, src/services/, test/
Monorepo: apps/, packages/, libs/

→ Different structures = Different rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of rules as a &lt;strong&gt;custom onboarding document&lt;/strong&gt; for each repo. Invest 30 minutes per project to create tailored rules that reflect how THAT specific codebase works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Principles for Success
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Keep AGENTS.md Minimal
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Under 50 lines&lt;/strong&gt; with only what applies to 80%+ of tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Make Rules Focused
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;One concern per file&lt;/strong&gt;: testing.mdc, architecture.mdc, not everything.mdc&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use Smart Loading
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;covers"&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.test.ts"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;# Auto-load for test files&lt;/span&gt;
&lt;span class="na"&gt;alwaysApply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;           &lt;span class="c1"&gt;# Don't load everywhere&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Examples Over Essays
&lt;/h3&gt;

&lt;p&gt;Show one good pattern. AI learns from code, not paragraphs.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Gain
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before (single .cursorrules):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slower responses&lt;/li&gt;
&lt;li&gt;Context budget wasted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After (hybrid approach):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster AI responses&lt;/li&gt;
&lt;li&gt;Rules load only when relevant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But remember&lt;/strong&gt;: Agent Mode trades upfront tokens for fewer iterations. You spend more per session, but complete tasks in 1-2 tries instead of 5+.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Next Action
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;AGENTS.md&lt;/code&gt; with your top 5 rules &lt;strong&gt;today&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Move detailed patterns to &lt;code&gt;.cursor/rules/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Test it: Ask Cursor to build something and watch it follow your workflow automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your AI pair programmer will be smarter, faster, and more aligned with your team's patterns.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cursor.com/docs/context/rules" rel="noopener noreferrer"&gt;Cursor Rules Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/PatrickJS/awesome-cursorrules" rel="noopener noreferrer"&gt;Awesome Cursor Rules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>cursor</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Your MCP Server Sucks (And How to Fix It)</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Wed, 28 Jan 2026 22:20:01 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/why-your-mcp-server-sucks-and-how-to-fix-it-4dkn</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/why-your-mcp-server-sucks-and-how-to-fix-it-4dkn</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: MCP servers aren't failing because of the protocol—they're failing because developers treat them like REST APIs. Here's why that's wrong and how to fix it (explained for everyone, with minimal code).&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Are Enterprise MCP Servers Disappointing?
&lt;/h2&gt;

&lt;p&gt;Picture this: You've invested 6 months building an MCP server. The protocol works. The integration is live. Claude Desktop connects. Cursor connects.&lt;/p&gt;

&lt;p&gt;But when your AI agent tries to use it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🤖 Agent: "Track my order"
   Your MCP Server: "Here are 47 options. Good luck figuring it out!"
🤖 Agent: *confused* *picks wrong option* *fails*
❌ Result: Complete failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sound familiar?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Here's the twist: &lt;strong&gt;The protocol isn't broken. Your server design is.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fatal Mistake: Treating MCP Like a REST API
&lt;/h2&gt;

&lt;p&gt;For 20+ years, we've built APIs for human developers. Those principles don't work for AI agents.&lt;/p&gt;

&lt;p&gt;Think of it this way:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building for Humans&lt;/strong&gt; 👤&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read documentation once&lt;/li&gt;
&lt;li&gt;Remember relationships between data&lt;/li&gt;
&lt;li&gt;Debug when things go wrong&lt;/li&gt;
&lt;li&gt;Unlimited memory and patience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Building for AI Agents&lt;/strong&gt; 🤖&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Re-read descriptions with every request (expensive!)&lt;/li&gt;
&lt;li&gt;Get confused by too many choices&lt;/li&gt;
&lt;li&gt;Can't debug—just tries the same thing again&lt;/li&gt;
&lt;li&gt;Limited "memory" (context window)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Core Problem: Different Users, Different Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚗 The Car Analogy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;REST API = Manual Transmission&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Human drivers: "I love the control! 6 speeds, perfect."&lt;/li&gt;
&lt;li&gt;You learn once, drive forever&lt;/li&gt;
&lt;li&gt;Expert drivers prefer it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bad MCP Server = Manual with 47 Gears&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even experts get confused&lt;/li&gt;
&lt;li&gt;"Wait, am I in gear 23 or 24?"&lt;/li&gt;
&lt;li&gt;Constant grinding, failures&lt;/li&gt;
&lt;li&gt;Nobody can drive it reliably&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Good MCP Server = Automatic Transmission&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"I want to go from A to B"&lt;/li&gt;
&lt;li&gt;The system handles complexity&lt;/li&gt;
&lt;li&gt;Just works. Every time.&lt;/li&gt;
&lt;li&gt;Anyone can use it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Real-World Example: Order Tracking
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Old Way (Bad):&lt;/strong&gt; &lt;br&gt;
Your MCP server exposes 3 separate tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the customer&lt;/li&gt;
&lt;li&gt;Find their orders&lt;/li&gt;
&lt;li&gt;Check shipping status&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Agent has to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Figure out the right sequence&lt;/li&gt;
&lt;li&gt;Call each tool separately (3 round-trips)&lt;/li&gt;
&lt;li&gt;Remember results between calls&lt;/li&gt;
&lt;li&gt;Combine everything into an answer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Fails 40% of the time, takes 6+ seconds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New Way (Good):&lt;/strong&gt;&lt;br&gt;
Your MCP server exposes 1 tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;track_order(email)&lt;/code&gt; → Returns "Order #98765 shipped via Flipkart, arriving Thursday"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calls once&lt;/li&gt;
&lt;li&gt;Gets complete answer immediately&lt;/li&gt;
&lt;li&gt;Always works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Fails 2% of the time, takes 2 seconds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Same outcome. 3x faster. 20x more reliable.&lt;/strong&gt; &lt;/p&gt;


&lt;h2&gt;
  
  
  The Six Principles of Good MCP Servers
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Outcomes Over Operations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Wrong Thinking:&lt;/strong&gt; "I have 3 database tables, so I need 3 tools"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Right Thinking:&lt;/strong&gt; "Users want to track orders. I need 1 tool for that."&lt;/p&gt;


&lt;h3&gt;
  
  
  2. Keep It Simple (No Complex Inputs)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Menu Analogy:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad MCP Server Menu:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool: order_food
Input: A complex form with nested sections:
  - Customer info (name, address, phone, preferences)
  - Order details (items, quantities, modifications, special instructions)
  - Delivery info (time, address, contact, instructions)
  - Payment info (method, billing address, tip percentage)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent gets confused, fills it out wrong 60% of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good MCP Server Menu:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool: order_food
Inputs (simple, clear):
  - customer_email: john@example.com
  - item: "Cheeseburger"
  - delivery_time: "6:00 PM"
  - address: "123 Main St"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent fills it out correctly 95% of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key principle:&lt;/strong&gt; Simple, flat inputs = fewer mistakes&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Instructions Matter (Guide the Agent)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The GPS Analogy:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad GPS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Turn"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where? When? Which direction? You crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good GPS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"In 500 feet, turn right onto Main Street.
Use this when: You want to reach the mall
You'll know you're there when: You see the big parking lot"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clear, specific, helpful. You succeed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Same with MCP tools:&lt;/strong&gt; Every tool needs crystal-clear instructions on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When&lt;/strong&gt; to use it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How&lt;/strong&gt; to use it
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; you'll get back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What to do&lt;/strong&gt; if something goes wrong&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Less Is More (Curate Ruthlessly)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Netflix Paradox:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When Netflix shows you 10,000 movies, what happens?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You spend 30 minutes scrolling&lt;/li&gt;
&lt;li&gt;Get overwhelmed&lt;/li&gt;
&lt;li&gt;Watch nothing&lt;/li&gt;
&lt;li&gt;Or pick randomly and regret it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Netflix shows you 15 carefully curated picks "Because you watched..."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You find something in 2 minutes&lt;/li&gt;
&lt;li&gt;Higher satisfaction&lt;/li&gt;
&lt;li&gt;Better experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Same with MCP servers:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;50 tools&lt;/strong&gt; = Agent is overwhelmed, picks wrong one, fails&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;5-10 tools&lt;/strong&gt; = Agent finds right one immediately, succeeds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Golden Rule:&lt;/strong&gt; If you can't explain what each tool does in 10 seconds, you have too many.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Example:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before:&lt;/strong&gt; 50 tools for our CMS. Success rate: 31%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After:&lt;/strong&gt; 8 focused tools. Success rate: 89%&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. Names That Make Sense
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Coffee Shop Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine 3 coffee shops in one building, all with the same menu names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;☕ Shop A: "Coffee"
☕ Shop B: "Coffee"  
☕ Shop C: "Coffee"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You ask your assistant: "Get me coffee"&lt;br&gt;
They guess randomly. Wrong shop 67% of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now imagine clear names:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;☕ Starbucks: "Starbucks Coffee"
☕ Peet's: "Peets Coffee"
☕ Dunkin: "Dunkin Coffee"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You ask: "Get me Starbucks coffee"&lt;br&gt;
They get it right 99% of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Same with MCP tools:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Bad: &lt;code&gt;send_message()&lt;/code&gt; (Which service? Slack? Email? Teams?)&lt;/p&gt;

&lt;p&gt;✅ Good: &lt;code&gt;slack_send_message()&lt;/code&gt; (Crystal clear!)&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Don't Overwhelm with Data 📄
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Phone Book Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad approach:&lt;/strong&gt;&lt;br&gt;
"Show me everyone named John"&lt;br&gt;
→ Returns 10,000 results&lt;br&gt;
→ Your screen crashes&lt;br&gt;
→ You can't process it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good approach:&lt;/strong&gt;&lt;br&gt;
"Show me everyone named John"&lt;br&gt;
→ Returns first 20 results&lt;br&gt;
→ "Found 10,000 total. Here are the first 20. Want more?"&lt;br&gt;
→ You can actually use it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key principle:&lt;/strong&gt; Show digestible amounts, offer to show more if needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Insight
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MCP is not just another API. It's a User Interface—for AI agents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you build a regular UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You think about user experience&lt;/li&gt;
&lt;li&gt;You simplify complex workflows&lt;/li&gt;
&lt;li&gt;You guide users with clear labels&lt;/li&gt;
&lt;li&gt;You test with real users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Do the same for your MCP server:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Think about agent experience&lt;/li&gt;
&lt;li&gt;Simplify complex operations into single tools&lt;/li&gt;
&lt;li&gt;Guide agents with clear descriptions&lt;/li&gt;
&lt;li&gt;Test with real agents&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Quick Self-Check
&lt;/h2&gt;

&lt;p&gt;Ask yourself these simple questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Can an AI accomplish user goals in 1-2 steps?&lt;/strong&gt; (Not 5+ steps)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do you have fewer than 15 tools?&lt;/strong&gt; (5-10 is ideal)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are inputs simple?&lt;/strong&gt; (No complex nested forms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do tools have clear instructions?&lt;/strong&gt; (When and how to use them)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do you limit response sizes?&lt;/strong&gt; (Show 20, not 2,000 items)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;If you answered "no" to any of these, your server needs work.&lt;/strong&gt; 🔧&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Steps to Fix Your Server
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit&lt;/strong&gt; - Test your MCP server. Where does it fail?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consolidate&lt;/strong&gt; - Find 3-5 tools you can merge into 1 outcome-focused tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplify&lt;/strong&gt; - Remove one layer of complexity from your most-used tool&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Start small. Fix one tool. Measure improvement. Repeat.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You don't need to rebuild everything at once. Every improvement helps.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Building a good MCP server is like building a good UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Know your user&lt;/strong&gt; (it's an AI agent, not a human)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplify ruthlessly&lt;/strong&gt; (fewer choices = better outcomes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guide clearly&lt;/strong&gt; (instructions matter)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with real users&lt;/strong&gt; (run it with actual agents)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The protocol works fine. Build your server right, and your AI will actually be useful.&lt;/strong&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Your Turn!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Are you building with MCP?&lt;/strong&gt; Share your experience in the comments!&lt;/p&gt;

&lt;p&gt;Questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's your biggest MCP challenge?&lt;/li&gt;
&lt;li&gt;Have you seen agents struggle with your tools?&lt;/li&gt;
&lt;li&gt;Which principle surprised you most?&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;P.P.S. - Thanks to &lt;a href="https://www.philschmid.de/mcp-best-practices" rel="noopener noreferrer"&gt;Philipp Schmid&lt;/a&gt; for the research that inspired this post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>llm</category>
      <category>cursor</category>
    </item>
    <item>
      <title>Why Client-Side Rate Limiting is Your API's Best Friend 🤝</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Sat, 24 Jan 2026 07:46:25 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/why-client-side-rate-limiting-is-your-apis-best-friend-4g9h</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/why-client-side-rate-limiting-is-your-apis-best-friend-4g9h</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: We reduced API failures from 38% to 0.2% by implementing smart client-side rate limiting. Here's why it matters and how it works (explained for everyone, not just engineers).&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Did Our Tool Keep Failing?
&lt;/h2&gt;

&lt;p&gt;Picture this: You're a content manager at a large company. It's 9 AM Monday. You need to publish 10,000 blog posts to your CMS before the marketing campaign launches at noon.&lt;/p&gt;

&lt;p&gt;You run the bulk publish command, grab coffee ☕, and return 20 minutes later expecting good news.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❌ Failed: 3,847 out of 10,000 entries
⚠️  Rate limit exceeded
⚠️  Please try again later
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Uh oh.&lt;/strong&gt; It's 9:30 AM. Campaign launch in 2.5 hours. You're sweating. 😰&lt;/p&gt;

&lt;p&gt;This was a real problem our users faced. And it wasn't their fault—it was ours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Culprit: We Were Being a Bad API Neighbor
&lt;/h2&gt;

&lt;p&gt;Imagine you're at a coffee shop. There are 100 people in line. Everyone's polite, ordering one at a time.&lt;/p&gt;

&lt;p&gt;Suddenly, 10 people rush to the counter simultaneously, all shouting orders. The barista gets overwhelmed, stops serving everyone, and puts up a sign: &lt;strong&gt;"CLOSED - Come back in 30 minutes"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's basically what our old CLI was doing to APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our Old Approach (The Bad Neighbor):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fixed speed&lt;/strong&gt;: Always drove at 60 mph, even in school zones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stubborn retries&lt;/strong&gt;: Failed twice? Give up immediately
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loud and proud&lt;/strong&gt;: When one request fails, ALL retries happen at once&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No learning&lt;/strong&gt;: Kept making the same mistakes over and over&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result?&lt;/strong&gt; 38% failure rate. Users had to manually retry thousands of times. Not cool.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Four Layers of "Being Polite" to APIs
&lt;/h2&gt;

&lt;p&gt;We rebuilt our system with four simple principles that work together like a well-oiled machine:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Four-Layer Approach
&lt;/h3&gt;

&lt;p&gt;Think of it like defensive driving with a GPS that warns you about traffic ahead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Layer 0 - Listen to Traffic Reports&lt;/strong&gt; (Real-Time Intelligence)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The API tells us: "I'm getting busy, slow down!"&lt;/li&gt;
&lt;li&gt;We proactively adjust BEFORE hitting any limits&lt;/li&gt;
&lt;li&gt;Like having a co-pilot who sees problems before you do&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Layer 1 - Speed Governor&lt;/strong&gt; (Prevention)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't go too fast in the first place&lt;/li&gt;
&lt;li&gt;Slow down automatically when you see trouble ahead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Layer 2 - Smart Braking&lt;/strong&gt; (Recovery)  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If something goes wrong, back off intelligently&lt;/li&gt;
&lt;li&gt;Don't try the same thing immediately&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Layer 3 - Avoid Traffic Jams&lt;/strong&gt; (Coordination)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't retry at the exact same time as everyone else&lt;/li&gt;
&lt;li&gt;Spread out the load&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Layer 0: Real-Time Intelligence (Server Header Integration)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This is the secret weapon!&lt;/strong&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  The GPS Analogy
&lt;/h3&gt;

&lt;p&gt;Imagine driving to work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without GPS (Old way):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You drive at the speed limit&lt;/li&gt;
&lt;li&gt;Hit traffic jam unexpectedly&lt;/li&gt;
&lt;li&gt;Now you're stuck! &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With GPS (New way with headers):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPS: "Traffic building up ahead, slow down now"&lt;/li&gt;
&lt;li&gt;You slow down BEFORE the traffic&lt;/li&gt;
&lt;li&gt;You smoothly merge into the slower lane&lt;/li&gt;
&lt;li&gt;Never get stuck!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How API Headers Work
&lt;/h3&gt;

&lt;p&gt;Modern APIs are like that GPS—they send you real-time traffic reports with every response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Every API response includes these "traffic reports"&lt;/span&gt;
&lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="nx"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ratelimit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;        &lt;span class="c1"&gt;// Speed limit: 10 requests/second&lt;/span&gt;
  &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ratelimit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;     &lt;span class="c1"&gt;// Only 3 "slots" left this second&lt;/span&gt;
  &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ratelimit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1732108801&lt;/span&gt; &lt;span class="c1"&gt;// Traffic clears at this timestamp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Magic: Proactive Slowdown
&lt;/h3&gt;

&lt;p&gt;Here's what makes this brilliant:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional approach (blind driving):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1 → Success (you don't know you're running out of quota)
Request 2 → Success (still no warning)
Request 3 → Success (uh oh, almost there)
Request 4 → 429 RATE LIMIT! (crash!)
Request 5 → 429 again! (stuck in traffic)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Our smart approach (with headers):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1 → Success 
  ← Headers say: "8/10 remaining" 
  → You: "Cool, I'm good"

Request 2 → Success
  ← Headers say: "3/10 remaining" 
  → You: "Whoa! Traffic ahead! Slowing down to 4 req/sec"

Request 3 → Success (slower pace)
  ← Headers say: "7/10 remaining" 
  → You: "Traffic clearing! Speeding up to 6 req/sec"

Request 4 → Success
  ← Headers say: "8/10 remaining"
  → You: "All clear! Back to 10 req/sec"

Result: ZERO 429 errors! 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example
&lt;/h3&gt;

&lt;p&gt;Publishing 5,000 blog posts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;9:00:00 AM - Start publishing at 10 req/sec
            ↓
9:00:01 AM - Header: "8/10 remaining" ✅ All good
            ↓
9:00:03 AM - Header: "2/10 remaining" ⚠️ Getting low!
            → Proactively throttle to 4 req/sec
            ↓
9:00:05 AM - Header: "6/10 remaining" ✅ Recovering
            → Gradually increase to 7 req/sec
            ↓
9:00:10 AM - Header: "9/10 remaining" ✅ Fully recovered
            → Back to 10 req/sec

RESULT: Published all 5,000 with ZERO 429 errors!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This is a Game-Changer
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Without headers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guessing the safe speed&lt;/li&gt;
&lt;li&gt;Hit 429 errors (average 38 per 5,000 requests)&lt;/li&gt;
&lt;li&gt;Waste time on retries&lt;/li&gt;
&lt;li&gt;Frustrating experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With headers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know EXACTLY how much quota remains&lt;/li&gt;
&lt;li&gt;Prevent 429 errors BEFORE they happen (down to 0-4 errors)&lt;/li&gt;
&lt;li&gt;Optimal speed (never too slow, never too fast)&lt;/li&gt;
&lt;li&gt;Smooth, predictable experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;It's like having X-ray vision into the API's capacity!&lt;/strong&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: The Smart Speed Governor (Token Bucket + Sliding Window)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Coffee Shop Analogy
&lt;/h3&gt;

&lt;p&gt;Imagine you have a &lt;strong&gt;token bucket&lt;/strong&gt; full of coffee vouchers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with 20 vouchers (burst capacity)&lt;/li&gt;
&lt;li&gt;Use 1 voucher per order&lt;/li&gt;
&lt;li&gt;Get 10 new vouchers every second (refill rate)&lt;/li&gt;
&lt;li&gt;Can't exceed 20 vouchers total&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can handle a rush (use 20 vouchers quickly)&lt;/li&gt;
&lt;li&gt;Then you settle into a steady pace (10 per second)&lt;/li&gt;
&lt;li&gt;You never overwhelm the barista&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Adaptive Part (The Secret Sauce!)
&lt;/h3&gt;

&lt;p&gt;Here's where it gets smart. Our system &lt;strong&gt;learns and adapts&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When things go well:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 successful orders → Speed up by 5%
Another 10 successes → Speed up another 5%
Keep improving until you hit the speed limit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When you get rate limited:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Got rejected? → Slow down by 30%
Rejected again? → Slow down another 30%
10 rejections in a row? → STOP. Take a 5-second break
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-world example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;9:00 AM → Start at 10 requests/second
9:01 AM → Got rate limited! Drop to 7 req/sec
9:03 AM → Things stable. Increase to 7.35 req/sec
9:05 AM → Still good. Increase to 7.7 req/sec
9:10 AM → Back to 10 req/sec (fully recovered)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's like cruise control that automatically slows down on curvy roads and speeds up on straightaways!&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2: Exponential Backoff (The "Back Off, Buddy" Strategy)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Wisdom of Waiting
&lt;/h3&gt;

&lt;p&gt;When something fails, &lt;strong&gt;don't try the exact same thing immediately&lt;/strong&gt;. That's the definition of insanity!&lt;/p&gt;

&lt;p&gt;Instead, wait progressively longer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attempt 1: Failed → Wait 1 second
Attempt 2: Failed → Wait 2 seconds  
Attempt 3: Failed → Wait 4 seconds
Attempt 4: Failed → Wait 8 seconds
Attempt 5: Failed → Wait 16 seconds
Attempt 6: Failed → Give up (or wait 32 seconds max)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gives the API time to recover&lt;/li&gt;
&lt;li&gt;Reduces server load during problems&lt;/li&gt;
&lt;li&gt;Shows respect to the service you're using&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Jitter Secret (Preventing Traffic Jams)
&lt;/h3&gt;

&lt;p&gt;Here's a problem: What if 1,000 people all fail at the same time and all wait exactly 2 seconds?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without randomization:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────┐
│ 9:00:00 → 1,000 requests → ALL FAIL     │
│ 9:00:02 → 1,000 retries  → ALL FAIL     │
│ 9:00:06 → 1,000 retries  → ALL FAIL     │
└─────────────────────────────────────────┘
         Problem NEVER gets solved! 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With randomization (jitter):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────┐
│ 9:00:00 → 1,000 requests → ALL FAIL     │
│ 9:00:01.6 → 50 retries   → Success ✓    │
│ 9:00:01.9 → 100 retries  → Success ✓    │
│ 9:00:02.1 → 150 retries  → Success ✓    │
│ 9:00:02.4 → 200 retries  → Success ✓    │
│   ... spread across 800ms window        │
└─────────────────────────────────────────┘
         Smooth recovery! 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We add ±20% randomness to prevent everyone from retrying at once. It's like zipper merging in traffic—much more efficient!&lt;/p&gt;




&lt;h2&gt;
  
  
  How All Four Layers Work Together
&lt;/h2&gt;

&lt;p&gt;Let's follow a single request through the system:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Perfect Path (With Server Headers)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Request arrives
2. Token available? → YES
3. Make API call → SUCCESS
4. Read response headers: "7/10 remaining"
5. Rate limiter: "Good capacity! Staying at current speed"
6. Process next request smoothly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Proactive Path (Headers Prevent Problems)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Request arrives
2. Token available? → YES
3. Make API call → SUCCESS
4. Read response headers: "2/10 remaining" ⚠️
5. Rate limiter: "Whoa! Getting low! Reducing speed by 60%"
6. NEW SPEED: 10 → 4 req/sec
7. Next requests are slower
8. Later headers show: "6/10 remaining" ✅
9. Rate limiter: "Traffic clearing! Gradually increasing speed"
10. ZERO 429 errors encountered!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Recovery Path (If Headers Aren't Available or We Miss Them)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Request arrives  
2. Token available? → YES
3. Make API call → 429 RATE LIMIT!
4. Tell rate limiter: "We got rejected!"
5. Rate limiter: "Oops! I'll slow down by 30%"
6. Wait 2.3 seconds (with jitter)
7. Try again → SUCCESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Circuit Breaker Path (Serious Problems)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1-10. Ten requests in a row → ALL FAIL
11. Rate limiter: "STOP EVERYTHING!"
12. Reduce speed to 10% of original
13. Take a 5-second coffee break ☕
14. Resume slowly
15. Gradually recover as things improve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it like a self-driving car:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Layer 0&lt;/strong&gt;: GPS warns about traffic ahead (headers)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 1&lt;/strong&gt;: Cruise control maintains safe speed (token bucket)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 2&lt;/strong&gt;: Automatic braking when needed (exponential backoff)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 3&lt;/strong&gt;: Anti-collision system prevents pile-ups (jitter)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Should YOU Care?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Developers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Better User Experience:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users don't need to understand rate limits&lt;/li&gt;
&lt;li&gt;"It just works" out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Automatic recovery from transient failures
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Bigger Picture: Being a Good API Citizen
&lt;/h2&gt;

&lt;p&gt;This isn't just about making our tool work better. It's about &lt;strong&gt;playing nice in a shared ecosystem&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six Key Principles (For Everyone!)
&lt;/h2&gt;

&lt;p&gt;Whether you're building a CLI tool, web app, or mobile app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Listen First&lt;/strong&gt; - Check what the API is telling you (use rate limit headers!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect Speed Limits&lt;/strong&gt; - Just like driving, follow the rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn from Mistakes&lt;/strong&gt; - If you fail, adapt your behavior
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Patient&lt;/strong&gt; - Sometimes waiting is faster than rushing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Rush Hour&lt;/strong&gt; - Spread out your requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Know When to Stop&lt;/strong&gt; - Don't keep trying if something's really broken&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Four Things to Remember
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Listen &amp;gt; Guess&lt;/strong&gt; - Use rate limit headers when available for perfect information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prevention &amp;gt; Reaction&lt;/strong&gt; - Don't wait for errors, control your speed proactively&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adapt &amp;gt; Assume&lt;/strong&gt; - API capacity varies; adjust based on real feedback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordinate &amp;gt; Compete&lt;/strong&gt; - When multiple clients fail, don't all retry at once&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  💬 Your Turn!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Have you dealt with rate limiting nightmares?&lt;/strong&gt; Share your stories in the comments! &lt;/p&gt;

&lt;p&gt;Questions I'd love to discuss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's your worst API rate limit horror story?&lt;/li&gt;
&lt;li&gt;How do you handle rate limits in your projects?&lt;/li&gt;
&lt;li&gt;Are you using client-side rate limiting? Why or why not?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Want to Learn More?
&lt;/h2&gt;

&lt;p&gt;For the technically curious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Token_bucket" rel="noopener noreferrer"&gt;How Token Bucket Algorithm Works&lt;/a&gt; - Visual explanation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/" rel="noopener noreferrer"&gt;AWS on Exponential Backoff and Jitter&lt;/a&gt; - From the experts&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>softwareengineering</category>
      <category>api</category>
      <category>backend</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>From Monolithic CLIs to Modular Plugins: Applying the Strangler Fig Pattern</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Thu, 04 Dec 2025 03:41:49 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/from-monolithic-clis-to-modular-plugins-applying-the-strangler-fig-pattern-3gok</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/from-monolithic-clis-to-modular-plugins-applying-the-strangler-fig-pattern-3gok</guid>
      <description>&lt;h3&gt;
  
  
  How the same patterns that saved backend APIs can transform your CLI architecture
&lt;/h3&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 TL;DR - The Safe Migration Strategy:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract commands to &lt;strong&gt;external plugins&lt;/strong&gt; (publish as beta)&lt;/li&gt;
&lt;li&gt;Add plugins as &lt;strong&gt;dependencies&lt;/strong&gt; in your core (v2.x - zero breaking changes)&lt;/li&gt;
&lt;li&gt;Gather feedback, iterate, stabilize&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove dependencies&lt;/strong&gt; in v3.0.0 (breaking change, but prepared)&lt;/li&gt;
&lt;li&gt;Users install &lt;strong&gt;only what they need&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Result: Safe migration + independent plugin evolution &lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Remember when your CLI was just a little tool with 3 commands? Yeah, me too. &lt;/p&gt;

&lt;p&gt;Then product asked for "just one more feature"... and another... and another. Now you're maintaining a 50-command behemoth where changing one line breaks three unrelated commands. Welcome to the &lt;strong&gt;CLI monolith trap&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the thing: &lt;strong&gt;CLIs go through the exact same evolution as backend APIs&lt;/strong&gt;. And guess what? The same architectural patterns that rescued backend teams work beautifully for CLIs too.&lt;/p&gt;

&lt;p&gt;In this post, I'll show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why CLI monoliths form (spoiler: it's inevitable)&lt;/li&gt;
&lt;li&gt;How plugin architectures mirror microservices&lt;/li&gt;
&lt;li&gt;How to use the Strangler Fig Pattern for safe migration&lt;/li&gt;
&lt;li&gt;Real benefits you'll see immediately&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Problem: How CLIs Become Unmaintainable
&lt;/h2&gt;

&lt;p&gt;Your CLI probably started like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cli/
├── commands/
│   ├── deploy.js
│   └── status.js
├── utils/
│   └── helpers.js
└── index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean. Simple. Everything in its place.&lt;/p&gt;

&lt;p&gt;Six months later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cli/
├── commands/ &lt;span class="o"&gt;(&lt;/span&gt;37 files&lt;span class="o"&gt;)&lt;/span&gt;
├── utils/ &lt;span class="o"&gt;(&lt;/span&gt;23 files&lt;span class="o"&gt;)&lt;/span&gt;
├── services/ &lt;span class="o"&gt;(&lt;/span&gt;15 files&lt;span class="o"&gt;)&lt;/span&gt;
├── integrations/ &lt;span class="o"&gt;(&lt;/span&gt;12 files&lt;span class="o"&gt;)&lt;/span&gt;
└── shared/ &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;who &lt;/span&gt;even knows?&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now you're dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tight coupling&lt;/strong&gt; - Every command imports 10+ utility files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared state nightmares&lt;/strong&gt; - Global config that everything touches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risky releases&lt;/strong&gt; - One change requires testing the entire CLI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow development&lt;/strong&gt; - Adding features takes weeks of coordination&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Breaking change hell&lt;/strong&gt; - Can't evolve one part without breaking everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound painfully familiar? &lt;strong&gt;You've built a monolith.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 The Backend Lesson: From Monoliths to Modularity
&lt;/h2&gt;

&lt;p&gt;The backend world already solved this problem. Let me show you the evolution:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Old Way (Monolithic API)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Everything in one codebase
↓
Tightly coupled domains
↓
Coordinated releases
↓
High-risk deployments
↓
Slow feature velocity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Modern Way (Microservices/Modular)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thin API Gateway
↓
Isolated domain services
↓
Independent deployments
↓
Versioned contracts
↓
Fast, safe iterations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The key insight?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Isolate domains. Establish clear boundaries. Enable independent evolution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Here's the beautiful part:&lt;/strong&gt; This works for CLIs too! &lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ The Solution: Core + Plugins Architecture
&lt;/h2&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core = API Gateway&lt;/strong&gt; (stable, lightweight, routing layer)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugins = Microservices&lt;/strong&gt; (isolated domains with independent lifecycles)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Thin Core
&lt;/h3&gt;

&lt;p&gt;Your core should be &lt;em&gt;boring&lt;/em&gt; and stable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;           &lt;span class="c1"&gt;// Auth logic&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;         &lt;span class="c1"&gt;// Config management  &lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;dispatcher&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;     &lt;span class="c1"&gt;// Command routing&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;          &lt;span class="c1"&gt;// Cross-cutting concerns&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;  &lt;span class="c1"&gt;// Plugin discovery&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That's it.&lt;/strong&gt; The core provides infrastructure and gets out of the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Plugins
&lt;/h3&gt;

&lt;p&gt;Each plugin is a self-contained domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;deploy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;README&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;  &lt;span class="c1"&gt;// Independent versioning!&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Each plugin:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owns exactly one responsibility&lt;/li&gt;
&lt;li&gt;Has its own semantic version&lt;/li&gt;
&lt;li&gt;Installs independently (&lt;code&gt;npm i @cli/deploy-plugin&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Changes without affecting others&lt;/li&gt;
&lt;li&gt;Tests in complete isolation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌳 The Migration Strategy: Strangler Fig Pattern
&lt;/h2&gt;

&lt;p&gt;"Cool story," you're thinking, "but I have a 50k-line CLI. I'm not rewriting everything."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good news: You don't have to!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Enter the &lt;strong&gt;Strangler Fig Pattern&lt;/strong&gt; (from Martin Fowler). It lets you migrate gradually without a risky big-bang rewrite.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;The pattern is named after strangler fig trees that grow around other trees, eventually replacing them. Same concept for code.&lt;/p&gt;

&lt;p&gt;Here's how to apply it to your CLI:&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1: Release External Plugins in Beta
&lt;/h3&gt;

&lt;p&gt;Start by extracting functionality into &lt;strong&gt;external plugins&lt;/strong&gt; and release them in beta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Release your first plugin in beta&lt;/span&gt;
npm publish @my-cli/deploy-plugin@1.0.0-beta.1
npm publish @my-cli/logs-plugin@1.0.0-beta.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why beta?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users can opt-in to test&lt;/li&gt;
&lt;li&gt;You can iterate quickly&lt;/li&gt;
&lt;li&gt;Breaking changes are expected&lt;/li&gt;
&lt;li&gt;Gives you real-world feedback
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// deploy-plugin/package.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@my-cli/deploy-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0-beta.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;peerDependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@my-cli/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^2.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2: Add Plugins as Dependencies in Core (Temporarily)
&lt;/h3&gt;

&lt;p&gt;During migration, include plugins as &lt;strong&gt;dependencies&lt;/strong&gt; in your core package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;core/package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@my-cli/core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.5.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Legacy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;plugins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;bundled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;during&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;migration&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@my-cli/deploy-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.0-beta.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@my-cli/logs-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.0-beta.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users install core → plugins come along automatically&lt;/li&gt;
&lt;li&gt;No breaking changes for existing users&lt;/li&gt;
&lt;li&gt;Plugins work standalone for early adopters&lt;/li&gt;
&lt;li&gt;You validate the plugin architecture safely&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 3: Gradually Migrate Commands
&lt;/h3&gt;

&lt;p&gt;Track your progress as you extract:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;v2.5.0 (Initial Beta)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; deploy  → Plugin (bundled as dependency)
 logs    → Legacy in core
 backup  → Legacy in core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;v2.8.0 (Beta 2)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; deploy  → Plugin (bundled as dependency)
 logs    → Plugin (bundled as dependency)
 backup  → Legacy in core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ships to production safely&lt;/li&gt;
&lt;li&gt;Users see no difference&lt;/li&gt;
&lt;li&gt;Plugins mature in the wild&lt;/li&gt;
&lt;li&gt;You gather feedback&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 4: The Big Switch - Remove Dependencies (v3.0.0)
&lt;/h3&gt;

&lt;p&gt;Once all plugins are stable, release a &lt;strong&gt;breaking change&lt;/strong&gt; that removes plugin dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;core/package.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;v&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@my-cli/core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dependencies!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"peerDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Plugins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;optional&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Migration guide for users:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Old way (v2.x) - everything bundled&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/core

&lt;span class="c"&gt;# New way (v3.x) - install what you need&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/core
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/deploy-plugin  &lt;span class="c"&gt;# Only if you need deploy&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/logs-plugin    &lt;span class="c"&gt;# Only if you need logs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this is a major version:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breaking change: plugins no longer auto-installed&lt;/li&gt;
&lt;li&gt;Users must explicitly install plugins they use&lt;/li&gt;
&lt;li&gt;But: more control, smaller footprint, faster installs&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 5: Users Install According to Their Needs
&lt;/h3&gt;

&lt;p&gt;Now users have &lt;strong&gt;full control&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Minimal installation (just core utilities)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/core

&lt;span class="c"&gt;# À la carte (only what I use)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/core @my-cli/deploy-plugin

&lt;span class="c"&gt;# Everything (opt-in to all plugins)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/all  &lt;span class="c"&gt;# Metapackage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller installations (15MB vs 250MB)&lt;/li&gt;
&lt;li&gt;Faster startup (fewer plugins to load)&lt;/li&gt;
&lt;li&gt;Better security (only install trusted plugins)&lt;/li&gt;
&lt;li&gt;Independent updates (update deploy plugin without touching core)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Result: Independent Plugin Releases
&lt;/h2&gt;

&lt;p&gt;Once your plugins are stable and external, this is where the magic happens:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Old Way (v2.x - bundled):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Breaking change in deploy command&lt;/span&gt;
&lt;span class="c"&gt;# Forces major version bump for ENTIRE CLI&lt;/span&gt;
npm publish @my-cli/core@3.0.0

&lt;span class="c"&gt;# Now everyone needs to:&lt;/span&gt;
&lt;span class="c"&gt;# - Update the entire CLI&lt;/span&gt;
&lt;span class="c"&gt;# - Regression test everything&lt;/span&gt;
&lt;span class="c"&gt;# - Coordinate with all teams&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The New Way (v3.x - modular):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Breaking change in deploy plugin only&lt;/span&gt;
npm publish @my-cli/deploy-plugin@3.0.0

&lt;span class="c"&gt;# Everything else?&lt;/span&gt;
&lt;span class="c"&gt;# - Core stays at v3.x&lt;/span&gt;
&lt;span class="c"&gt;# - Logs plugin stays at v1.5.3&lt;/span&gt;
&lt;span class="c"&gt;# - Backup plugin stays at v2.1.0&lt;/span&gt;
&lt;span class="c"&gt;# - Zero cross-testing needed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is massive&lt;/strong&gt; for teams with multiple stakeholders! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even better:&lt;/strong&gt; Users who don't use deploy aren't affected at all!&lt;/p&gt;




&lt;h2&gt;
  
  
  End State: Minimal Core, Maximum Flexibility
&lt;/h2&gt;

&lt;p&gt;After migration, your core becomes tiny and stable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Final core: ~500 lines total&lt;/span&gt;
&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;        &lt;span class="c1"&gt;// 150 lines&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;      &lt;span class="c1"&gt;// 120 lines  &lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;  &lt;span class="c1"&gt;// 100 lines&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;      &lt;span class="c1"&gt;// 80 lines&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;       &lt;span class="c1"&gt;// 50 lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything else lives in plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;plugins/
├── @my-cli/deploy-plugin   &lt;span class="o"&gt;(&lt;/span&gt;v2.0.0&lt;span class="o"&gt;)&lt;/span&gt;
├── @my-cli/logs-plugin     &lt;span class="o"&gt;(&lt;/span&gt;v1.5.3&lt;span class="o"&gt;)&lt;/span&gt;
├── @my-cli/backup-plugin   &lt;span class="o"&gt;(&lt;/span&gt;v3.1.0&lt;span class="o"&gt;)&lt;/span&gt;
├── @my-cli/migrate-plugin  &lt;span class="o"&gt;(&lt;/span&gt;v1.0.0-beta.2&lt;span class="o"&gt;)&lt;/span&gt;
└── @my-cli/docs-plugin     &lt;span class="o"&gt;(&lt;/span&gt;v2.2.1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The core is now:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to maintain (rarely changes)&lt;/li&gt;
&lt;li&gt;Easy to test (minimal surface area)&lt;/li&gt;
&lt;li&gt;Easy to understand (just infrastructure)&lt;/li&gt;
&lt;li&gt;Boring (in the best way!)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Benefits: Why This Matters
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Faster Release Velocity
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We need to schedule a CLI release. When can everyone test their parts? How about 2 weeks from now?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Deploy plugin v2.4.0 is live. Changelog in Slack. Carry on!"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Isolated Breaking Changes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One breaking change → Entire CLI bumps to v3.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One breaking change → That plugin bumps to v3.0.0
                    → Everything else stays put
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Users Install Only What They Need
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; my-cli
&lt;span class="c"&gt;# Downloads: 250MB (includes 30 commands you never use)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/core           &lt;span class="c"&gt;# 12MB&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/deploy-plugin  &lt;span class="c"&gt;# 8MB&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/logs-plugin    &lt;span class="c"&gt;# 5MB&lt;/span&gt;
&lt;span class="c"&gt;# Downloads: 25MB (only what you need!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Faster installs. Smaller footprint. Happier users. &lt;/p&gt;




&lt;h3&gt;
  
  
  🤔 "Won't this break my existing users?"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Not with the beta approach!&lt;/strong&gt; That's the beauty of it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;v2.x:&lt;/strong&gt; Plugins bundled as dependencies → Zero breaking changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v3.x:&lt;/strong&gt; Plugins separate → Breaking change, but well-communicated&lt;/li&gt;
&lt;li&gt;Users get months to prepare during the beta phase&lt;/li&gt;
&lt;li&gt;Migration guide makes the transition smooth&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  "Why not just make v3.0 immediately?"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Risk management!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;By bundling plugins as dependencies in v2.x first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You prove the plugin architecture works&lt;/li&gt;
&lt;li&gt;Users can test beta plugins early&lt;/li&gt;
&lt;li&gt;You gather real-world feedback&lt;/li&gt;
&lt;li&gt;No one's workflow breaks during migration&lt;/li&gt;
&lt;li&gt;The v3.0 switch is just removing deps (lower risk)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  "What about users who want everything?"
&lt;/h3&gt;

&lt;p&gt;Create a &lt;strong&gt;metapackage&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@my-cli/all/package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@my-cli/all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@my-cli/core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@my-cli/deploy-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@my-cli/logs-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.5.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@my-cli/backup-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.1.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @my-cli/all  &lt;span class="c"&gt;# One command, everything installed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Best of both worlds!&lt;/p&gt;




&lt;h3&gt;
  
  
  "How do I handle shared code between plugins?"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used by &lt;strong&gt;one plugin&lt;/strong&gt; → Keep it in the plugin&lt;/li&gt;
&lt;li&gt;Used by &lt;strong&gt;two plugins&lt;/strong&gt; → Maybe extract to &lt;code&gt;@my-cli/shared&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;Used by &lt;strong&gt;three+ plugins&lt;/strong&gt; → Belongs in core utilities&lt;/li&gt;
&lt;li&gt;Used by &lt;strong&gt;external plugins&lt;/strong&gt; → Definitely in core (stable API)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  "What if I'm building a new CLI from scratch?"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Even better!&lt;/strong&gt; Start with the plugin architecture from day one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the thin core first&lt;/li&gt;
&lt;li&gt;Make your first command a plugin (proves the pattern)&lt;/li&gt;
&lt;li&gt;Release everything as stable v1.0.0 together&lt;/li&gt;
&lt;li&gt;Every new feature becomes a new plugin&lt;/li&gt;
&lt;li&gt;Future you will be &lt;strong&gt;so grateful&lt;/strong&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;But:&lt;/strong&gt; Still consider releasing as a monolith initially (v1.x), then split in v2.x once you understand usage patterns.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Changed?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefits you get immediately:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear interface&lt;/strong&gt; - Plugin contract vs monolith spaghetti&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Injected dependencies&lt;/strong&gt; - No more deep imports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-contained logic&lt;/strong&gt; - Plugin owns its domain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trivial testing&lt;/strong&gt; - Mock the context, done&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent releases&lt;/strong&gt; - Deploy updates without touching core&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller installs&lt;/strong&gt; - 25MB vs 250MB&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;CLIs are going through the same architectural evolution that backend systems experienced years ago:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;From&lt;/th&gt;
&lt;th&gt;To&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monolithic&lt;/td&gt;
&lt;td&gt;Modular&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tightly Coupled&lt;/td&gt;
&lt;td&gt;Plugin-Based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coordinated Releases&lt;/td&gt;
&lt;td&gt;Independent Lifecycles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risky Changes&lt;/td&gt;
&lt;td&gt;Isolated Changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slow Development&lt;/td&gt;
&lt;td&gt;Fast Iterations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;Strangler Fig Pattern with Beta Releases&lt;/strong&gt; gives you a safe, incremental path to get there &lt;strong&gt;without a risky rewrite&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The secret sauce:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract to external plugins (beta)&lt;/li&gt;
&lt;li&gt;Bundle them temporarily (v2.x - safe transition)&lt;/li&gt;
&lt;li&gt;Remove dependencies (v3.0.0 - breaking change, but prepared)&lt;/li&gt;
&lt;li&gt;Independent evolution forever&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By keeping your core thin and moving features into independent plugins, you create a CLI that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easier to maintain&lt;/strong&gt; - Smaller, focused codebases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safer to extend&lt;/strong&gt; - Changes are isolated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster to iterate&lt;/strong&gt; - No coordination needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More stable for users&lt;/strong&gt; - Breaking changes are scoped&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future-proof&lt;/strong&gt; - New plugins without touching core&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lighter weight&lt;/strong&gt; - Install only what you need&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building or maintaining a CLI, &lt;strong&gt;modularity isn't optional anymore - it's your architectural advantage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start today:&lt;/strong&gt; Extract one command to a beta plugin. See how it feels. You'll never look back.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you hit the CLI monolith wall?&lt;/strong&gt; What's your biggest pain point with CLI architecture?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thinking about plugins?&lt;/strong&gt; What's holding you back?&lt;/p&gt;




</description>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>How Airline Group Fares Really Work: The Business &amp; Tech Behind 'TBA' Passenger Names</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Fri, 07 Nov 2025 12:48:48 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/how-airline-group-fares-really-work-the-business-tech-behind-tba-passenger-names-4mo9</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/how-airline-group-fares-really-work-the-business-tech-behind-tba-passenger-names-4mo9</guid>
      <description>&lt;p&gt;If you've ever seen &lt;strong&gt;"TBA/TBA"&lt;/strong&gt; as a passenger name in a flight booking, it's not a glitch—it's a feature. After booking a cheap group fare on Yatra.com, I discovered the hidden world of airline group bookings, and uncovered a &lt;strong&gt;real bug&lt;/strong&gt; with same-name passengers.&lt;/p&gt;

&lt;p&gt;In this post, we'll unpack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How group fare booking systems work&lt;/li&gt;
&lt;li&gt;Why "TBA" exists in airline PNRs&lt;/li&gt;
&lt;li&gt;What developers building travel systems should know&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A critical bug I found&lt;/strong&gt;: Same-name passengers causing seat swaps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✈️ 1. What Are Group Fares?
&lt;/h2&gt;

&lt;p&gt;Group fares are special airline rates for &lt;strong&gt;10+ passengers&lt;/strong&gt; traveling together on the same flight and date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🏢 Corporate trips&lt;/li&gt;
&lt;li&gt;💒 Weddings and family gatherings&lt;/li&gt;
&lt;li&gt;🕌 Pilgrimage or religious tours&lt;/li&gt;
&lt;li&gt;🏀 School or sports teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike individual bookings, group fares are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Negotiated&lt;/strong&gt; directly with airlines or via GDS&lt;/li&gt;
&lt;li&gt;More &lt;strong&gt;flexible&lt;/strong&gt; with payment schedules&lt;/li&gt;
&lt;li&gt;Allow &lt;strong&gt;placeholder names&lt;/strong&gt; initially&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Business Logic: The Group Booking Flow
&lt;/h2&gt;

&lt;p&gt;Here's how it works from an OTA or travel agent's perspective:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Process&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1️⃣&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Group Quote Request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agency requests fare for route, date, and passenger count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2️⃣&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PNR Creation (TBA stage)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Airline/GDS creates group PNR with placeholders like &lt;code&gt;TBA/TBA&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3️⃣&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deposit &amp;amp; Hold&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Group pays deposit to hold seats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4️⃣&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Name Finalization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12–72 hours before flight, replace "TBA" with real names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5️⃣&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ticketing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Once names finalized, tickets are issued&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📋 3. What Does "TBA" Actually Mean?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TBA = To Be Advised&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When creating a group booking, actual passenger details may not be known yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example in GDS (Amadeus/Sabre):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each entry reserves a seat while allowing the agent to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hold inventory&lt;/strong&gt; without final names&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track blocked seats&lt;/strong&gt; in airline systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display flight details&lt;/strong&gt; before passenger confirmation&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  How GDS Systems Power This Magic
&lt;/h4&gt;

&lt;p&gt;Behind the scenes, OTAs don't talk directly to each airline. They use &lt;strong&gt;GDS (Global Distribution System)&lt;/strong&gt; — think of it as the "API gateway" of the travel industry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Big Three:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amadeus&lt;/strong&gt; (European dominance)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sabre&lt;/strong&gt; (Strong in Americas)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Travelport&lt;/strong&gt; (Galileo/Worldspan/Apollo)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⏰ 4. The 12-Hour Rule
&lt;/h2&gt;

&lt;p&gt;Most airlines require final passenger names &lt;strong&gt;no later than 12 hours before departure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens at finalization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ All "TBA" placeholders updated with real names&lt;/li&gt;
&lt;li&gt;⚠️ Unnamed passengers may auto-cancel&lt;/li&gt;
&lt;li&gt;🎫 Group PNR transitions to ticketed state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why Yatra/MMT show "flight details visible before 12 hours" — the system holds the group block, but names are pending.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. System Architecture Flow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Key technical points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Placeholders stored in PNR until replaced&lt;/li&gt;
&lt;li&gt;Airlines track via group booking IDs (not individual tickets)&lt;/li&gt;
&lt;li&gt;Background jobs handle PNR sync and updates&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💻 6. How OTAs Handle This (Developer View)
&lt;/h2&gt;

&lt;p&gt;For platforms like Yatra or MakeMyTrip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified model&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;groupBooking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;pnr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ABC123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TBA_PENDING&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;passengers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TBA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TBA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TBA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TBA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;finalizationDeadline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2025-11-08T10:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;flightDetails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// visible after name update&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backend requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Handle placeholder data models&lt;/li&gt;
&lt;li&gt;Schedule PNR refresh/update jobs&lt;/li&gt;
&lt;li&gt;Implement deadline alerts&lt;/li&gt;
&lt;li&gt;Validate against duplicate names (see bug below!)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  7. &lt;strong&gt;CRITICAL BUG I DISCOVERED: Same-Name Collision&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;When booking through Yatra's group fare system, I found:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If two passengers have the same name:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ During web check-in, the system will display both passengers names when the PNR and last name are entered together.&lt;/li&gt;
&lt;li&gt;❌ Boarding passes get mixed up&lt;/li&gt;
&lt;li&gt;❌ Airport staff can't distinguish passengers&lt;/li&gt;
&lt;li&gt;❌ Potential security and check-in issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Scenario
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Booking for two people with same name&lt;/span&gt;
&lt;span class="nx"&gt;passengers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Amit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Kumar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;seat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Amit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Kumar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;seat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// What happens in airline system:&lt;/span&gt;
&lt;span class="c1"&gt;// PNR shows: KUMAR/AMIT MR + KUMAR/AMIT MR&lt;/span&gt;
&lt;span class="c1"&gt;// Boarding pass generates wrong seat for one passenger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Happens
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GDS Name Formatting&lt;/strong&gt;: Airlines use &lt;code&gt;PNR and LASTNAME&lt;/code&gt; combination&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate Detection&lt;/strong&gt;: System may treat as duplicate entry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seat Assignment Logic&lt;/strong&gt;: Uses last name as primary key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group PNR Merge&lt;/strong&gt;: Multiple "AMIT KUMAR" entries cause confusion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Recommended fixes for OTAs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 Pre-booking validation for duplicate last names&lt;/li&gt;
&lt;li&gt;📝 Force middle name or mobile number for duplicates&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔮 8. Future: NDC and Modern APIs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;IATA's NDC (New Distribution Capability)&lt;/strong&gt; is modernizing group fares:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚡ Real-time quotes and seat holds&lt;/li&gt;
&lt;li&gt;🔄 Easier passenger data updates via REST APIs&lt;/li&gt;
&lt;li&gt;📉 Reduced reliance on "TBA" placeholders&lt;/li&gt;
&lt;li&gt;🤝 Direct airline-to-OTA connections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Though many airlines still support TBA for backward compatibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Key Takeaways
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Point&lt;/th&gt;
&lt;th&gt;Reality Check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;✅ &lt;strong&gt;"TBA" is a feature, not a bug&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Intentional placeholder system for group inventory management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⏰ &lt;strong&gt;The 12-hour rule has a twist&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Names often start reflecting from &lt;strong&gt;midnight&lt;/strong&gt; (not exactly 12 hours), which can frustrate travelers expecting earlier updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💰 &lt;strong&gt;How OTAs really make money&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Indian OTAs like Yatra/MMT book group fares and mark them up—this is on &lt;strong&gt;top of&lt;/strong&gt; convenience charges. That "cheap fare" might just be a group booking arbitrage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🚨 &lt;strong&gt;Same-name = system chaos&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Multiple passengers with identical last names create PNR conflicts, seat swaps, and boarding issues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎭 &lt;strong&gt;The agent model&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;OTAs aren't always direct airline partners—many operate as &lt;strong&gt;super-agents&lt;/strong&gt; booking group blocks and reselling individually&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💬 Discussion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For developers building travel systems:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How does your system handle group booking placeholders?&lt;/li&gt;
&lt;li&gt;Ever encountered the same-name bug I found?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Drop your experiences in the comments! 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.iata.org/en/programs/airline-distribution/retailing/ndc/" rel="noopener noreferrer"&gt;IATA NDC Program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.amadeus.com/" rel="noopener noreferrer"&gt;Amadeus API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.sabre.com/" rel="noopener noreferrer"&gt;Sabre Dev Studio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This post is based on real-world experience booking through Yatra.com. If you found this helpful, consider sharing it with your travel-tech friends! ✈️&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #traveltech #backend #systemdesign #api #devstory&lt;/p&gt;

</description>
      <category>traveltech</category>
      <category>backend</category>
      <category>api</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>How YouTube Tracks Your Location Even with GPS and History Turned Off</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Tue, 14 Oct 2025 20:55:40 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/how-youtube-tracks-your-location-even-with-gps-and-history-turned-off-1gk</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/how-youtube-tracks-your-location-even-with-gps-and-history-turned-off-1gk</guid>
      <description>&lt;p&gt;"I had location turned off. I was in incognito mode. Still, YouTube recommended a nearby concert of the band I just listened to. What?!"&lt;/p&gt;

&lt;p&gt;If that sounds familiar, you're not alone. Many users have reported the accuracy of YouTube's recommendations, especially around location-based content—even when they've gone to great lengths to remain private.&lt;/p&gt;

&lt;p&gt;Let's break down how YouTube (and by extension, Google) can still estimate your location without GPS, location history, or account activity.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛰️ 1. IP Address Geolocation – The Primary Tracker
&lt;/h2&gt;

&lt;p&gt;Even without GPS, your &lt;strong&gt;IP address&lt;/strong&gt; gives away your general location.&lt;/p&gt;

&lt;p&gt;Every internet-connected device is assigned an IP address by your Internet Service Provider (ISP). These addresses are mapped to geographic regions using public and commercial IP geolocation databases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accuracy:&lt;/strong&gt; Generally within 50–100 km, but it can be even more precise—especially in cities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example: How IP geolocation might work&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://ipapi.co/json/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`City: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Region: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Country: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// YouTube uses similar (but more sophisticated) techniques&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ You can't completely hide from IP-based geolocation unless you're using a VPN or proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 2. Google Account Data (Even If You're in Incognito)
&lt;/h2&gt;

&lt;p&gt;Even if you're browsing in &lt;strong&gt;Incognito Mode&lt;/strong&gt;, Google might still know who you are if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're logged into a Google account in another tab or device&lt;/li&gt;
&lt;li&gt;You've ever saved a home or work address in your Google Account&lt;/li&gt;
&lt;li&gt;You've used Google Maps or other location-based services in the past&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google keeps past location history (if it was ever turned on) and uses that to infer your habits and regions of interest.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Dev Tip:&lt;/strong&gt; Incognito mode only prevents local storage—it doesn't prevent network-level tracking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🧠 3. Device &amp;amp; Network Fingerprinting
&lt;/h2&gt;

&lt;p&gt;Google collects metadata from your device and local network to build a &lt;strong&gt;digital fingerprint&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wi-Fi network names (SSID) and nearby access points&lt;/li&gt;
&lt;li&gt;Device timezone, language, and region settings&lt;/li&gt;
&lt;li&gt;Your ISP and general network behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This information can correlate with known locations and help Google guess your approximate whereabouts, even without direct GPS data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Browser fingerprinting example&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fingerprint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;resolvedOptions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;timeZone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;screenResolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ... and dozens more data points&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔄 4. Cross-Device &amp;amp; Cross-Platform Learning
&lt;/h2&gt;

&lt;p&gt;If you're using multiple devices connected to the same Google account or Wi-Fi network, Google's ecosystem shares information across them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A smart TV, laptop, or tablet on the same home network might leak contextual data to your phone&lt;/li&gt;
&lt;li&gt;YouTube recommendations can be influenced by other people watching on the same IP or shared account (roommates, family, etc.)&lt;/li&gt;
&lt;li&gt;Even if you didn't search for a concert, your household might have, and that can affect what shows up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  😱 Real-World Example: YouTube Recommending Nearby Concerts
&lt;/h2&gt;

&lt;p&gt;Here's what likely happened in this scenario:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user listened to a band in YouTube's incognito mode&lt;/li&gt;
&lt;li&gt;YouTube picked up their &lt;strong&gt;IP address&lt;/strong&gt; (revealing their approximate location)&lt;/li&gt;
&lt;li&gt;It correlated that with known tour dates in that area&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation:&lt;/strong&gt; "🎤 Don't miss [Band Name] live in [Your City]!"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All that, without needing GPS or location history.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 How to Protect Yourself (If You Want To)
&lt;/h2&gt;

&lt;p&gt;If you're concerned about this level of tracking, here are some steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  For Regular Users:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Use a reliable &lt;strong&gt;VPN&lt;/strong&gt; to mask your IP address&lt;/li&gt;
&lt;li&gt;🚫 Avoid logging into Google accounts when browsing privately&lt;/li&gt;
&lt;li&gt;📵 Turn off YouTube watch history and ad personalization&lt;/li&gt;
&lt;li&gt;⚙️ Regularly clear cookies and site data from your browser&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Developers:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🧪 Consider using privacy-focused alternatives (e.g., NewPipe for YouTube, or Firefox Focus)&lt;/li&gt;
&lt;li&gt;🔍 Implement &lt;strong&gt;Privacy by Design&lt;/strong&gt; principles in your own applications&lt;/li&gt;
&lt;li&gt;📊 Be transparent about data collection in your projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Note:&lt;/strong&gt; Even with these measures, total privacy is difficult in an ecosystem as interconnected as Google's.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ Implications for Web Developers
&lt;/h2&gt;

&lt;p&gt;As developers, we should be aware of these tracking mechanisms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Trust:&lt;/strong&gt; Be transparent about what data you collect&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GDPR/Privacy Laws:&lt;/strong&gt; Ensure compliance with regulations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ethical Considerations:&lt;/strong&gt; Just because you &lt;em&gt;can&lt;/em&gt; track users doesn't mean you &lt;em&gt;should&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alternative Monetization:&lt;/strong&gt; Explore privacy-respecting business models
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example: Respect user privacy preferences&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Skip analytics and personalization&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User has requested not to be tracked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Initialize analytics with consent&lt;/span&gt;
  &lt;span class="nf"&gt;initAnalytics&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔍 Final Thoughts: You're Not Paranoid—It's Just Smart Algorithms
&lt;/h2&gt;

&lt;p&gt;YouTube's ability to serve accurate, location-based recommendations without GPS or location sharing isn't magic—&lt;strong&gt;it's data science&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By blending signals from your IP address, network environment, device metadata, and cross-platform behavior, YouTube can pinpoint your probable location with surprising accuracy.&lt;/p&gt;

&lt;p&gt;So, the next time you see a "nearby" event on YouTube while in incognito mode… know that it's not spying—it's just very, very good at guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Fingerprinting" rel="noopener noreferrer"&gt;MDN: Browser Fingerprinting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://panopticlick.eff.org/" rel="noopener noreferrer"&gt;EFF: Panopticlick - Test Your Browser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/youtube/answer/16604211" rel="noopener noreferrer"&gt;YouTube's Location Settings&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;What's your experience with location-based recommendations? Have you noticed similar patterns? Share your thoughts in the comments below! 👇&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>webdev</category>
      <category>google</category>
    </item>
    <item>
      <title>Best Practices for Public npm Packages: Lock Files, Publishing &amp; Dependency Management</title>
      <dc:creator>Aman Kumar</dc:creator>
      <pubDate>Mon, 06 Oct 2025 13:30:21 +0000</pubDate>
      <link>https://dev.to/aman_kumar_bdd40f1b711c15/best-practices-for-public-npm-packages-lock-files-publishing-dependency-management-4mmi</link>
      <guid>https://dev.to/aman_kumar_bdd40f1b711c15/best-practices-for-public-npm-packages-lock-files-publishing-dependency-management-4mmi</guid>
      <description>&lt;h3&gt;
  
  
  Confused about whether to commit package-lock.json when publishing to npm? Here's the standard practice for public repositories.
&lt;/h3&gt;




&lt;p&gt;When maintaining an open source project or reusable package on npm, it’s easy to run into uncertainty:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should you commit &lt;code&gt;package-lock.json&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;How do you ensure consistent dependency resolution?&lt;/li&gt;
&lt;li&gt;What do end users get when they install your package?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post breaks down the &lt;strong&gt;standard industry practice&lt;/strong&gt; for open-source npm packages — especially regarding lock files, dependency pinning, CI, and secure publishing.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔒 Should I Commit &lt;code&gt;package-lock.json&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Yes, &lt;strong&gt;commit &lt;code&gt;package-lock.json&lt;/code&gt; to your Git repo&lt;/strong&gt; — but know that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;package-lock.json&lt;/code&gt; is &lt;strong&gt;ignored&lt;/strong&gt; when you publish a package to the npm registry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means it benefits &lt;strong&gt;you and your contributors&lt;/strong&gt;, but has no direct effect on your package consumers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of committing it:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Consistent installs during development&lt;/li&gt;
&lt;li&gt;✅ Reproducible CI environments&lt;/li&gt;
&lt;li&gt;✅ Easier debugging &amp;amp; auditing&lt;/li&gt;
&lt;li&gt;✅ Clear diffs when dependencies are upgraded&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 What Gets Published to npm?
&lt;/h2&gt;

&lt;p&gt;By default, npm publishes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Files not listed in &lt;code&gt;.npmignore&lt;/code&gt; (or included in the &lt;code&gt;files&lt;/code&gt; field)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;But not&lt;/strong&gt; &lt;code&gt;package-lock.json&lt;/code&gt; (unless you publish a &lt;code&gt;npm-shrinkwrap.json&lt;/code&gt; — more on that below)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  TL;DR:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Consumers install dependencies based on your &lt;code&gt;package.json&lt;/code&gt; semver ranges, &lt;strong&gt;not your lock file&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🛠 How to Pin Dependencies for Safety
&lt;/h2&gt;

&lt;p&gt;Even though you can’t ship a lock file, you &lt;strong&gt;can&lt;/strong&gt; prevent surprises:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Use exact versions in &lt;code&gt;package.json&lt;/code&gt;:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dependencies": {
  "lodash": "4.17.21"   // Not ^4.17.21
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid semver ranges like ^ or ~ if you want deterministic installs.&lt;/p&gt;




&lt;h2&gt;
  
  
  📄 What About npm-shrinkwrap.json?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;npm-shrinkwrap.json&lt;/strong&gt; is published with your package and locks the entire dependency tree.&lt;br&gt;
&lt;strong&gt;But:&lt;/strong&gt;&lt;br&gt;
⚠️ It can conflict with your consumers' dependencies&lt;br&gt;
⚠️ It makes updating harder for downstream projects&lt;br&gt;
✅ Useful for CLI tools or apps where you want full control of the install&lt;br&gt;
For libraries, it's not standard to use shrinkwrap.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧪 CI &amp;amp; Testing Best Practices
&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;npm ci&lt;/strong&gt; in CI — this installs from the lock file and ensures reproducible builds.&lt;br&gt;
Test the final output using:&lt;br&gt;
&lt;strong&gt;npm pack&lt;/strong&gt;&lt;br&gt;
This shows you exactly what your users will get before you publish.&lt;br&gt;
Automate checks before publishing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
  "prepublishOnly": "npm test &amp;amp;&amp;amp; npm run lint &amp;amp;&amp;amp; npm run build"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🤝 Use Peer Dependencies Wisely
&lt;/h2&gt;

&lt;p&gt;If your library is designed to plug into another framework (e.g. React, Next.js, ESLint):&lt;br&gt;
Declare those as peerDependencies in package.json.&lt;br&gt;
Don’t bundle them in your dependencies.&lt;br&gt;
This avoids version conflicts and duplication.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"peerDependencies": {
  "react": "^18.0.0"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔐 Security Practices
&lt;/h2&gt;

&lt;p&gt;Run npm audit regularly&lt;br&gt;
&lt;strong&gt;Use tools like:&lt;/strong&gt;&lt;br&gt;
Dependabot&lt;br&gt;
Snyk&lt;br&gt;
GitHub security alerts&lt;/p&gt;

&lt;p&gt;Keep your dependencies updated — responsibly!&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Committing your lock file doesn’t harm your npm package — it helps your team. And while npm won’t publish it, you can still enforce reliable builds and secure installs by pinning versions, using CI properly, and testing your tarballs.&lt;br&gt;
If you’ve ever been burned by a subtle dependency upgrade breaking your users — you’re not alone. Following these practices can save you (and your users) hours of debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Happy publishing!🚀
&lt;/h3&gt;

</description>
      <category>npm</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
