<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Prakhar's blog]]></title><description><![CDATA[Prakhar's blog]]></description><link>https://prakhartripathi.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 16 Sep 2026 06:09:06 GMT</lastBuildDate><atom:link href="https://prakhartripathi.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why replacing /usr/bin/python3 broke apt on my Ubuntu system]]></title><description><![CDATA[The problem
I installed Python 3.12 for a project and pointed /usr/bin/python3 to it, instead of using a virtual environment. Everything worked fine at first. A few days later, add-apt-repository fail]]></description><link>https://prakhartripathi.hashnode.dev/why-replacing-usr-bin-python3-broke-apt-on-my-ubuntu-system</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/why-replacing-usr-bin-python3-broke-apt-on-my-ubuntu-system</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Wed, 12 Aug 2026 06:05:27 GMT</pubDate><content:encoded><![CDATA[<h2>The problem</h2>
<p>I installed Python 3.12 for a project and pointed <code>/usr/bin/python3</code> to it, instead of using a virtual environment. Everything worked fine at first. A few days later, <code>add-apt-repository</code> failed with:</p>
<pre><code class="language-shell">ModuleNotFoundError: No module named 'apt_pkg'
</code></pre>
<h2>Why it happened</h2>
<p><code>/usr/bin/python3</code> is not just a developer shortcut. Ubuntu uses it to run several of its own tools, including <code>add-apt-repository</code>, <code>unattended-upgrades</code>, and <code>apport</code>. These are Python scripts, and some of them depend on compiled Python modules built specifically for the Python version Ubuntu ships with, which was 3.10, not 3.12.</p>
<p>Once <code>/usr/bin/python3</code> pointed at 3.12, these tools were running on an interpreter their compiled modules were never built for. Python looked for a module built for 3.12 and found nothing, because no such module existed.</p>
<h2>The culprit</h2>
<p>Installing Python 3.12 alongside the system Python was never the problem. That part is completely normal, plenty of machines run several Python versions side by side without any issue.</p>
<p>The real culprit was <code>/usr/bin/python3</code> itself, a single, shared path. Every tool on the system that calls <code>python3</code> without asking for a specific version follows that same path, including Ubuntu's own package management scripts. Those scripts don't need "some" Python 3, they need the exact one their compiled modules were built against. There's no version check before they run, so the moment <code>/usr/bin/python3</code> changed, every one of those tools was quietly pointed at an interpreter it was never built for, and it stayed that way until one of them happened to run.</p>
<h2>The fix</h2>
<p>Keep the system Python untouched, and give the project its own environment instead:</p>
<img src="https://cdn.hashnode.com/uploads/covers/612b62992858872661b9afef/5d6a5e28-b2df-44b4-ad43-a7a29f8265fd.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">sudo update-alternatives --set python3 /usr/bin/python3.10
python3.12 -m venv .venv
source .venv/bin/activate
</code></pre>
<p>This restores apt's original interpreter and gives the project Python 3.12 inside its own virtual environment. The OS manages its own dependencies, the project manages its own, and neither one has to interfere with the other.</p>
]]></content:encoded></item><item><title><![CDATA[How AI Reads Text: From Words to Vectors]]></title><description><![CDATA[You type a question. The AI replies. But between those two moments, your words get converted into thousands of numbers — and meaning emerges from pure math.
Here's how that works.

It's Not Reading. I]]></description><link>https://prakhartripathi.hashnode.dev/how-ai-reads-text-from-words-to-vectors</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/how-ai-reads-text-from-words-to-vectors</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Sun, 26 Apr 2026 15:04:45 GMT</pubDate><content:encoded><![CDATA[<p>You type a question. The AI replies. But between those two moments, your words get converted into thousands of numbers — and meaning emerges from pure math.</p>
<p>Here's how that works.</p>
<hr />
<h2>It's Not Reading. It's Translating.</h2>
<p>AI doesn't "understand" English the way you do. It can't. Instead, it converts words into <strong>vectors</strong> — lists of numbers that encode meaning mathematically. Words that mean similar things end up with similar numbers. Words that have nothing in common don't.</p>
<blockquote>
<p>💡 <strong>Core idea:</strong> Every word you send to an AI becomes a point in a giant mathematical space. Meaning = position.</p>
</blockquote>
<hr />
<h2>What Are Embeddings?</h2>
<p>An <strong>embedding</strong> is that numerical representation — the set of numbers a word gets mapped to.</p>
<p>"King" and "Queen" end up numerically close to each other. "King" and "Laptop" don't. Nobody told the AI this. It figured it out on its own, by reading vast amounts of text and noticing which words kept showing up in similar situations.</p>
<img src="https://cdn.hashnode.com/uploads/covers/612b62992858872661b9afef/ed8e9cfb-60a8-4724-8fe2-8940147eb746.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>The 3-Step Journey</h2>
<h3>Step 1 — Tokenization</h3>
<p>Before any math happens, the text gets broken into <strong>tokens</strong> — small, digestible pieces the model can work with.</p>
<img src="https://cdn.hashnode.com/uploads/covers/612b62992858872661b9afef/09770ae4-f276-4209-af5a-f9c64f3cfe09.svg" alt="" style="display:block;margin:0 auto" />

<p>It's a small step, but an important one. By splitting unfamiliar words into known pieces, the model makes sure nothing is ever truly unreadable.</p>
<hr />
<h3>Step 2 — Vectorization</h3>
<p>Once tokenized, each piece gets a unique address in meaning-space:</p>
<pre><code class="language-markdown">King  → [0.25,  0.51, -0.12, 0.88, ...]
Queen → [0.24,  0.49, -0.15, 0.82, ...]
Apple → [0.91, -0.33,  0.55, 0.01, ...]
</code></pre>
<p>Look at King and Queen — nearly identical values. Apple is somewhere completely different. Nobody hardcoded this. The model learned it purely from patterns in billions of sentences. That's also how it works out that "car" and "automobile" mean the same thing, or that "happy" sits on the opposite end of the spectrum from "sad." No one had to spell it out.</p>
<hr />
<h3>Step 3 — Contextualization</h3>
<p>Here's where it gets interesting. The same word can mean completely different things — and the model has to figure out which one you meant.</p>
<img src="https://cdn.hashnode.com/uploads/covers/612b62992858872661b9afef/15b211dd-53c6-4183-a829-fd508970e82f.png" alt="" style="display:block;margin:0 auto" />

<p>Older AI gave every word one fixed meaning, no matter what. Modern models like BERT and GPT do something smarter — they generate a <strong>different vector each time</strong>, shaped by the words around it. The word "bank" in a fishing story is not the same "bank" as in a finance article. Context changes everything.</p>
<hr />
<h2>Why Embeddings Are AI's Superpower</h2>
<table>
<thead>
<tr>
<th>Capability</th>
<th>What it enables</th>
</tr>
</thead>
<tbody><tr>
<td>Semantic search</td>
<td>Finds results by <em>intent</em>, not keyword match</td>
</tr>
<tr>
<td>Language translation</td>
<td>Maps concepts across language spaces</td>
</tr>
<tr>
<td>Recommendations</td>
<td>Surfaces items with similar semantic profiles</td>
</tr>
<tr>
<td>Text generation</td>
<td>Predicts the most contextually fitting next word</td>
</tr>
<tr>
<td>Sentiment analysis</td>
<td>Gauges emotional tone even in informal text</td>
</tr>
</tbody></table>
<hr />
<h2>The Takeaway</h2>
<p>Every time AI processes text, three things happen:</p>
<ol>
<li><p><strong>Tokenize</strong> — break text into manageable units</p>
</li>
<li><p><strong>Vectorize</strong> — map each unit to a position in meaning-space</p>
</li>
<li><p><strong>Contextualize</strong> — shift that position based on surrounding words</p>
</li>
</ol>
<p>What you get is a mathematical map of language. Meaning has coordinates. Relationships have distances. And "understanding" turns out to be a geometry problem.</p>
<p>It's a very different kind of reading. But it works.</p>
]]></content:encoded></item><item><title><![CDATA[Hybrid Search Explained: When to Use Keyword, Vector, or Both in AI Applications]]></title><description><![CDATA[While building AI-powered products, terms like vector search, RAG, and hybrid search show up everywhere
This post breaks it all down — clearly, practically, and without the hype.

The Problem With Sim]]></description><link>https://prakhartripathi.hashnode.dev/hybrid-search-explained-when-to-use-keyword-vector-or-both-in-ai-applications</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/hybrid-search-explained-when-to-use-keyword-vector-or-both-in-ai-applications</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Sun, 01 Mar 2026 11:41:25 GMT</pubDate><content:encoded><![CDATA[<p>While building AI-powered products, terms like <strong>vector search</strong>, <strong>RAG</strong>, and <strong>hybrid search</strong> show up everywhere</p>
<p>This post breaks it all down — clearly, practically, and without the hype.</p>
<hr />
<h2>The Problem With Simple Search</h2>
<p>Most of us started with keyword search. Type a word, scan for matches. It works fine until it doesn't.</p>
<p>Keyword search (like <strong>BM25</strong> or <strong>TF-IDF</strong>) is purely lexical — it matches <strong>exact words or tokens</strong>, nothing more. Ask it for "automobile" when your docs say "car" and it comes back empty-handed. Ask it "dog bites man" and it'll happily treat that as identical to "man bites dog." It has no concept of meaning.</p>
<p>That's where <strong>semantic search</strong> comes in.</p>
<hr />
<h2>Semantic Search: Meaning Over Words</h2>
<p>Semantic search converts text into <strong>embeddings</strong> — high-dimensional vectors that represent meaning. Instead of comparing words, you're comparing concepts.</p>
<p>Ask "Who wrote Dubious Parenting Tips?" and it can match "Lisa Melton <em>wrote</em> Dubious Parenting Tips" even though your query said "author," not "wrote." It understands they mean the same thing.</p>
<p>Under the hood, similarity is measured with:</p>
<ul>
<li><p><strong>Cosine similarity</strong> — measures the <em>angle</em> between two vectors. Small angle = high similarity. This is the most common choice.</p>
</li>
<li><p><strong>Dot product</strong> — similar to cosine but sensitive to vector magnitude.</p>
</li>
<li><p><strong>Euclidean / Manhattan distance</strong> — measures raw distance in vector space.</p>
</li>
</ul>
<p>Cosine similarity is particularly powerful because <strong>meaning is about direction, not magnitude</strong>. Two sentences can be phrased very differently but point in the same conceptual direction.</p>
<hr />
<h2>BM25 vs. Cosine Similarity — When to Use Which</h2>
<p>This is where most tutorials gloss over the important stuff. Let's be direct:</p>
<table>
<thead>
<tr>
<th></th>
<th>BM25 (Keyword)</th>
<th>Cosine Similarity (Vector)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Matching</strong></td>
<td>Exact words</td>
<td>Meaning / concept</td>
</tr>
<tr>
<td><strong>Strength</strong></td>
<td>Precision, rare terms</td>
<td>Recall, natural language</td>
</tr>
<tr>
<td><strong>Weakness</strong></td>
<td>Misses synonyms</td>
<td>Misses exact codes/IDs</td>
</tr>
<tr>
<td><strong>Best for</strong></td>
<td>SKUs, error codes, names</td>
<td>Questions, concepts, intent</td>
</tr>
</tbody></table>
<p><strong>BM25</strong> answers: <em>"How important is this word across all documents?"</em> It balances three things:</p>
<ol>
<li><p>How <strong>rare</strong> the word is across the whole corpus (IDF)</p>
</li>
<li><p>How <strong>often</strong> it appears in a specific document (TF)</p>
</li>
<li><p><strong>Document length</strong> normalization (so shorter docs aren't unfairly penalized)</p>
</li>
</ol>
<p><strong>Cosine similarity</strong> doesn't care about exact words at all. "I want Italian food" and "pizza, pasta, risotto" can be very close in vector space even with zero word overlap.</p>
<p>The practical takeaway: <strong>neither is universally better</strong>. They're tools for different jobs.</p>
<hr />
<h2>Hybrid Search: The Real-World Architecture</h2>
<p>Here's something most tutorials don't tell you — <strong>you can't pick a fixed 50/50 weight between keyword and vector search and expect it to work well across all query types.</strong></p>
<p>Consider a product catalog with an item titled <em>"Apple MacBook Pro 16-inch M3 Max"</em> with SKU <code>MBP-M3MAX-32-1TB</code>.</p>
<table>
<thead>
<tr>
<th>Query</th>
<th>Best weights</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td><code>MBP-M3MAX-32-1TB</code></td>
<td>20% vector / 80% keyword</td>
<td>It's a product code — semantic search is useless</td>
</tr>
<tr>
<td>"best laptop for video editing"</td>
<td>80% vector / 20% keyword</td>
<td>Natural language needs meaning, not exact matches</td>
</tr>
<tr>
<td>"Sony headphones"</td>
<td>50% / 50%</td>
<td>Brand name + product category — both matter</td>
</tr>
</tbody></table>
<p>A well-designed hybrid system looks like this:</p>
<pre><code class="language-markdown">User Query  
↓  
Query Parser  
↓  
BM25 (Keyword Search) + Vector Search (Semantic Search)  
↓  
Merge &amp; Re-rank  
↓  
Top-K Retrieved Documents  
↓  
LLM (RAG)  
↓  
Final Answer
</code></pre>
<p>The smart part is the <strong>query classifier</strong> — detecting whether a query is a product code, a natural language question, or something in between, and adjusting weights accordingly.</p>
<hr />
<h2>When NOT to Use Vector Search</h2>
<p>This is the section nobody writes, but it's arguably the most useful one.</p>
<p>Vector search is powerful, but it's genuinely the wrong tool in several common situations:</p>
<p><strong>1. Exact IDs, codes, and SKUs</strong> Queries like <code>Order A9F-3321</code> or <code>Error code E042</code> need exact matching. Embeddings <em>blur</em> meaning — <code>A9F-3321</code> and <code>A9F-3322</code> may look nearly identical in vector space. Use BM25 or a database query instead.</p>
<p><strong>2. Structured / filtered queries</strong> <code>price &lt; 100 AND color = red AND size = M</code> is a database problem, not a search problem. Vectors don't reliably understand logical operators. Use SQL or faceted filters.</p>
<p><strong>3. Short, ambiguous queries</strong> <code>python</code>, <code>apple</code>, <code>jaguar</code> — what does the embedding even represent here? A programming language? A fruit? A car brand? Vector search will guess, and it may guess wrong. Add query expansion, hybrid search, or clarifying prompts.</p>
<p><strong>4. Real-time or frequently changing data</strong> Vector search retrieves what was indexed at embedding time. "Current Tesla stock price" or "today's weather" need live APIs, not a vector DB.</p>
<p><strong>5. When ranking must be explainable</strong> In legal or compliance contexts, you need to answer "why did this document rank first?" Vector similarity doesn't give you a clean answer beyond "the distance was smaller." Use keyword scoring or rule-based systems where auditing matters.</p>
<p><strong>6. Exact phrasing or legal clauses</strong> When you need <code>FIND documents containing this exact sentence</code>, embeddings intentionally lose exact phrasing. Use regex or exact text search.</p>
<p><strong>7. Very small datasets</strong> 20–100 documents? Similarity scores get noisy and unreliable at tiny scale. A simple keyword search or even a manual review is often better.</p>
<p><strong>8. Domain-specific jargon with no embedding coverage</strong> Internal acronyms, niche medical terms, company-specific concepts — generic embedding models don't "know" your private language. You'll need domain-specific embeddings, fine-tuning, or hybrid search with reranking.</p>
<hr />
<h2>The Takeaway</h2>
<p>Search in the age of AI isn't one thing. It's a spectrum:</p>
<ul>
<li><p><strong>Keyword search</strong> for precision — codes, names, exact terms</p>
</li>
<li><p><strong>Vector search</strong> for meaning — concepts, questions, natural language</p>
</li>
<li><p><strong>Hybrid search</strong> for the real world — because queries don't fit neatly into one box</p>
</li>
</ul>
<p>Understanding when to reach for each tool is what separates developers who can <em>use</em> AI APIs from those who can <em>architect</em> AI systems.</p>
<p>That's a distinction worth making.</p>
]]></content:encoded></item><item><title><![CDATA[Database Indexes: The Performance Trade-off]]></title><description><![CDATA[Ever wondered why database inserts are slow while queries are blazing fast? The answer is : indexes.
Indexes are one of those magical database features that can make your app feel lightning-fast—until they don't. Let's break down what's really happen...]]></description><link>https://prakhartripathi.hashnode.dev/database-index</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/database-index</guid><category><![CDATA[Databases]]></category><category><![CDATA[SQL]]></category><category><![CDATA[indexing]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Tue, 27 Jan 2026 19:16:17 GMT</pubDate><content:encoded><![CDATA[<p>Ever wondered why database inserts are slow while queries are blazing fast? The answer is : <strong>indexes</strong>.</p>
<p>Indexes are one of those magical database features that can make your app feel lightning-fast—until they don't. Let's break down what's really happening under the hood.</p>
<hr />
<h2 id="heading-what-exactly-is-an-index">What Exactly Is an Index?</h2>
<p>Think of a database index like the index at the back of a textbook. Instead of flipping through every page to find "Binary Search Trees," you check the index, which tells you exactly where to look.</p>
<p><mark>A database index contains three key pieces:</mark></p>
<ol>
<li><p><strong><mark>Copies of the indexed column values</mark></strong> <mark> (sorted for quick searching)</mark></p>
</li>
<li><p><strong><mark>Pointers to the actual row locations</mark></strong> <mark> in the main table</mark></p>
</li>
<li><p><strong><mark>Metadata</mark></strong> <mark> for maintaining the index structure (B-tree nodes, etc.)</mark></p>
</li>
</ol>
<p>Here's what happens under the hood:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769540222653/3950b99b-85ae-4ee1-827c-eb208d0e7aa4.png" alt class="image--center mx-auto" /></p>
<p><mark>The index stores a </mark> <strong><mark>sorted copy</mark></strong> <mark> of the email column along with pointers back to the full records. Indexes typically use B-tree structures </mark> (balanced tree structures that keep data sorted and allow searches, inserts, and deletes in logarithmic time) to maintain this sorted order efficiently.</p>
<hr />
<h2 id="heading-the-write-performance-hit-and-why-it-happens">The Write Performance Hit (And Why It Happens)</h2>
<p>Here's the painful truth: <strong>every index you create slows down writes</strong>.</p>
<h3 id="heading-why-because-of-redundancy">Why? Because of Redundancy.</h3>
<p>When you insert, update, or delete data, the database doesn't just modify the main table—it has to update <strong>every single index</strong> that references the affected columns.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769539615609/e676ccc1-b2f3-495d-a8f3-bdf7f9823a70.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-real-world-impact-the-numbers-dont-lie">Real-World Impact: The Numbers Don't Lie</h3>
<p>Let's say you're building an e-commerce platform and need to bulk-import 1 million products:</p>
<ul>
<li><p><strong>Without indexes</strong>: ~10-15 seconds</p>
</li>
<li><p><strong>With 3-4 indexes</strong>: ~120 seconds (8x slower!)</p>
</li>
</ul>
<p>Indexes can make bulk writes <strong>dramatically slower</strong>.</p>
<hr />
<h2 id="heading-when-indexes-shine-the-read-performance-boost">When Indexes Shine: The Read Performance Boost</h2>
<p>Now for the good news: indexes make <strong>reads incredibly fast</strong>.</p>
<h3 id="heading-real-world-scenario-social-media-feed">Real-World Scenario: Social Media Feed</h3>
<p>Imagine you're building a Twitter-like app with a <code>posts</code> table:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> posts (
    <span class="hljs-keyword">id</span> <span class="hljs-built_in">INT</span> PRIMARY <span class="hljs-keyword">KEY</span>,
    user_id <span class="hljs-built_in">INT</span>,
    <span class="hljs-keyword">content</span> <span class="hljs-built_in">TEXT</span>,
    created_at <span class="hljs-built_in">TIMESTAMP</span>,
    likes_count <span class="hljs-built_in">INT</span>
);

<span class="hljs-comment">-- Create composite index</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_user_created <span class="hljs-keyword">ON</span> posts (user_id, created_at);
</code></pre>
<p><strong>Without the index</strong>, finding a user's recent posts means:</p>
<ul>
<li><p>Scanning <strong>every single row</strong> in the table (1 billion posts?)</p>
</li>
<li><p>Checking if <code>user_id</code> matches</p>
</li>
<li><p>Sorting by <code>created_at</code></p>
</li>
<li><p>Performance: <strong>O(n)</strong> — gets slower as your table grows</p>
</li>
</ul>
<p><strong>With the index</strong>, the database:</p>
<ul>
<li><p>Jumps directly to the user's posts using the sorted index</p>
</li>
<li><p>Already sorted by <code>created_at</code> (thanks to index ordering!)</p>
</li>
<li><p>Returns results in milliseconds</p>
</li>
<li><p>Performance: <strong>O(log n)</strong> — barely affected by table size</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769539923292/a5d80523-2684-469d-b664-dfb8563fa0c5.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-the-catch-column-order-matters">The Catch: Column Order Matters</h3>
<p>Here's where it gets tricky. The <strong>order of columns</strong> in a composite index determines which queries can use it efficiently.</p>
<p>Consider these two indexes:</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- Index 1</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_price_category <span class="hljs-keyword">ON</span> products (price, <span class="hljs-keyword">category</span>);

<span class="hljs-comment">-- Index 2</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_category_price <span class="hljs-keyword">ON</span> products (<span class="hljs-keyword">category</span>, price);
</code></pre>
<p>Now run this query:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> products 
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">category</span> = <span class="hljs-string">'Electronics'</span> 
<span class="hljs-keyword">AND</span> price <span class="hljs-keyword">BETWEEN</span> <span class="hljs-number">100</span> <span class="hljs-keyword">AND</span> <span class="hljs-number">500</span>;
</code></pre>
<p><strong>Index 1</strong> (<code>price, category</code>): The database can't efficiently use this because the query doesn't filter by <code>price</code> first (the leading column). It might skip the index entirely.</p>
<p><strong>Index 2</strong> (<code>category, price</code>): Perfect! The database jumps to 'Electronics' in the index, then scans the price range. Fast and efficient.</p>
<p><strong>Rule of thumb</strong>: Queries benefit from an index only when they use the <strong>leading columns</strong> (left to right) in the index definition.</p>
<hr />
<h2 id="heading-building-better-indexes-practical-guidelines">Building Better Indexes: Practical Guidelines</h2>
<h3 id="heading-column-ordering-strategy">Column Ordering Strategy</h3>
<p>When creating a multi-column index, prioritize columns in this order:</p>
<ol>
<li><p><strong>Equality filters first</strong> (<code>WHERE status = 'active'</code>)</p>
</li>
<li><p><strong>Range filters second</strong> (<code>WHERE price BETWEEN 100 AND 500</code>)</p>
</li>
<li><p><strong>Sort columns last</strong> (<code>ORDER BY created_at</code>)</p>
</li>
</ol>
<p><strong>E-commerce example</strong>:</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- Optimize for: WHERE category='Electronics' AND price &lt; 1000 ORDER BY rating DESC</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_products <span class="hljs-keyword">ON</span> products (
    <span class="hljs-keyword">category</span>,    <span class="hljs-comment">-- Equality filter (most selective)</span>
    price,       <span class="hljs-comment">-- Range filter</span>
    rating       <span class="hljs-comment">-- Sort order</span>
);
</code></pre>
<h3 id="heading-the-partial-index-update-rule">The Partial Index Update Rule</h3>
<p>Here's a performance win many developers miss: <strong>only indexes containing modified columns need updating</strong>.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">users</span> (
    <span class="hljs-keyword">id</span> <span class="hljs-built_in">INT</span> PRIMARY <span class="hljs-keyword">KEY</span>,
    email <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>),
    last_login <span class="hljs-built_in">TIMESTAMP</span>,
    <span class="hljs-keyword">settings</span> <span class="hljs-keyword">JSON</span>
);

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_email <span class="hljs-keyword">ON</span> <span class="hljs-keyword">users</span> (email);
</code></pre>
<p>When you run:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">SET</span> last_login = <span class="hljs-keyword">NOW</span>() <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span> = <span class="hljs-number">123</span>;
</code></pre>
<p>The <code>idx_email</code> index <strong>doesn't get updated</strong> because <code>email</code> wasn't modified. This is why strategic column selection in indexes matters—you're not just optimizing reads, you're minimizing write overhead.</p>
<hr />
<h2 id="heading-the-decision-framework-your-takeaway-checklist">The Decision Framework: Your Takeaway Checklist</h2>
<h3 id="heading-create-an-index-when">Create an Index When:</h3>
<ul>
<li><p>You have a <strong>read-heavy workload</strong> (80%+ reads)</p>
</li>
<li><p>Queries on specific columns are consistently slow</p>
</li>
<li><p>The table has <strong>\&gt;10,000 rows</strong> and growing</p>
</li>
<li><p>Columns have <strong>high cardinality</strong> (many unique values)</p>
</li>
<li><p>You're filtering/joining on the same columns repeatedly</p>
</li>
</ul>
<h3 id="heading-think-twice-when">Think Twice When:</h3>
<ul>
<li><p>Table size is <strong>&lt; 1,000 rows</strong> (table scans are faster)</p>
</li>
<li><p>Write operations dominate your workload (&gt;70% writes)</p>
</li>
<li><p>You already have <strong>5+ indexes</strong> on the table (diminishing returns)</p>
</li>
<li><p>Indexing low-cardinality columns (few unique values)</p>
</li>
<li><p>Storage constraints are tight</p>
</li>
</ul>
<h3 id="heading-red-flags-dont-index">Red Flags (Don't Index):</h3>
<ul>
<li><p>Columns that are <strong>rarely queried</strong></p>
</li>
<li><p>Columns with <strong>frequent updates</strong> but rare reads</p>
</li>
<li><p>Boolean/status flags without additional composite columns</p>
</li>
<li><p>Already covered by existing composite indexes</p>
</li>
</ul>
<h3 id="heading-action-items">Action Items:</h3>
<ol>
<li><p><strong>Audit your slowest queries</strong> (use <code>EXPLAIN</code> or query logs)</p>
</li>
<li><p><strong>Check existing indexes</strong>: Are they actually being used?</p>
</li>
<li><p><strong>Remove unused indexes</strong>: They cost you on every write</p>
</li>
<li><p><strong>Test before deploying</strong>: Benchmark write performance with new indexes</p>
</li>
<li><p><strong>Monitor index sizes</strong>: Set up alerts for storage growth</p>
</li>
</ol>
<hr />
<h2 id="heading-the-bottom-line">The Bottom Line</h2>
<p>Indexes are a <strong>deliberate trade-off</strong>: you sacrifice write speed for dramatically faster reads. Start with your slowest queries, add indexes strategically, and always measure the impact on both reads and writes.</p>
]]></content:encoded></item><item><title><![CDATA[Create Windows Installer for Node.js App using Inno Setup]]></title><description><![CDATA[In the world of software development, creating a seamless installation experience for your users is crucial. If you've built a Node.js application and want to distribute it to Windows users, you'll need to create a Windows installer. This blog post w...]]></description><link>https://prakhartripathi.hashnode.dev/create-windows-installer-for-nodejs-app-using-inno-setup</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/create-windows-installer-for-nodejs-app-using-inno-setup</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Fri, 20 Sep 2024 13:10:06 GMT</pubDate><content:encoded><![CDATA[<p>In the world of software development, creating a seamless installation experience for your users is crucial. If you've built a Node.js application and want to distribute it to Windows users, you'll need to create a Windows installer. This blog post will guide you through the process of creating a Windows installer for your Node.js app, covering everything from environment variables to using Inno Setup.</p>
<h2 id="heading-understanding-windows-environment-variables">Understanding Windows Environment Variables</h2>
<p>Before diving into the installer creation process, it's important to understand how Windows handles environment variables:</p>
<ol>
<li><p>Environment variables in Windows can be set for the current user (HKCU) or local machine (HKLM).</p>
</li>
<li><p>These variables are stored in the Windows Registry Editor.</p>
</li>
<li><p>The paths for environment variables are:</p>
<ul>
<li><p>For local machine: <code>Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment</code></p>
</li>
<li><p>For current user: <code>Computer\HKEY_CURRENT_USER\Environment</code></p>
</li>
</ul>
</li>
</ol>
<p>When working with 32-bit and 64-bit systems, it's crucial to use the correct registry keys. For example, <code>HKLM64</code> maps to the 64-bit view of the registry, while <code>HKLM32</code> maps to the 32-bit view.</p>
<h2 id="heading-steps-to-create-a-windows-installer">Steps to Create a Windows Installer</h2>
<h3 id="heading-1-prepare-your-nodejs-application">1. Prepare Your Node.js Application</h3>
<p>Ensure your Node.js application is ready for deployment. This includes:</p>
<ul>
<li><p>Having a <code>package.json</code> file with all necessary dependencies.</p>
</li>
<li><p>Creating a main entry point for your application (e.g., <code>app.js</code> or <code>index.js</code>).</p>
</li>
<li><p>Testing your application thoroughly on Windows.</p>
</li>
</ul>
<h3 id="heading-2-install-inno-setup">2. Install Inno Setup</h3>
<p>Download and install Inno Setup from the official website: <a target="_blank" href="https://jrsoftware.org/isinfo.php">Inno Setup</a></p>
<h3 id="heading-3-create-an-inno-setup-script">3. Create an Inno Setup Script</h3>
<p>Create a new file with a <code>.iss</code> extension (e.g., <code>myapp-installer.iss</code>). This script will define how your installer behaves. Here's a basic template:</p>
<pre><code class="lang-plaintext">[Setup]
AppName=My Node.js App
AppVersion=1.0
DefaultDirName={pf}\MyNodeApp
DefaultGroupName=My Node.js App
OutputDir=installer
OutputBaseFilename=myapp-setup

[Files]
Source: "path\to\your\app\*"; DestDir: "{app}"; Flags: recursesubdirs

[Run]
Filename: "{app}\node.exe"; Parameters: "{app}\app.js"; Flags: runhidden

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "MY_APP_HOME"; ValueData: "{app}"; Flags: preservestringtype
</code></pre>
<h3 id="heading-4-customize-the-installer">4. Customize the Installer</h3>
<p>Depending on your application's needs, you may want to:</p>
<ul>
<li><p>Create a Windows service using NSSM (Non-Sucking Service Manager).</p>
</li>
<li><p>Set up environment variables.</p>
</li>
<li><p>Include additional files like Node.js runtime, npm packages, or other dependencies.</p>
</li>
</ul>
<h3 id="heading-5-handle-32-bit-and-64-bit-architectures">5. Handle 32-bit and 64-bit Architectures</h3>
<p>To support both 32-bit and 64-bit Windows systems, you'll need to:</p>
<ul>
<li><p>Include both 32-bit and 64-bit versions of Node.js and any native dependencies.</p>
</li>
<li><p>Use conditional statements in your Inno Setup script to choose the correct files based on the system architecture.</p>
</li>
</ul>
<h3 id="heading-6-implement-logging">6. Implement Logging</h3>
<p>For easier troubleshooting, implement logging in both your Node.js application and the installer:</p>
<ul>
<li><p>Use a logging library like Winston for your Node.js app.</p>
</li>
<li><p>Utilize Inno Setup's built-in logging capabilities for the installation process.</p>
</li>
</ul>
<p>By following these steps and best practices, you can create a Windows installer for your Node.js application. This will make it easier for users to install and use your software, ultimately leading to better adoption and user satisfaction.</p>
]]></content:encoded></item><item><title><![CDATA[Log Parsing Tools Compared: Choosing Between Grep, Awk, and Sed]]></title><description><![CDATA[Log parsing is an essential task in system administration, monitoring, and data analysis. It helps in identifying issues, understanding system behavior, and gaining insights from log files.
In this blog, we will explore the popular log parsing comman...]]></description><link>https://prakhartripathi.hashnode.dev/log-parsing-tools-compared-choosing-between-grep-awk-and-sed</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/log-parsing-tools-compared-choosing-between-grep-awk-and-sed</guid><category><![CDATA[log analysis]]></category><category><![CDATA[grep]]></category><category><![CDATA[awk]]></category><category><![CDATA[sed]]></category><category><![CDATA[logstash]]></category><category><![CDATA[Splunk]]></category><category><![CDATA[elasticsearch]]></category><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Sat, 01 Jun 2024 03:44:13 GMT</pubDate><content:encoded><![CDATA[<p>Log parsing is an essential task in system administration, monitoring, and data analysis. It helps in identifying issues, understanding system behavior, and gaining insights from log files.</p>
<p>In this blog, we will explore the popular log parsing commands - <code>grep</code>, <code>awk</code>, and <code>sed</code>, and discuss how to choose the right tool based on your specific requirements.</p>
<h2 id="heading-types-of-commands">Types of Commands</h2>
<h3 id="heading-grep">Grep</h3>
<p><code>grep</code> (Global Regular Expression Print) is a powerful search utility used for finding patterns within text files.</p>
<h3 id="heading-awk">Awk</h3>
<p><code>awk</code> is a versatile programming language designed for text processing and data extraction.</p>
<h3 id="heading-sed">Sed</h3>
<p><code>sed</code> (Stream Editor) is used for parsing and transforming text streams.</p>
<h2 id="heading-key-considerations-for-choosing-the-right-log-parsing-tool">Key Considerations for Choosing the Right Log Parsing Tool:</h2>
<ul>
<li><p><strong>Size of the Dataset</strong>: Large datasets require efficient tools to minimize processing time and resource usage.</p>
</li>
<li><p><strong>Complexity of Parsing</strong>: Choose a tool that matches the complexity of the parsing and extraction tasks.</p>
</li>
<li><p><strong>Infrastructure Available</strong>: Ensure the tool can run efficiently on your available infrastructure and within any resource constraints.</p>
</li>
<li><p><strong>Performance Metrics</strong>: Evaluate execution time, CPU usage, memory usage, I/O performance, and scalability.</p>
</li>
</ul>
<h2 id="heading-when-to-use-grep-awk-and-sed">When to Use Grep, Awk, and Sed</h2>
<h3 id="heading-grep-1">Grep</h3>
<ul>
<li><p><strong>Best For</strong>: Simple text searches and filtering lines based on patterns.</p>
</li>
<li><p><strong>Performance</strong>: Fastest for simple searches with low CPU and memory usage.</p>
</li>
</ul>
<h3 id="heading-awk-1">Awk</h3>
<ul>
<li><p><strong>Best For</strong>: Complex pattern matching, data extraction, and text manipulation and calculation.</p>
</li>
<li><p><strong>Performance</strong>: Efficient for advanced text processing but slightly slower than <code>grep</code> for basic tasks.</p>
</li>
</ul>
<h3 id="heading-sed-1">Sed</h3>
<ul>
<li><p><strong>Best For</strong>: Stream editing and simple text transformations.</p>
</li>
<li><p><strong>Performance</strong>: Similar to <code>grep</code> for simple tasks, but less intuitive for complex parsing compared to <code>awk</code>.</p>
</li>
</ul>
<h2 id="heading-usage-of-grep-awk-and-sed-commands">Usage of Grep, Awk, and Sed Commands</h2>
<h3 id="heading-grep-2">Grep</h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Find all lines containing "ERROR"</span>
grep <span class="hljs-string">"ERROR"</span> application.log
</code></pre>
<h3 id="heading-awk-2">Awk</h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Extract and print the second field from lines containing "ERROR"</span>
awk <span class="hljs-string">'/ERROR/ {print $2}'</span> application.log
</code></pre>
<h3 id="heading-sed-2">Sed</h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Replace all occurrences of "ERROR" with "WARNING"</span>
sed <span class="hljs-string">'s/ERROR/WARNING/g'</span> application.log
</code></pre>
<h2 id="heading-practical-example-using-awk-vs-grep">Practical Example: Using Awk vs Grep</h2>
<h3 id="heading-scenario-extracting-fields-from-a-log-file">Scenario: Extracting Fields from a Log File</h3>
<p><strong>Log File Example</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span> - - [<span class="hljs-number">12</span>/Mar/<span class="hljs-number">2023</span>:<span class="hljs-number">14</span>:<span class="hljs-number">21</span>:<span class="hljs-number">14</span> <span class="hljs-number">-0700</span>] <span class="hljs-string">"GET /index.html HTTP/1.1"</span> <span class="hljs-number">200</span> <span class="hljs-number">2326</span>
<span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.2</span> - - [<span class="hljs-number">12</span>/Mar/<span class="hljs-number">2023</span>:<span class="hljs-number">14</span>:<span class="hljs-number">22</span>:<span class="hljs-number">01</span> <span class="hljs-number">-0700</span>] <span class="hljs-string">"POST /login HTTP/1.1"</span> <span class="hljs-number">403</span> <span class="hljs-number">534</span>
<span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.3</span> - - [<span class="hljs-number">12</span>/Mar/<span class="hljs-number">2023</span>:<span class="hljs-number">14</span>:<span class="hljs-number">23</span>:<span class="hljs-number">08</span> <span class="hljs-number">-0700</span>] <span class="hljs-string">"GET /images/logo.png HTTP/1.1"</span> <span class="hljs-number">200</span> <span class="hljs-number">456</span>
</code></pre>
<p><strong>Objective</strong>: Extract the IP address and the status code from each log entry.</p>
<h3 id="heading-using-grep">Using Grep</h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Grep cannot directly extract fields; we need to use additional tools like cut or awk.</span>
grep <span class="hljs-string">"ERROR"</span> access.log | awk <span class="hljs-string">'{print $1, $9}'</span>
</code></pre>
<h3 id="heading-using-awk">Using Awk</h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Extract and print the first (IP address) and ninth (status code) fields</span>
awk <span class="hljs-string">'{print $1, $9}'</span> access.log
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Choosing the right log parsing tool depends on your specific needs and the complexity of the tasks at hand. <code>grep</code> is ideal for simple searches, <code>awk</code> excels in complex data extraction and manipulation, and <code>sed</code> is powerful for stream editing and transformations.  </p>
<p>Additionally, tools like Logstash, Splunk, and Elasticsearch offer high scalability and performance for handling large datasets(tens of gigabytes to terabytes), organizations need to consider the associated infrastructure and resource requirements as part of their deployment strategy.</p>
<p>Happy log parsing!</p>
<p><img src="https://pbs.twimg.com/media/GGMmdY8bsAAIo0H.jpg:large" alt="Shubham Sharma on X: &quot;Commands for Log Parsing Credit: @bytebytego  https://t.co/5ucwHfLPvh&quot; / X" /></p>
<p>Credits: <a target="_blank" href="https://twitter.com/sahnlam/status/1796048721517637922">Bytebytego</a></p>
]]></content:encoded></item><item><title><![CDATA[npm security best practices]]></title><description><![CDATA[This blog discusses security practices to follow while using npm packages, for both frontend and backend developers.
Importance of package-lock.json
In Node when your code references library A, that library references library B and that in turn refer...]]></description><link>https://prakhartripathi.hashnode.dev/npm-security-best-practices</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/npm-security-best-practices</guid><category><![CDATA[npm]]></category><category><![CDATA[Security]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Sun, 04 Feb 2024 12:51:37 GMT</pubDate><content:encoded><![CDATA[<p>This blog discusses security practices to follow while using npm packages, for both frontend and backend developers.</p>
<h3 id="heading-importance-of-package-lockjson">Importance of package-lock.json</h3>
<p>In Node when your code references library A, that library references library B and that in turn references Library C. Running <code>npm install</code> will install the latest version available of those dependencies <em>(as long as no particular version is specified)</em>.</p>
<p>Upon installation, a new file is created called <code>package-lock.json</code> with the exact versions.</p>
<p>A new machine pulls the repo and runs <code>npm install</code>, if we didn’t have the <code>package-lock.json</code> the machine may pull the newer version of libraries and as a result possibly that your code no longer works are very high.</p>
<p>If <code>package-lock.json</code> exists in the repo, the <code>npm install</code> command will install the dependencies of same version as present in original repo, and as a result making the code consistent.</p>
<blockquote>
<p>Always commit package.json and package-lock.json file along side of it.<br />In build,prod environment use <code>npm ci</code> for continuos integration and deployment workflows.</p>
</blockquote>
<h3 id="heading-managing-dependencies">Managing dependencies</h3>
<p>To manage npm dependency issues on repositories, it's advisable to use <a target="_blank" href="https://www.mend.io/renovate/">Renovate</a>, <a target="_blank" href="https://github.com/dependabot">Dependabot</a>, <a target="_blank" href="https://www.npmjs.com/package/snyk">Snyk</a></p>
<p><strong>Dependabot</strong> provides automated dependency upgrades for software repositories. Users can receive automated reports of new security vulnerabilities in their repo's dependencies.</p>
<p><strong>Renovate</strong> is an open-source tool that automatically creates pull requests for all types of dependency updates. It offers real-time scanning, annotated updates, and verification against existing tests to avoid regression errors.</p>
<p><strong>Snyk</strong> is a developer-first cloud-native security tool that covers multiple areas of application security, including open source, application code, container, and infrastructure as code security. Snyk CLI can be authorized in the CI/CD programatically to use Snyk for npm dependency security vulnerabilities</p>
<h3 id="heading-references">References</h3>
<ul>
<li><p><a target="_blank" href="https://snyk.io/blog/ten-npm-security-best-practices/">ten npm security best practices (snyk.io)</a></p>
</li>
<li><div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://ghumare64.medium.com/managing-dependencies-are-the-issue-c0ab844c05e0">https://ghumare64.medium.com/managing-dependencies-are-the-issue-c0ab844c05e0</a></div>
<p> </p>
</li>
<li><div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/hnasr/status/1728755651659079980">https://twitter.com/hnasr/status/1728755651659079980</a></div>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Horizontal vs Vertical scaling]]></title><description><![CDATA[Definition
Scaling is a technique that modifies any system's size by extending or contracting it to meet a requirement. The scaling procedure can be accomplished by adding resources to the current system or by integrating a new one.
Real-world exampl...]]></description><link>https://prakhartripathi.hashnode.dev/scaling</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/scaling</guid><category><![CDATA[System Design]]></category><category><![CDATA[scalability]]></category><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Tue, 02 Jan 2024 15:36:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704209529670/f4064212-5748-493f-a016-51f03d682122.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-definition">Definition</h3>
<p>Scaling is a technique that modifies any system's size by extending or contracting it to meet a requirement. The scaling procedure can be accomplished by adding resources to the current system or by integrating a new one.</p>
<h3 id="heading-real-world-example">Real-world example</h3>
<p>Suppose your family currently has four members. And you have a water tank, according to your present situation. On vacations, your relatives arrive, and your family size increases to twelve. To fulfill the current water requirements, you have two options:</p>
<ol>
<li><p>Add another water tank</p>
</li>
<li><p>Increase the size of water tank</p>
</li>
</ol>
<p>If you read definition again,you will be able to understand better</p>
<h3 id="heading-vertical-scaling">Vertical scaling</h3>
<p><strong>Vertical scaling</strong>, also known as <strong>scaling up</strong>, involves adding more processing power or resources to a <strong>single instance of a system</strong>, such as adding more CPU, RAM, or storage to a virtual machine. <em>(second option in real-world example above)</em></p>
<p>The major drawbacks of vertical scaling are the single point of failure and the risk of high downtime.</p>
<h3 id="heading-horizontal-scaling">Horizontal scaling</h3>
<p><strong>Horizontal scaling</strong>, also known as <strong>scaling out</strong>, involves <strong>adding more resource</strong>s (e.g., servers, storage, and networking components) <strong>to a system</strong> to handle increasing workloads. <em>(first option in real-world example above)</em></p>
<p>The major drawbacks of horizontal scaling has increased complexity and data inconsistency</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Both methods have their own advantages and disadvantages, and which approach is used depends on a given system's specific needs and constraints.</p>
]]></content:encoded></item><item><title><![CDATA[Scaling Node.js Applications with Clustering]]></title><description><![CDATA[Node.js applications running on a single process are limited to the performance of a single CPU core. However, most modern computers have multiple cores, so how can we take advantage of all that processing power? This is where clustering comes in.
Wh...]]></description><link>https://prakhartripathi.hashnode.dev/scaling-nodejs-applications-with-clustering</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/scaling-nodejs-applications-with-clustering</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Mon, 18 Dec 2023 09:54:53 GMT</pubDate><content:encoded><![CDATA[<p>Node.js applications running on a single process are limited to the performance of a single CPU core. However, most modern computers have multiple cores, so how can we take advantage of all that processing power? This is where clustering comes in.</p>
<h2 id="heading-what-is-clustering">What is Clustering?</h2>
<p>Clustering allows Node.js applications to spawn multiple child processes (workers) to handle incoming requests. This allows the workload to be distributed across multiple CPU cores, improving performance and concurrency.</p>
<h2 id="heading-how-clustering-works">How Clustering Works</h2>
<p>Here's a quick overview of how clustering works:</p>
<h3 id="heading-1-create-a-cluster">1. Create a Cluster</h3>
<p>Use the built-in<code>cluster</code> module and check if the current process is a master or worker. The master process manages the workers.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> cluster = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cluster'</span>);

<span class="hljs-keyword">if</span>(cluster.isMaster) {
  <span class="hljs-comment">// fork workers</span>
} <span class="hljs-keyword">else</span> {
  <span class="hljs-comment">// worker processes</span>
}
</code></pre>
<h3 id="heading-2-fork-worker-processes">2. Fork Worker Processes</h3>
<p>The master process can fork multiple worker processes using <code>cluster.fork()</code> to utilize multiple CPU cores.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; numCPUs; i++) {
  cluster.fork(); 
}
</code></pre>
<h3 id="heading-3-distribute-requests">3. Distribute Requests</h3>
<p>The master process listens for connections and distributes incoming requests among the workers in a <strong>round-robin</strong> fashion.</p>
<h3 id="heading-4-handle-the-worker-lifecycle">4. Handle the worker lifecycle</h3>
<p><strong><em>If a worker dies, the cluster module allows the master process to fork a new worker to replace it for high availability.</em></strong></p>
<h2 id="heading-key-benefits">Key Benefits</h2>
<ul>
<li><p>Improved performance through better <strong>utilization of CPU cores</strong></p>
</li>
<li><p>Increased capacity to handle <strong>more concurrent requests</strong></p>
</li>
<li><p><strong>High availability</strong> through graceful handling of worker failures</p>
</li>
</ul>
<p>By implementing clustering, Node.js apps can scale a lot better across multi-core systems. Give it a try!</p>
]]></content:encoded></item><item><title><![CDATA[Decoding Node.js Callback Priority: A Guide to Interview Questions on Scheduling Methods]]></title><description><![CDATA[This blog post is focused on a question interviewers generally tend to ask in interviews to test candidates' proficiency in understanding the priority of methods used for scheduling callbacks.
In Node.js, there are several methods for scheduling call...]]></description><link>https://prakhartripathi.hashnode.dev/decoding-nodejs-callback-priority</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/decoding-nodejs-callback-priority</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Tue, 28 Nov 2023 09:08:52 GMT</pubDate><content:encoded><![CDATA[<p>This blog post is focused on a question interviewers generally tend to ask in interviews to test candidates' proficiency in understanding the priority of methods used for scheduling callbacks.</p>
<p>In Node.js, there are several methods for scheduling callbacks:</p>
<ul>
<li><p><strong>Timers</strong> (setTimeout(), setInterval())</p>
</li>
<li><p><strong>Promises</strong></p>
</li>
<li><p><strong>setImmediate()</strong></p>
</li>
<li><p><strong>process.nextTick()</strong></p>
</li>
<li><p><strong>I/O events</strong> (actions involving reading from or writing to external resources such as files, network sockets, or other I/O operations)</p>
</li>
</ul>
<p>Let's understand using an example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Start'</span>);

process.nextTick(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'process.nextTick callback'</span>);
});

<span class="hljs-built_in">Promise</span>.resolve().then(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Promise microtask'</span>);
});

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout1 callback'</span>);
}, <span class="hljs-number">0</span>);

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout2 callback'</span>);
}, <span class="hljs-number">100</span>);

setImmediate(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setImmediate callback'</span>);
});

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'End'</span>);
</code></pre>
<p>The output will be:</p>
<pre><code class="lang-plaintext">Start
End
process.nextTick callback
Promise microtask
setTimeout1 callback
setImmediate callback
setTimeout2 callback
</code></pre>
<ul>
<li><p><code>Start</code> and <code>End</code> are printed first because they are <strong>non-blocking (synchronous)</strong> operations</p>
</li>
<li><p>Both <code>process.nextTick()</code> and <code>Promises</code> are executed at the end of the current event loop cycle, but <strong>process.nextTick() has a higher priority than promises</strong>. Therefore, the<code>process.nextTick()</code> callback is executed first, followed by the <code>Promise</code> microtask.</p>
</li>
<li><p>The<code>setTimeout1</code> callback is scheduled in the timer phase of the event loop. <strong>Even though the specified delay is 0 milliseconds, it still goes through the timer phase</strong></p>
</li>
<li><p><strong>The</strong> <code>setImmediate</code><strong>callback</strong> is executed after the I/O phase of the event loop. It <strong>runs after I/O events but before the timers</strong>.</p>
</li>
<li><p>At last, the <code>setTimeout</code> callback is called at last because it has a delay of 100 milliseconds</p>
</li>
</ul>
<p><strong>Conclusion:</strong> The priority order can be considered as follows:</p>
<ol>
<li><p>Non-blocking operations</p>
</li>
<li><p>process.nextTick()</p>
</li>
<li><p>Promises</p>
</li>
</ol>
<p>After this, the priority is: In a non-I/O loop, the execution order is <code>setTimeout()</code> &gt; <code>setImmediate()</code>. In an I/O loop, the execution order is <code>setImmediate()</code> &gt; <code>setTimeout()</code></p>
<p>Here is an example of an I/O loop:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);

fs.readFile(__filename, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'start'</span>);

  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout'</span>);
  }, <span class="hljs-number">0</span>);

  setImmediate(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setImmediate'</span>);
  });

  process.nextTick(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'process.nextTick'</span>);
  });
});
</code></pre>
<p>Output of the above would be:</p>
<pre><code class="lang-javascript">start
process.nextTick
setImmediate
<span class="hljs-built_in">setTimeout</span>
</code></pre>
<p>For further reading in-depth, read Node.js docs <a target="_blank" href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick">here</a></p>
]]></content:encoded></item><item><title><![CDATA[Git commands]]></title><description><![CDATA[Git is a version control system used to track changes in software by developers.
It was created by Linus Torvalds.
Git, SVN, and Mercurial are other VCSs used out there.
In this blog post, we will be discussing the most commonly used commands.

git c...]]></description><link>https://prakhartripathi.hashnode.dev/git-commands</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/git-commands</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[version control]]></category><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Sat, 25 Nov 2023 11:58:42 GMT</pubDate><content:encoded><![CDATA[<p><strong>Git</strong> is a version control system used to track changes in software by developers.</p>
<p>It was created by <strong>Linus Torvalds.</strong></p>
<p>Git, SVN, and Mercurial are other VCSs used out there.</p>
<p>In this blog post, we will be discussing the most commonly used commands.</p>
<ul>
<li><p><strong>git config</strong>: Configure git globally using these commands:</p>
<ul>
<li><p><code>git config --global user.name</code> <em>[username]</em></p>
</li>
<li><p><code>git config --global user.email</code> <em>[email ID]</em></p>
</li>
<li><p><code>git config --global core.editor nano</code></p>
<ul>
<li>above command sets up the default editor for git to nano; other available editors are vim, vi, etc.</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>git clone:</strong> <code>git clone https://github.com/repo_name.git</code> clones a remote repo. onto the local machine.</p>
</li>
<li><p><strong>git init:</strong> Initialize a git repository inside the current directory.</p>
</li>
<li><p><strong>git remote:</strong> Here, the "origin" works as an alias for the repo URL in further commands.</p>
<ul>
<li><p><code>git remote add origin</code> <a target="_blank" href="https://github.com/repo_name.git"><code>https://github.com/repo_name.git</code></a> creates a connection from the local repository to the remote repository.</p>
</li>
<li><p><code>git remote -v</code> displays remote for push and pull</p>
</li>
<li><p><code>git remote remove origin</code> removes remote from the current local repo.</p>
</li>
</ul>
</li>
<li><p><strong>git status:</strong> Displays the modified, staged, and unstaged files</p>
</li>
<li><p><strong>git add:</strong> This command is used to move untracked files into staging area. It can be done in 2 ways:</p>
<ul>
<li><p><code>git add &lt;file1.txt&gt; &lt;file2.txt&gt;</code> This command only adds file1 and file2 and keeps other untracked files as it is, to staging area.</p>
</li>
<li><p><code>git add .</code> the command adds all untracked files to the staging area.</p>
</li>
</ul>
</li>
<li><p><strong>git commit:</strong> The modified files in the staging area are committed with a message.</p>
<ul>
<li><p>Assume you made additional changes after the last commit and want to include them in the last commit. Use these commands in the following order:</p>
<p>  <code>git add additional_file.txt ; git commit --amend</code></p>
</li>
<li><p>Assume you need to change the commit message<br />  <code>git commit --amend -m "New commit message"</code></p>
</li>
</ul>
</li>
<li><p><strong>git push:</strong> <code>git push origin main</code> This command pushes changes from the local 'main' branch to the 'main' branch on the 'origin' remote.</p>
</li>
<li><p><strong>git pull:</strong> <code>git pull origin master</code> This command fetches changes from the default remote repository and merges them into the current branch. It's combination of <code>git fetch</code> and <code>git pull</code> commands.</p>
</li>
<li><p><strong>git log:</strong> displays the log of commits in the git repository, including information such as commit hashes, authors, dates, and commit messages.When you run <code>git log</code> without any additional options, it uses the default pager. The pager allows you to navigate through the commit history one page at a time. The following commands help navigate commit history:</p>
<p>  <code>f:</code> next page, <code>b</code>: prev page, <code>/</code> : search, <code>n</code>: next match, <code>p</code>: prev match,<code>q</code>: quit</p>
<ul>
<li><p><code>git log -n 5</code> <em>[displays latest 5 commits]</em></p>
</li>
<li><p><code>git log -- &lt;file-path&gt;</code> <em>[displays commit history specifically for the given file</em>]</p>
</li>
<li><p><code>git log --author=&lt;user.name&gt;</code> <em>[displays commits by particular developer]</em></p>
</li>
<li><p><code>git log --since=&lt;date&gt;</code> <em>[displays commit since, specified date: YYYY-MM-DD}]</em></p>
</li>
<li><p><code>git log --after=&lt;date&gt;</code> <em>[displays commit</em> after*, specified date: YYYY-MM-DD}]*</p>
</li>
<li><p><code>git log --oneline</code> <em>[displays condensed output, commit hash, and message]</em></p>
</li>
<li><p><code>git log --grep='login'</code> <em>[displays only those commits whose commit messages contain the string</em> <code>login</code><em>]</em></p>
</li>
<li><p><code>git log -p</code> Command is used to display the commit history along with the corresponding patch (changes) introduced in each commit. This is useful for reviewing the detailed changes made in each commit.</p>
</li>
</ul>
</li>
</ul>
<p>    The above commands can also be applied in combination as attributes.</p>
<ul>
<li><p><strong>git cherry-pick:</strong> <code>git cherry-pick &lt;commit_id&gt;</code> merges the commit with <code>commit-id</code> the current local repository. <strong><em>This command can be used to merge a specific commit from one branch to another.</em></strong></p>
</li>
<li><p><strong>git fetch:</strong> <code>git fetch origin</code> This command fetches the changes from the 'origin' remote repository, but it does not modify your working directory or merge the changes into your local branch.</p>
</li>
<li><p><strong>git branch:</strong> Displays all the branches (the current branch is shown with a star)</p>
<ul>
<li><p><code>git branch -a</code> <em>[shows all remote and local branches]</em></p>
</li>
<li><p><code>git branch dev-prakhar</code> <em>[creates branch dev-prakhar]</em></p>
</li>
<li><p><code>git branch -d branch1</code> <em>[deletes branch1]</em></p>
</li>
</ul>
</li>
<li><p><strong>git checkout:</strong> Command has various purposes as branching.</p>
<ul>
<li><p><code>git checkout feature1</code> the command used to switch to an existing branch.</p>
</li>
<li><p><code>git chekout -b feature2</code> this command creates a new branch and switches to it also.</p>
</li>
<li><p><code>git checkout -- myfile.txt</code> this command discards changes in a specific file</p>
</li>
</ul>
</li>
<li><p><strong>git stash:</strong> Saves unstaged changes to a stash, which can be later used so that you can switch branches or perform other operations without committing your changes</p>
<ul>
<li><p><code>git stash save -u "[WIP] Login feature"</code></p>
</li>
<li><p><code>git stash list</code> <em>[View list of stashes]</em></p>
</li>
<li><p><code>git stash apply</code> <em>[apply the last stash]</em></p>
<ul>
<li><code>git stash apply &lt;stash-ref&gt;</code>[<em>Applies a particular stash from the list]</em></li>
</ul>
</li>
<li><p><code>git stash pop</code> <em>[Apply the latest stash and remove it from the stash list]</em></p>
</li>
</ul>
</li>
</ul>
<p>Use Gitlens vs code extension to find the difference between two branches for the same file.</p>
]]></content:encoded></item><item><title><![CDATA[When 0.1 + 0.2 Doesn't Equal 0.3]]></title><description><![CDATA[Hey fellow devs, ever wondered why interviewers love throwing this tricky question at you? Brace yourselves, we're about to dive into the quirky world of JavaScript and floating-point numbers. 🤪
Here's the question: "What's the result of the console...]]></description><link>https://prakhartripathi.hashnode.dev/when-01-02-doesnt-equal-03</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/when-01-02-doesnt-equal-03</guid><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Mon, 06 Nov 2023 16:57:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699283780894/7bfa4de1-01ff-4654-a6d5-67a9b0200211.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey fellow devs, ever wondered why interviewers love throwing this tricky question at you? Brace yourselves, we're about to dive into the quirky world of JavaScript and floating-point numbers. 🤪</p>
<p>Here's the question: "What's the result of the <code>console.log(0.1 + 0.2)</code>?" 🧐 It's so quirky that even interviewers might not know the answer themselves! 😂</p>
<p>And here's the punchline: It prints <code>0.30000000000000004</code> to the console! 🤯</p>
<p>So, what's the deal? Well, it's all about how JavaScript handles these wacky floating-point numbers. Let me break it down for you.</p>
<p>💡 Computers store numbers in binary. But here's the kicker: not all numbers can be perfectly translated into binary. 🤖</p>
<p>When you add 0.1 and 0.2 in decimal (our usual numbering system), you expect to get a neat 0.3, right? But in binary, these numbers have never-ending fractions like <code>0.0001100110011</code>... and <code>0.001100110011</code>... 😬</p>
<p>When you add them in binary, it's like trying to add up never-ending fractions, and that's where the fun begins! Computers have limited space for these fractions, so they have to round them off or chop them at some point. And that's when you end up with <code>0.30000000000000004</code>. 🙈</p>
<p>This is a common issue in many programming languages and environments. While the error, in this case, is extremely small and usually not noticeable in everyday calculations, <strong>it can become significant when dealing with critical applications that require high precision</strong>.</p>
<p>💡 <strong>The Bonus Part:</strong> I've got a bonus video for you to impress your fellow devs at the next code meetup! 📺</p>
<p><strong>Bonus video</strong></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=5tJPXYA0Nec">https://www.youtube.com/watch?v=5tJPXYA0Nec</a></div>
]]></content:encoded></item><item><title><![CDATA[DRY Approach]]></title><description><![CDATA[DRY which stands for Don't Repeat Yourself, is a fundamental rule that should be followed while developing software.
The concept (AFAIK) simply means to NOT rewrite the same piece of code again and again.
Let's say, for example, you are designing sch...]]></description><link>https://prakhartripathi.hashnode.dev/dry-approach</link><guid isPermaLink="true">https://prakhartripathi.hashnode.dev/dry-approach</guid><category><![CDATA[coding]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Prakhar tripathi]]></dc:creator><pubDate>Sat, 14 Oct 2023 17:56:05 GMT</pubDate><content:encoded><![CDATA[<p><strong>DRY which stands for Don't Repeat Yourself</strong>, is a fundamental rule that should be followed while developing software.</p>
<p>The concept (AFAIK) simply means to <strong>NOT rewrite the same piece of code</strong> again and again.</p>
<p>Let's say, for example, you are designing schema for your database using Mongoose, and you have used key timestamps, which by default insert createdAt and updatedAt fields in every document created. <em>(here createdAt and updatedAt fields denote the time, new data was created or updated in the database)</em></p>
<p>But a backend developer unknown of the functionality of the timestamps key might add keys - created_at and updated_at in that schema and implement a method to update the updated_at field in the database in all API routes that have update queries.</p>
<p>He/she won't stop there and goes on implementing the same thing in other schemas and routes, and queries related to those schemas.</p>
<p>Now, there are two problems which could've been avoided:</p>
<ol>
<li><p>The developer could've reduced the lines of code if had knowledge of the timestamp field or seen its implementation in the codebase already there</p>
</li>
<li><p>If he/she had followed the first step, there wouldn't have been a repetition of the code to implement created_at and updated_at</p>
</li>
</ol>
<p>The above solutions might not work all the time, the permanent solution is to <strong>read the documentation</strong> of libraries that you are using in your code. This will not only deepen your understanding but also increase your knowledge about methods that can be leveraged to reduce your code complexity and achieve a <strong>DRY approach.</strong></p>
]]></content:encoded></item></channel></rss>