<?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[Abhis3kh's Thoughts]]></title><description><![CDATA[Blog for the things I don't understand but trying to understand ]]></description><link>https://abhisekh.in</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 13:31:03 GMT</lastBuildDate><atom:link href="https://abhisekh.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[What Really Happens After You Run a SQL Query - SQL Journey ]]></title><description><![CDATA[I just finished a project where we were hitting an internal database - large dataset, reads happening constantly, the kind of workload where every extra millisecond compounds into something users actu]]></description><link>https://abhisekh.in/what-really-happens-after-you-run-a-sql-query-sql-journey</link><guid isPermaLink="true">https://abhisekh.in/what-really-happens-after-you-run-a-sql-query-sql-journey</guid><category><![CDATA[Databases]]></category><category><![CDATA[SQL]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[optimization]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Wed, 04 Mar 2026 22:39:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6314dc8a041b51e1712e5380/685b674f-584a-4b39-801d-0f96bbdcef76.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p>I just finished a project where we were hitting an internal database - large dataset, reads happening constantly, the kind of workload where every extra millisecond compounds into something users actually feel. At some point I stopped tuning blindly my application code and asked myself a question : what actually happens between the moment my application sends a query and the moment rows come back?</p>
<p>I had a rough idea. But rough don't tell you why adding an index sometimes does nothing. They don't tell you which of the five layers your query is getting stuck in. My philosophy has always been the same - you can't optimize what you don't how background processing is working in the first place. Find how the thing actually works, find the gaps, fix the gaps.</p>
<h3>You write a query. You hit enter. Data comes back.</h3>
<p>I stopped there. I got what what i needed, move on. But that "hitting enter" part? There's a lot happening underneath it that most people never bother to understand and until this point neither do i - and that's fine, until queries get slow or production breaks and you have no idea where to even start looking - it comes with experience.</p>
<p>I've seen engineers with years of experience stare at a slow query and just add more hardware. Sometimes that works. Usually it doesn't. Because the problem wasn't resources - it was that the database chose a bad plan, or there was no index, or someone didn't wrap two writes in a transaction. Things you'd catch instantly if you understood what happens after you hit enter.</p>
<hr />
<h2><strong>The Query</strong></h2>
<pre><code class="language-sql">SELECT name, age FROM users WHERE city = 'Kolkata';
</code></pre>
<p>Simple enough. But the path this takes inside the database isn't simple at all. There are at least five distinct layers it passes through, each doing something completely different. Miss any one of them and you're working with an incomplete model. Incomplete models lead to wrong assumptions. Wrong assumptions lead to 3am incidents which i had past experiences with.</p>
<hr />
<h2><strong>Step 1 - Transport Layer</strong></h2>
<p>Before the database reads a single character of your SQL, it first has to receive it.</p>
<p>Your application sends the query over TCP. Raw bytes. The database is listening on a port - 5432 for Postgres, 3306 for MySQL - and receives those bytes according to a wire protocol. Postgres has its own. MySQL has its own. They're not interchangeable, which is why your MySQL driver doesn't work against a Postgres server and gives you an error that feels completely unrelated to the actual problem.</p>
<p>Authentication happens here too. The database checks your credentials, then checks whether your user has SELECT permission on the table you're querying. If not, the query dies right here. Doesn't even get parsed.</p>
<p>Now, something a lot of junior engineers don't think about: opening a TCP connection costs real time. You've got the three-way handshake, memory allocation on the server side, thread assignment - it adds up. If your application opened a fresh connection for every single query, you'd spend more time connecting than actually running SQL. This is why <strong>connection pooling exists</strong>.</p>
<pre><code class="language-python"># The pool is created once when your app starts
pool = psycopg2.pool.ThreadedConnectionPool(minconn=5, maxconn=20, dsn="...")

# Every request borrows a connection that's already open
conn = pool.getconn()
</code></pre>
<p>I've seen applications that weren't using a connection pool go from 800ms average query time down to under 50ms just by adding one. The queries themselves didn't change. The database didn't change. Just stopped paying the connection overhead on every request. It's one of those fixes that feels too simple to be real until you see the numbers.</p>
<hr />
<h2><strong>Step 2 - The Query Processor Layer</strong></h2>
<p>This is where most of the work happens. There are four distinct things happening inside it, and collapsing them into one is how people end up with broken mental models that don't help when something actually goes wrong.</p>
<h3><strong>Parsing</strong></h3>
<p>The parser reads your SQL as plain text and decides whether it's even valid. It doesn't know your tables, doesn't know your schema, doesn't care about any of that yet. It just checks whether the words and symbols you wrote form a legal sentence in SQL's grammar. A misplaced comma, a typo in a keyword, a quote you forgot to close - any of it stops everything cold.</p>
<pre><code class="language-sql">SELCT name, age FORM users WHERE city = 'Kolkata';
-- ERROR: syntax error at or near "SELCT"
</code></pre>
<p>Nothing else runs. Not the semantic check, not the optimizer. Just an error.</p>
<p>If the syntax is valid, the parser produces a <strong>parse tree</strong> - your query represented as a data structure instead of text. The <code>SELECT</code> is the root. The column list, the <code>FROM</code>, the <code>WHERE</code> - each becomes a node. That tree is what every other step works from. You never see it. But every query you've ever written turned into one the moment you hit enter.</p>
<h3><strong>The Semantic Analyzer - missing from the original diagram</strong></h3>
<p>The parser said the sentence is grammatically correct. The semantic analyzer asks whether it actually means anything.</p>
<p>It goes to the system catalog - the database's own internal record of everything that exists in it, every table, every column, every type - and checks whether the things you named are real. <em>Does a table called</em> <code>users</code> <em>exist? Does it have a column called</em> <code>name</code><em>? Is</em> <code>city</code> <em>a text column, or something else you can't compare to a string?</em></p>
<pre><code class="language-sql">-- Valid syntax, fails semantic analysis
SELECT name, age FROM users WHERE city = 'Kolkata';
-- ERROR: relation "users" does not exist
</code></pre>
<p>That error you've seen a hundred times - <code>relation does not exist</code>, <code>column does not exist</code> - that's this step catching a typo before anything else runs. <strong>The reason it's separate from parsing is that the parser has no idea what tables you have.</strong> It only knows grammar. <strong>The semantic analyzer is the part that connects the words in your query to real objects in your database</strong>. Once I understood this, those errors stopped feeling cryptic. They're just the catalog saying "I checked, and that thing isn't here."</p>
<h3><strong>The Rewriter</strong></h3>
<p>Once semantics pass, the query may be rewritten into a different form before optimization begins.</p>
<p>The clearest example is views. When you query a view, the database doesn't run the view separately and combine the results. It expands the view's definition directly into your query before the optimizer sees anything at all.</p>
<pre><code class="language-sql">-- Assume you defined this earlier
CREATE VIEW active_users AS
    SELECT * FROM users WHERE status = 'active';

-- You write this
SELECT name FROM active_users WHERE city = 'Kolkata';

-- The rewriter turns it into this before anything else happens
SELECT name FROM users
WHERE status = 'active' AND city = 'Kolkata';
</code></pre>
<p>The optimizer never knows a view was involved. It just gets a clean query against a real table. This is actually reassuring once you know it - it means using a view doesn't cost you anything at the query level. The abstraction is free. The rewriter handles the expansion silently so the optimizer never has to reason about indirection.</p>
<p>There's other work it does too - flattening subqueries, pushing conditions closer to where the data lives, simplifying things that evaluate to constants. Most of it you'll never notice, which is exactly the point.</p>
<h3><strong>The Query Optimizer - the most important step</strong></h3>
<p>If you understand nothing else from this article, understand what the optimizer does.</p>
<p>The optimizer takes the rewritten query and figures out the best way to actually run it. Not just one way - <strong>it generates multiple candidate plans, estimates the cost of each, and picks the cheapest one</strong>. The cost isn't wall-clock time directly. It's a proxy - in Postgres, roughly the number of disk page reads the plan is expected to require. Low cost means fewer reads, which usually means faster.</p>
<pre><code class="language-sql">SELECT name, age FROM users WHERE city = 'Kolkata';
</code></pre>
<p>Two obvious plans for this:</p>
<pre><code class="language-plaintext">Option A - Sequential Scan
Scan every page in the users table.
Filter rows where city = 'Kolkata'.
Cost estimate: 42.7

Option B - Index Scan on city_index
Walk the B+Tree index on the city column.
Read only the pages containing matching rows.
Cost estimate: 0.04
</code></pre>
<p>Both give you the same rows. The cost difference is roughly 1000x. The optimizer picks Option B.</p>
<p>Those estimates come from statistics the database keeps about your data - how many rows exist, how many distinct values each column has, how the values are distributed. When those statistics are fresh and accurate, the optimizer makes good choices. When they're stale - say, your table grew by an order of magnitude since the last time stats were collected - the optimizer is working from a picture of your data that no longer looks like your actual data. It picks a plan that seemed reasonable based on what it knew. You feel the result as a query that used to be fast and suddenly isn't, with no obvious explanation.</p>
<p><code>EXPLAIN</code> shows you which plan it chose:</p>
<pre><code class="language-sql">EXPLAIN SELECT name, age FROM users WHERE city = 'Kolkata';

-- Index Scan using users_city_idx on users
--   Index Cond: (city = 'Kolkata')
-- Planning Time: 0.3 ms
</code></pre>
<p><code>Seq Scan</code> where you expected <code>Index Scan</code> means the optimizer didn't use your index - either because it doesn't exist or because outdated stats made a full scan look cheaper. Running <code>EXPLAIN ANALYZE</code> instead of plain <code>EXPLAIN</code> actually executes the query and shows you real row counts next to the estimates. That gap, when it's large, is usually the explanation for whatever you're debugging.</p>
<p>I run <code>EXPLAIN</code> on every non-trivial query before it ships. Not because I distrust the optimizer, but because there's a big difference between thinking a plan will be good and confirming it is. The number of times those two have disagreed on me is higher than I'd like to admit.</p>
<hr />
<h2><strong>Step 3 - The Execution Engine</strong></h2>
<p>The optimizer chose a plan. Now something has to actually run it.</p>
<p>The execution engine walks the plan tree and carries out each operation in order - index scan, key lookup, filter, sort, whatever the plan calls for - passing rows from one step to the next like a relay. It's not doing anything clever. The clever part already happened. The execution engine just follows instructions.</p>
<p>For our query, it goes like this:</p>
<pre><code class="language-plaintext">1. Walk the city_index B+Tree to find rows where city = 'Kolkata'
   → Returns tuple IDs (row pointers)

2. For each tuple ID, fetch the actual row from the table heap
   → Reads name, age off the page

3. Stream rows back up the call stack
</code></pre>
<p>That second step - going back to the table to get columns that aren't in the index - is called a heap fetch. It's easy to miss because the index lookup feels like the whole thing. But the index only stores what you indexed, plus a pointer. Anything else has to be fetched separately. On our project, we had implemented the right index on the filter column. The queries were still slower than they should have been. That was the heap fetch - thousands of extra page reads per second that nobody had thought about because the index itself felt sufficient.</p>
<p>Adding those two columns to the index fixed it. A covering index - one that includes every column the query needs - means the execution engine never has to leave the index at all. The difference in something read-heavy is hard to miss once you've seen it. It has its own drawbacks.</p>
<hr />
<h2><strong>Step 4 - The Storage Engine</strong></h2>
<p>The execution engine doesn't touch disk directly. It calls down into the storage engine, which handles everything at the physical level - pages, memory, concurrency, crash recovery.</p>
<p>Four things live here that are worth actually understanding.</p>
<p>First is the buffer manager : Databases don't read individual rows off disk. They read pages - fixed-size blocks, 8KB in Postgres. The buffer manager keeps a pool of recently-used pages in memory. If the page you need is already there, you get it from RAM and it's fast. If it isn't, the buffer manager reads it from disk, caches it, and keeps it warm for next time. This is why the same query often runs faster on the second call - the first one paid the disk cost and left the pages where the second one could find them. On our project this was immediately visible. Cold-start query times were a different world from what the same queries did after the system had been running under load for a few minutes. The buffer pool was the difference.</p>
<p>Then there's the lock manager : Reads can happen in parallel - shared locks don't conflict with each other. Writes can't. A write needs an exclusive lock on the row, which means waiting for every existing reader to finish and blocking any new ones until the write is done. One writer, or many readers, never both at once. Without this the database would let two concurrent updates race against each other, and whoever wrote last would quietly undo the other one. No error, no warning, just a number that's wrong.</p>
<p>The transaction manager is what makes writes safe across multiple statements. Take this:</p>
<pre><code class="language-sql">BEGIN;
    UPDATE accounts SET balance = balance - 500 WHERE id = 1;
    UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
</code></pre>
<p>If the database crashes after the first UPDATE but before COMMIT, neither change survives. Both rows go back to their original values when the database restarts. The transaction manager sees the uncommitted transaction in the log and rolls it back. Nothing half-applied, nothing missing.</p>
<p>Without that BEGIN wrapped around both writes - if someone just ran them as two standalone statements - a crash between them leaves one account debited and the other unchanged. I've seen this in real production code. The person who wrote it thought the two statements were close enough together that the risk was negligible. It usually is. Until it isn't.</p>
<p>Last is the recovery manager. Every change is written to the Write-Ahead Log - an append-only log file - before it's applied to the actual data. That's sequential writes, which are fast. On a crash, the database replays the WAL on startup and reconstructs anything that was committed but hadn't been flushed to the data files yet. The system call that actually persists the WAL to physical storage is <code>fsync</code>. Turn it off and you get better throughput, but a crash can take commits with it that the application already acknowledged as successful. Some workloads accept that tradeoff - they care more about speed than strict durability. Most production databases shouldn't. The gap between "I turned off fsync knowingly" and "I turned off fsync because I read it was faster" is a postmortem waiting to happen.</p>
<hr />
<h2><strong>So what</strong></h2>
<p>Add indexes on columns you filter by. Without one, the optimizer has no choice but to scan the whole table - not because it's dumb, because there's literally nothing faster available to it.</p>
<p>Run <code>EXPLAIN</code> before you ship any query that'll run against real data at scale. Doesn't take long. Tells you exactly what the optimizer decided. The plan you assumed it would use and the plan it actually chose are sometimes the same. Not always.</p>
<pre><code class="language-sql">EXPLAIN ANALYZE SELECT name, age FROM users WHERE city = 'Kolkata';

-- Seq Scan   → missing index or stale stats
-- Index Scan → optimizer found it, you're probably fine
-- big gap between estimated rows and actual rows → run ANALYZE
</code></pre>
<p>Wrap related writes in transactions. Both updates or neither - not whichever one made it before the server decided to restart.</p>
<p>Stop reaching for more hardware when a query is slow. Hardware helps a working system carry more load. It does almost nothing for a query running the wrong plan. A missing index is still a missing index on a faster machine - you just pay more per slow request.</p>
<p>Most performance problems I've seen in databases weren't hardware problems. They were a missing index, estimates the optimizer was making from statistics that no longer reflected the data, or a transaction boundary someone forgot to draw. All three are findable once you understand what actually happens after you hit enter. That's the whole reason to know this. Not the theory for its own sake - the ability to sit down with a slow system and have a real idea of where to look.</p>
]]></content:encoded></item><item><title><![CDATA[Intro to Cloud Formation - Infra as Code ]]></title><description><![CDATA[CloudFormation is an Infrastructure as Code (IaC) service where we define the resources we need to deploy in AWS in a coding manner. Generally, CloudFormation uses JSON or YAML for declaring resources]]></description><link>https://abhisekh.in/intro-to-cloud-formation-infra-as-code</link><guid isPermaLink="true">https://abhisekh.in/intro-to-cloud-formation-infra-as-code</guid><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Tue, 24 Feb 2026 17:36:32 GMT</pubDate><content:encoded><![CDATA[<p><strong>CloudFormation</strong> is an Infrastructure as Code (IaC) service where we define the resources we need to deploy in AWS in a coding manner. Generally, CloudFormation uses <strong>JSON or YAML</strong> for declaring resources. This file is treated as a template, which is then uploaded to the CloudFormation "Stack" section for creation.</p>
<p>CloudFormation is a <strong>declarative language</strong>, so you don't have to worry about the sequence in which you list your resources—AWS automatically figures out the correct order for deployment.</p>
<h4><strong>How Stacks Work</strong></h4>
<p>When you create a stack, each resource is tagged with a unique identifier for better visibility. By default, deleting a stack results in the termination of all resources created by it. You can avoid this by using the <strong>Deletion Policy</strong> flag (setting it to <code>Retain</code>), which prevents specific resources from being deleted.</p>
<blockquote>
<p><strong>Note:</strong> If an S3 bucket is part of your stack and it isn't empty, the deletion will fail even if your policy allows it. AWS requires buckets to be empty before they can be removed - can be done using AWS Lambda.</p>
</blockquote>
<h4><strong>Pros of Using CloudFormation</strong></h4>
<ul>
<li><p><strong>More control:</strong> Everything is configured from a YAML file, and AWS provides comprehensive documentation to guide you.</p>
</li>
<li><p><strong>Ease of deployment:</strong> You can reuse the same template with small tweaks or use <strong>Parameters</strong> to make the infrastructure dynamic based on user input.</p>
</li>
<li><p><strong>Infrastructure Composer:</strong> An additional benefit is viewing your architecture visually to see how services are interlinked—something not easily available when creating services manually.</p>
</li>
</ul>
<h4><strong>Why use this instead of the GUI?</strong></h4>
<p>The main reason is automation across environments. Once your template is ready, you can deploy multiple linked services for different stages. For example, a <strong>Dev</strong> instance might only require 2 EC2 units, whereas <strong>PROD</strong> might require 4 to handle a much larger load. You can manage this difference easily within the code rather than clicking through the console every time.</p>
<h4><strong>Core Components</strong></h4>
<ul>
<li><p><strong>Template Sections:</strong> Beyond just resources, templates use "Parameters" for input and "Helper Functions" (like <code>Ref</code>) to link items together.</p>
</li>
<li><p><strong>Logical Sequencing:</strong> AWS configures which step to run first and last by looking at dependencies, meaning your declaration order doesn't limit the deployment logic.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Git & GitHub in 5 Minutes: Stop Emailing Code! 🚀]]></title><description><![CDATA[Ever had files named final_code.js, final_code_v2.js, or final_code_REALLY_final.js? 😵 We've all been there. It's a messy way to track changes and a nightmare for teamwork.
Let's fix this forever with two tools: Git and GitHub.

Part 1: Git - Your P...]]></description><link>https://abhisekh.in/git-and-github-in-5-minutes-stop-emailing-code</link><guid isPermaLink="true">https://abhisekh.in/git-and-github-in-5-minutes-stop-emailing-code</guid><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Fri, 18 Jul 2025 22:55:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/wX2L8L-fGeA/upload/49eb686dd4fb878f8844fbc67eb752bb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever had files named <code>final_code.js</code>, <code>final_code_v2.js</code>, or <code>final_code_REALLY_final.js</code>? 😵 We've all been there. It's a messy way to track changes and a nightmare for teamwork.</p>
<p>Let's fix this forever with two tools: <strong>Git</strong> and <strong>GitHub</strong>.</p>
<hr />
<h2 id="heading-part-1-git-your-personal-time-machine">Part 1: Git - Your Personal Time Machine ⏳</h2>
<p>Imagine Git as a "save game" system for your code. It runs on your local machine and keeps a complete history of every change you make. You can mess things up, experiment freely, and always revert to a previous working version.</p>
<h3 id="heading-the-3-core-commands">The 3 Core Commands</h3>
<p>Let's say you've started a new project.</p>
<ol>
<li><p><strong>Initialize Git:</strong> Go to your project folder in the terminal and run:</p>
<pre><code class="lang-bash"> <span class="hljs-comment"># This creates a hidden .git folder to track everything</span>
 git init
</code></pre>
</li>
<li><p><strong>Add Files:</strong> You've created a file, say <code>index.html</code>. Now, tell Git you want to track it.</p>
<pre><code class="lang-bash"> <span class="hljs-comment"># The '.' means "add all files in this folder"</span>
 git add .
</code></pre>
</li>
<li><p><strong>Commit Changes:</strong> This is your "save point." You lock in the changes with a descriptive message.</p>
<pre><code class="lang-bash"> git commit -m <span class="hljs-string">"Create initial index.html file"</span>
</code></pre>
</li>
</ol>
<p>That's it! You've made your first commit. You now have a snapshot of your project you can return to at any time.</p>
<hr />
<h2 id="heading-part-2-github-your-codes-cloud-home">Part 2: GitHub - Your Code's Cloud Home ☁️</h2>
<p>If Git is the tool, <strong>GitHub</strong> is the place where you store your projects online. It's your cloud backup, your portfolio, and your collaboration hub. It lets you share your Git "save points" with the world or your team.</p>
<h3 id="heading-the-magic-workflow">The Magic Workflow ✨</h3>
<p>Here’s how Git and GitHub work together.</p>
<ol>
<li><p><strong>Create a Repo on GitHub:</strong> First, create a new, empty "repository" (repo) on <a target="_blank" href="http://GitHub.com">GitHub.com</a>.</p>
</li>
<li><p><strong>Link and Push:</strong> On your local machine, link your project to the GitHub repo and "push" your commits to it. GitHub will provide you with the exact commands to copy and paste, which usually look like this:</p>
<pre><code class="lang-bash"> <span class="hljs-comment"># Links your local project to the GitHub URL (you only do this once)</span>
 git remote add origin [YOUR_GITHUB_REPO_URL]

 <span class="hljs-comment"># Sends your committed changes to GitHub</span>
 git push -u origin main
</code></pre>
</li>
</ol>
<p>Now, anyone can see your code online! When you make more changes, the process is just two steps:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># 1. Save your changes locally</span>
git commit -m <span class="hljs-string">"Add new feature"</span>

<span class="hljs-comment"># 2. Push them to GitHub</span>
git push
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Prompt Caching - Simple Explanation]]></title><description><![CDATA[I have come across Prompt Caching Technique when learning about RAG Architecture.
Overview:
Prompt Caching is technique where the System stores the repetitive sentences/words from our Prompts to save time and Cost.

Mainly the prompts contain mostly ...]]></description><link>https://abhisekh.in/prompt-caching-simple-explanation</link><guid isPermaLink="true">https://abhisekh.in/prompt-caching-simple-explanation</guid><category><![CDATA[#PromptEngineering]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Mon, 05 May 2025 11:06:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/xbEVM6oJ1Fs/upload/bc84a66740184dd04d203656febba61e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have come across <strong>Prompt Caching</strong> Technique when learning about RAG Architecture.</p>
<p><strong>Overview:</strong></p>
<p>Prompt Caching is technique where the System stores the repetitive sentences/words from our Prompts to save time and Cost.</p>
<ol>
<li><p>Mainly the prompts contain mostly the same words - so prompt caching stores the repetitive parts of the Prompt.</p>
</li>
<li><p>When we send the same prompt again - <strong>System recognizes</strong> the repetitive words and instead of reprocessing them - it uses the stored version.</p>
</li>
</ol>
<p><strong>Benefits of Prompt Caching:</strong></p>
<ol>
<li><p>Faster API Response as the LLM doesn’t have to process all words.</p>
</li>
<li><p>Lower Cost (Since the LLM requires less processing power because the repetitive words are not processed again)</p>
</li>
</ol>
<p>It's like giving the model a "<strong>memory</strong>" of previous computations, allowing it to quickly retrieve and use that information.</p>
<p>I was curious about “<strong>system recognizes</strong> “part that how the LLM able to recognize these repetitive words without processing it. Below are the few methods which followed by LLM for Prompt Caching</p>
<ul>
<li><p><strong>Exact Prefix Matching:</strong></p>
<ul>
<li><p><strong>How it works:</strong> The system looks at the <em>beginning</em> (the prefix) of the incoming prompt. It compares this prefix, token by token, with prefixes it has already processed and stored in its cache from recent requests.</p>
</li>
<li><p><strong>Recognition:</strong> If the <em>entire</em> sequence of tokens at the beginning of the new prompt exactly matches a sequence stored in the cache, it's a "cache hit." The system recognizes that this part doesn't need reprocessing.</p>
</li>
<li><p>This is used by providers like OpenAI and Anthropic.</p>
</li>
<li><p><strong>Example:</strong></p>
<ul>
<li><p><strong>Cached Prompt Prefix:</strong> "System: You are a helpful assistant. User: Analyze this document: [long document text]"</p>
</li>
<li><p><strong>New Prompt:</strong> "System: You are a helpful assistant. User: Analyze this document: [long document text] User: Now summarize the key points."</p>
</li>
<li><p><strong>Recognition:</strong> The system sees that the beginning of the new prompt is identical to the cached prefix up to the end of the document text. It recognizes this match.</p>
</li>
</ul>
</li>
<li><p><strong>Why it works:</strong> This method is simple and efficient. It guarantees that the reused part is identical, ensuring the model's state is consistent. However, even a tiny change (like a single different character or extra space) in the prefix will break the match ("cache miss").</p>
</li>
</ul>
</li>
<li><p><strong>Cryptographic Hashing (Often used internally for cache keys):</strong></p>
<ul>
<li><p><strong>How it works:</strong> While not the primary recognition method for the <em>content</em> itself during comparison, hashing is often used to create unique identifiers (cache keys) for the stored prefixes. The system calculates a unique digital fingerprint (a hash) for the sequence of tokens in the cacheable prefix.</p>
</li>
<li><p><strong>Recognition:</strong> When a new request comes in, the system calculates the hash for its prefix. It then quickly checks if a cache entry with that <em>exact same hash</em> exists. If it does, it means the content is identical.</p>
</li>
<li><p><strong>Benefit:</strong> Hashing is very fast for looking up whether an <em>exact</em> match exists in a large cache. It also helps ensure data privacy, as the system deals with hashes rather than the raw text directly for lookup.</p>
</li>
</ul>
</li>
<li><p><strong>Semantic Similarity (Less common for direct prefix caching, more for related concepts):</strong></p>
<ul>
<li><p><strong>How it works:</strong> This is more advanced and less commonly used for the strict "prefix caching" we've discussed, but related concepts exist (like GPTCache mentioned in one of the articles). Instead of looking for an exact match, the system might use techniques like vector embeddings to determine if a new prompt is <em>semantically similar</em> (i.e., has a similar meaning) to a cached one.</p>
</li>
<li><p><strong>Recognition:</strong> If the meaning is close enough (above a certain threshold), it might retrieve a related cached response or state.</p>
</li>
<li><p><strong>Caveat:</strong> This is generally <em>not</em> how standard prompt prefix caching works in major APIs like OpenAI or Anthropic for cost/latency reduction, as they rely on <em>exact</em> matches to guarantee identical processing states. Semantic matching is more complex and might be used in different types of caching systems.</p>
</li>
</ul>
</li>
</ul>
<p><strong>Prompt Caching in Different Platforms:</strong></p>
<ul>
<li><p><strong>OpenAI:</strong> Automatically enabled for prompts longer than 1024 tokens. Static content should be at the beginning of the prompt for optimal caching. <a target="_blank" href="https://platform.openai.com/docs/guides/prompt-caching">Prompt caching - OpenAI API</a></p>
</li>
<li><p><strong>Anthropic:</strong> Allows you to cache specific parts of prompts using the <code>cache_control</code> parameter. They emphasize placing static content at the beginning of the prompt. <a target="_blank" href="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching">Prompt caching - Anthropic API</a></p>
</li>
<li><p><strong>Amazon Bedrock:</strong> Implements caching with "cache checkpoints" to mark the beginning of the cacheable section. <a target="_blank" href="https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html">Prompt caching for faster model inference - Amazon Bedrock</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Understanding Dynamic Variable Allocation in Python]]></title><description><![CDATA[I was always curious about how Python assigns values under the hood to the same variable.
Example
Let's say we declare:
a = 2
print(type(a))  # This will give INT as a response

a = 2
a = "Hello World"
print(type(a))  # This will give String as a res...]]></description><link>https://abhisekh.in/understanding-dynamic-variable-allocation-in-python</link><guid isPermaLink="true">https://abhisekh.in/understanding-dynamic-variable-allocation-in-python</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Tue, 25 Mar 2025 10:56:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/vb-3qEe3rg8/upload/3b3d1fe6395679ccff317c474ed5298f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was always curious about how Python assigns values under the hood to the same variable.</p>
<h2 id="heading-example"><strong>Example</strong></h2>
<p>Let's say we declare:</p>
<pre><code class="lang-python">a = <span class="hljs-number">2</span>
print(type(a))  <span class="hljs-comment"># This will give INT as a response</span>
</code></pre>
<pre><code class="lang-python">a = <span class="hljs-number">2</span>
a = <span class="hljs-string">"Hello World"</span>
print(type(a))  <span class="hljs-comment"># This will give String as a response</span>
</code></pre>
<p>This is where the interest pops up that <code>a</code> was initially an <code>INT</code> but suddenly converted to a <code>String</code>.</p>
<h2 id="heading-how-it-works"><strong>How it works</strong></h2>
<p>It uses objects when assigning values to variables and it does it at runtime.</p>
<ul>
<li><p>When we say <code>a = 2</code>:</p>
<ul>
<li><p>At runtime, it creates an object of <code>INT</code> and assigns the value of <code>2</code> to that object.</p>
</li>
<li><p>It increments the reference count by 1.</p>
</li>
<li><p>It assigns the reference of that object to the <code>a</code> variable.</p>
</li>
</ul>
</li>
<li><p>When we reassign <code>"Hello World"</code> (a string value) to <code>a</code>:</p>
<ul>
<li><p>In the background, it creates another object of <code>String</code> with the value <code>"Hello World"</code> assigned to it.</p>
</li>
<li><p>It increments the reference of the new object's count by 1.</p>
</li>
<li><p>The reference of this newly created object is assigned to the <code>a</code> variable.</p>
</li>
<li><p>The reference count for the <code>INT</code> object decreases by 1.</p>
</li>
</ul>
</li>
</ul>
<p>When the reference count of an object hits 0, it becomes eligible for garbage collection. At runtime, the Python garbage collector collects the <code>INT</code> object as it doesn't have any references and the reference count is set to 0.</p>
]]></content:encoded></item><item><title><![CDATA[Return Game: Traditional vs. High-Order Array Functions!]]></title><description><![CDATA[Hey there, curious folks!
Ever wondered how traditional loops differ from those cool higher-order array functions in JavaScript? Allow me to share a surprising revelation I stumbled upon while diving into arrays.
I used to think that traditional for ...]]></description><link>https://abhisekh.in/return-game-traditional-vs-high-order-array-functions</link><guid isPermaLink="true">https://abhisekh.in/return-game-traditional-vs-high-order-array-functions</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[array methods]]></category><category><![CDATA[Loops]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Thu, 30 Nov 2023 04:30:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FGXqbqbGt5o/upload/8f3577c0a7276a30ec38bfb6af8d2c4b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey there, curious folks!</p>
<p>Ever wondered how traditional loops differ from those cool higher-order array functions in JavaScript? Allow me to share a surprising revelation I stumbled upon while diving into arrays.</p>
<p>I used to think that traditional <code>for</code> loops and higher-order array functions like <code>forEach</code> were just two sides of the same coin—different syntax, same functionality. But here's the twist: their handling of the <code>return</code> statement sets them apart.</p>
<p>In the realm of <code>forEach</code>, the <code>return</code> statement exits only the callback function passed to it, not the entire surrounding function. It's like a 'skip' button for that specific iteration.</p>
<pre><code class="lang-javascript">javascriptCopy codeconst numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];

numbers.forEach(<span class="hljs-function">(<span class="hljs-params">number</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (number === <span class="hljs-number">3</span>) {
    <span class="hljs-keyword">return</span>; <span class="hljs-comment">// Skips iteration when number equals 3</span>
  }
  <span class="hljs-built_in">console</span>.log(number);
});

<span class="hljs-comment">// Output: 1, 2, 4, 5</span>
</code></pre>
<p>On the flip side, a <code>return</code> statement in a traditional <code>for</code> loop exits the entire enclosing function. This is because in a <code>for</code> loop, <code>return</code> directly affects the function scope, unlike in a <code>forEach</code> loop.</p>
<p>But wait, if you're thinking of using <code>return</code> to stop a <code>forEach</code> loop altogether, hold that thought! You'll need to explore methods like <code>Array.prototype.some()</code> or <code>Array.prototype.every()</code> to achieve similar functionality. These methods gracefully halt iteration when certain conditions are met.</p>
<p>Understanding these nuances can be a game-changer, especially when fine-tuning your code for specific behaviors or conditions. Have you encountered similar surprises while working with JavaScript arrays? Do Share your thoughts!</p>
<p>Further Reading if One Interested:</p>
<ol>
<li><p>MDN Web Docs - Array.prototype.forEach(): <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">Link</a></p>
</li>
<li><p>MDN Web Docs - Array.prototype.some(): <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some">Link</a></p>
</li>
<li><p>MDN Web Docs - Array.prototype.every(): <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every">Link</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">JavaScript.info</a> - Array Methods: <a target="_blank" href="https://javascript.info/array-methods">Link</a></p>
</li>
<li><p>Medium Article - Understanding JavaScript’s forEach(): <a target="_blank" href="https://medium.com/@gaganvohra010/understanding-javascripts-foreach-3edba3a4d70d">Link</a>.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Simplifying Databases: The Power of Data Abstraction and Essential Abstractions]]></title><description><![CDATA[Database systems use abstraction to simplify database design and improve efficiency in terms of data retrieval and user usability. There are three levels of data abstraction: physical, logical, and view.

Physical Level: This is the lowest level of d...]]></description><link>https://abhisekh.in/databases-data-abstraction</link><guid isPermaLink="true">https://abhisekh.in/databases-data-abstraction</guid><category><![CDATA[Databases]]></category><category><![CDATA[engineering]]></category><category><![CDATA[System Architecture]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Sun, 11 Jun 2023 09:29:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686475339477/a7d5d282-1c48-4323-bbaf-0bcda5101f47.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Database systems use abstraction to simplify database design and improve efficiency in terms of data retrieval and user usability. There are three levels of data abstraction: physical, logical, and view.</p>
<ol>
<li><p>Physical Level: This is the lowest level of data abstraction and deals with how data is stored in memory. It involves access methods (sequential or random) and file organization methods (e.g., B+ trees or hashing). Details such as storage blocks and memory usage are hidden from the user. For example, when storing employee details, the specifics of storage and memory are kept hidden.</p>
</li>
<li><p>Logical Level(Conceptual): This level represents the actual data stored in the database in the form of tables and defines the relationships between data entities. It provides a relatively simple structure for storing information. The information available at the view level is unknown at this level. Attributes of an employee and relationships (e.g., with the manager) can be stored at the logical level.</p>
</li>
<li><p>View Level: This is the highest level of abstraction, which allows users to interact with the database by viewing a specific part of it. Users can access data in the form of rows and columns using tables and relations. Multiple views of the same database may exist. The view level exists to make the database easily accessible to individual users, hiding storage and implementation details.</p>
</li>
</ol>
<p>The main purpose of data abstraction is to achieve data independence, which saves time and costs when modifying or altering the database. Data independence allows changes to be made at one level of the system without affecting the schema at the next level. There are two types of data independence:</p>
<ol>
<li><p>Physical Level Data Independence: This refers to the ability to modify the physical schema without affecting the conceptual or logical schema. It allows optimization changes, such as using new storage devices, modifying data structures, altering indexes, or changing file organization techniques.</p>
</li>
<li><p>Logical Level Data Independence: This refers to the ability to modify the logical schema without affecting the external schema or application programs. Changes can include inserting or deleting attributes, altering table structures, or modifying entities and relationships in the logical schema.</p>
</li>
</ol>
<p>By providing data independence, database systems allow for flexibility and easier maintenance as different levels of the system can be modified independently.</p>
]]></content:encoded></item><item><title><![CDATA[Consistent Hashing: How to Distribute Data Evenly Across Multiple Servers]]></title><description><![CDATA[In a distributed computing environment, it is common to have multiple servers handling requests from clients. However, distributing the load evenly across these servers can be a challenge. Traditional hashing techniques can lead to uneven distributio...]]></description><link>https://abhisekh.in/consistent-hashing-how-to-distribute-data-evenly-across-multiple-servers</link><guid isPermaLink="true">https://abhisekh.in/consistent-hashing-how-to-distribute-data-evenly-across-multiple-servers</guid><category><![CDATA[System Design]]></category><category><![CDATA[Design]]></category><category><![CDATA[engineering]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Sat, 25 Mar 2023 18:59:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679770893010/a57073e0-4131-403b-aaa9-470c2a6a1d94.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In a distributed computing environment, it is common to have multiple servers handling requests from clients. However, distributing the load evenly across these servers can be a challenge. Traditional hashing techniques can lead to uneven distribution of the load, resulting in some servers being overloaded while others remain underutilized. This is where <strong>consistent hashing</strong> comes in.</p>
<h3 id="heading-what-is-consistent-hashing">What is Consistent Hashing?</h3>
<p><strong>Consistent hashing</strong> is a technique used to distribute data evenly across multiple servers in a cluster. It is an algorithm that maps each data item to a point on a ring or a circle, and the servers are also mapped to points on the same ring. Each server is responsible for storing and serving the data that falls within the range between it and its neighbouring server on the ring.</p>
<p>Here's how it works:</p>
<ol>
<li><p>Imagine a circle or a ring. Each point on the circle represents a server.</p>
</li>
<li><p>You use a hash function to map each server's IP address (or some other identifier) to a point on the circle.</p>
</li>
<li><p>You also use the same hash function to map each piece of data to a point on the circle.</p>
</li>
<li><p>Each piece of data is then assigned to the server that is closest to it on the circle (either clockwise or counterclockwise).</p>
</li>
<li><p>Now, let's say you want to add a new server. You just need to map its IP address to a point on the circle, and then move some of the data that was assigned to its neighbouring servers over to the new server. This way, the load is distributed evenly across all the servers.</p>
</li>
<li><p>If a server goes down, you just need to move its data to the server that is closest to it on the circle. Again, this ensures that the load is distributed evenly.</p>
</li>
</ol>
<p>For more visual explanation: <a target="_blank" href="https://youtu.be/oKAU6LaYFhw">https://youtu.be/oKAU6LaYFhw</a></p>
<h3 id="heading-consistent-hashing-benefits">Consistent Hashing Benefits</h3>
<p>Consistent hashing offers several benefits in distributed systems, including:</p>
<ol>
<li><p>Scalability: Consistent hashing allows for easy scaling of a system. When a new server is added to the cluster, only a fraction of the data needs to be moved around to balance the load. This makes it easy to add and remove servers without disrupting the entire system.</p>
</li>
<li><p>Load Balancing: Consistent hashing evenly distributes data across multiple servers, ensuring that each server gets an equal share of the load. This helps to prevent the overloading of any single server and ensures that the system can handle a large number of requests without slowing down.</p>
</li>
<li><p>Fault Tolerance: Consistent hashing is fault-tolerant. If a server fails, the data it was responsible for can be easily moved to a neighbouring server without affecting the rest of the system. This ensures that the system remains available even when individual servers fail.</p>
</li>
<li><p>Caching: Consistent hashing can be used to cache data efficiently. The data can be cached on the server that is responsible for it, ensuring that the cache is always up to date.</p>
</li>
</ol>
<h3 id="heading-use-cases-of-consistent-hashing">Use Cases of Consistent Hashing</h3>
<p>Consistent hashing is used in a variety of distributed systems, including:</p>
<ol>
<li><p>Distributed Databases: Consistent hashing is widely used in distributed databases. It allows for easy scaling of the database, load balancing, and fault tolerance.</p>
</li>
<li><p>Content Delivery Networks (CDNs): CDNs use consistent hashing to distribute content across multiple servers around the world. This ensures that the content is delivered quickly and efficiently to users.</p>
</li>
<li><p>Distributed Caching: Consistent hashing is used to distribute cached data across multiple servers. This ensures that the cache is always up to date and that the load is evenly distributed across the servers.</p>
</li>
<li><p>Load Balancers: Load balancers use consistent hashing to distribute requests across multiple servers. This ensures that each server gets an equal share of the load and prevents the overloading of any single server.</p>
</li>
<li><p>Peer-to-Peer Networks: Consistent hashing is used in peer-to-peer networks to distribute data across multiple nodes. This ensures that each node gets an equal share of the data and that the load is evenly distributed across the network.</p>
</li>
</ol>
<h3 id="heading-pitfalls-of-consistent-hashing">Pitfalls of Consistent Hashing</h3>
<p>Although consistent hashing is designed to evenly distribute the load across multiple servers, it can still lead to some issues in certain scenarios. Here are a couple of pitfalls to be aware of:</p>
<ol>
<li><p>Load Imbalance: Although consistent hashing is designed to evenly distribute the load across multiple servers, it can still lead to load imbalance in certain scenarios. This can happen when there are too few servers in the cluster or when the hash function is not uniform.</p>
</li>
<li><p>Hotspotting: Hotspotting is a phenomenon that occurs when a particular data item is accessed frequently, causing a disproportionate amount of traffic to a single server. Consistent hashing can exacerbate this problem by directing all traffic for a particular data item to a single server.</p>
<p> To avoid these pitfalls, it is important to carefully design a consistent hashing algorithm and tune it for the specific use case.</p>
</li>
</ol>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>Consistent hashing is a powerful technique for distributing data evenly across multiple servers in a distributed computing environment. It offers several benefits, including scalability, load balancing, fault tolerance, and caching. Consistent hashing is widely used in distributed databases, CDNs, distributed caching, load balancers, and peer-to-peer networks. However, it can still lead to load imbalance and hot-spotting in certain scenarios, so it is important to carefully design a consistent hashing algorithm and tune it for the specific use case.</p>
]]></content:encoded></item><item><title><![CDATA[ES6 Concepts]]></title><description><![CDATA[This article will be explaining some ES6-specific features which you can actually use or using in your day-to-day life.
Let & Const
As Js already has some reputation for being complicated language so I will try to explain the different types of keywo...]]></description><link>https://abhisekh.in/es6-concepts</link><guid isPermaLink="true">https://abhisekh.in/es6-concepts</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Rest operator]]></category><category><![CDATA[variables]]></category><category><![CDATA[ES6]]></category><category><![CDATA[#arrowfunction]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Sun, 22 Jan 2023 18:51:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/i25aqE_YUZs/upload/5de8178169b4ab8022e26eb3ee432866.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article will be explaining some ES6-specific features which you can actually use or using in your day-to-day life.</p>
<h2 id="heading-let-amp-const">Let &amp; Const</h2>
<p>As Js already has some reputation for being complicated language so I will try to explain the different types of keywords we used for variable declaration first &amp; why use one over another.</p>
<p>So in ES6, <a target="_blank" href="https://github.com/lukehoban/es6features">ECMAScript</a> Introduces Let &amp; Const keywords for defining variables.</p>
<p>First, we have to understand the different types of scoping in JS. We have three variations here</p>
<ul>
<li><p><strong>Block Scope:</strong> This scope restricts the variable that is declared inside a specific block,(if else, switch, loops) from access by the outside of the block.</p>
</li>
<li><p><strong>Functional Scope:</strong> When a variable is declared inside a function, it is only accessible within that function and cannot be used outside that function.</p>
</li>
<li><p><strong>Global Scope:</strong> As the name suggests, all variables declared in this scope can be accessed globally without restriction.</p>
</li>
</ul>
<blockquote>
<p>Declaring variables with 'Let' &amp; 'const' keywords, facilitates the variables to be block scoped.</p>
<p>Variables declared with the var keyword, do not have block scope.(Global)</p>
</blockquote>
<p>If you declare a variable using let/const within block means an if-else statement or switch statement or loops, then that variable becomes blocked scoped. But if you declare the same variable within a function that makes it function-scoped.</p>
<p>Then comes <strong>Const</strong>, as the name suggests this keyword we use to make variable constant so we or the program itself doesn't change the value of that variable accidentally. Const is also a blocked scope variable as mentioned before.</p>
<h3 id="heading-const-is-also-mutable">Const is also mutable</h3>
<p>But declaring variables with const, we have one caveat i.e const is mutable. So if you are declaring an array or object using const we will be able to modify the content within. But how's that even possible when const only works to prevent mutation? Actually, const does prevent modification by <strong>creating a read-only reference to a value</strong>. It does not mean the value it holds is immutable—just that <strong>the variable identifier cannot be reassigned</strong> means you can't reinitialize the whole array/obj.</p>
<h2 id="heading-arrow-functions">Arrow Functions</h2>
<p>ES6 introduced a new way of declaring functions. First, we will see what a normal function looks like &amp; then we will convert it to an arrow function so you can do it too.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//normal function </span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">traditionalFunction</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello Developer, <span class="hljs-subst">${name}</span> !!!`</span>);
}
traditionalFunction(<span class="hljs-string">'Abhisekh'</span>);
</code></pre>
<p><strong>Arrow Function :</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arrowFunction = <span class="hljs-function">(<span class="hljs-params">name</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello Developer, <span class="hljs-subst">${name}</span> !!!`</span>);
};
arrowFunction(<span class="hljs-string">'Abhisekh'</span>);
</code></pre>
<p>Arrow some new differences with normal functions which you may like</p>
<ul>
<li><p>if you are taking one argument in your function then you don't need to include (). (It makes the code looks nice IMO). You only need to add parenthesis when you are working with more than one argument.</p>
</li>
<li><p>if your function doing one-liner work &amp; returning the value, then you don't need to return as well curly braces({}).</p>
</li>
<li><p>The biggest functional differences are that arrow functions do not have their own <strong>this</strong> binding or prototype and cannot be used as a constructor.</p>
</li>
<li><p>Arrow functions don't have a constructor or prototype.</p>
</li>
</ul>
<p>Example :</p>
<ul>
<li><p>without parenthesis &amp; return</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> arrowFunction = <span class="hljs-function"><span class="hljs-params">name</span> =&gt;</span> <span class="hljs-string">`Hello Developer, <span class="hljs-subst">${name}</span> !!!`</span>;

  <span class="hljs-built_in">console</span>.log(arrowFunction(<span class="hljs-string">'Abhisekh'</span>));
</code></pre>
</li>
</ul>
<ul>
<li><p>ArrowFunction doesn't have a prototype &amp; Constructor</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> myArrowFunction = <span class="hljs-function">() =&gt;</span> {}

  <span class="hljs-comment">// Attempt to log the prototype property of myArrowFunction</span>
  <span class="hljs-built_in">console</span>.log(myArrowFunction.prototype) <span class="hljs-comment">//this will give undefined</span>

  <span class="hljs-keyword">const</span> arrowInstance = <span class="hljs-keyword">new</span> myArrowFunction()

  <span class="hljs-built_in">console</span>.log(arrowInstance) <span class="hljs-comment">// this throw typeError saying it is not a constructer but it will not happen with function as they supports constructer &amp; prototype.</span>
</code></pre>
<h2 id="heading-rest-operator">Rest Operator</h2>
</li>
<li><p>The JavaScript spread operator (<code>...</code>) allows us to put the rest of some specific user-supplied values into a JavaScript array.</p>
</li>
<li><p>A function definition can only have one rest parameter, and the rest parameter must be the last parameter in the function definition.</p>
</li>
<li><p>The console would display the strings <code>You have passed 3 arguments.</code> and <code>You have passed 4 arguments.</code>.</p>
</li>
<li><p>The rest parameter eliminates the need to check the <code>args</code> array and allows us to apply <code>map()</code>, <code>filter()</code> and <code>reduce()</code> on the parameters array.</p>
<p>  Note: <strong>Beware!</strong> You Cannot Use <code>“use strict”</code> Inside a Function Containing a Rest Parameter</p>
<pre><code class="lang-js">  <span class="hljs-keyword">const</span> spreadFuntion = <span class="hljs-function">(<span class="hljs-params">...args</span>) =&gt;</span><span class="hljs-string">'You have passed '</span> + args.length + <span class="hljs-string">' arguments.'</span>;

  <span class="hljs-built_in">console</span>.log(spreadFuntion(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>));
  <span class="hljs-built_in">console</span>.log(spreadFuntion(<span class="hljs-string">'string'</span>, <span class="hljs-literal">null</span>, [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], {}));
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>  So these are the few new features that ES6 introduced. There is a lot to cover. But I try to outline some of the most important ones which I usually find myself using.</p>
<p>  <strong>Thank you for reading.</strong></p>
<h4 id="heading-if-you-want-to-explore-here-are-some-links">If you want to explore here are some links.</h4>
</li>
<li><p><a target="_blank" href="https://github.com/lukehoban/es6features">GitHub - ECMAScript 6</a></p>
</li>
<li><p><a target="_blank" href="http://es6-features.org/#Constants">ECMAScript 6: New Features: Overview and Comparison (</a><a target="_blank" href="http://es6-features.org">es6-features.org</a><a target="_blank" href="http://es6-features.org/#Constants">)</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[What is Scaling ? Which one is best : vertical Scaling or Horizontal Scaling ?]]></title><description><![CDATA[Intro :
The scalability of an application can be measured by the number of requests it can effectively handle in a given time frame.
When your website grows in popularity and getting more incoming traffic than normal, to support simultaneous amount o...]]></description><link>https://abhisekh.in/what-is-scaling-which-one-is-best-vertical-scaling-or-horizontal-scaling</link><guid isPermaLink="true">https://abhisekh.in/what-is-scaling-which-one-is-best-vertical-scaling-or-horizontal-scaling</guid><category><![CDATA[engineering]]></category><category><![CDATA[System Architecture]]></category><category><![CDATA[System Design]]></category><category><![CDATA[Design]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Mon, 12 Sep 2022 05:37:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662960957886/ruIaeOG_h.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Intro</strong> :</p>
<p>The <strong>scalability</strong> of an application can be measured by the <strong>number of requests it can effectively handle in a given time frame</strong>.</p>
<p>When your website grows in popularity and getting more incoming traffic than normal, to support simultaneous amount of request which are expected(and unexpected), we need more  resources(CPU, RAM, GPU power) to handle those request.</p>
<ol>
<li><p><strong>Vertical Scaling</strong> :</p>
<p>One way of tackling is increasing the resource of an existing machine to such extent so it can handle large amounts of requests easily. This technique of scaling is called <strong>Vertical Scaling.</strong> This kind of scaling is good when you are just getting started because it provides simplicity and low latency. The reason for low latency is <code>all of components of the website resides in one machine</code> which makes the API/DB calls much faster as we don't need to perform network calls. </p>
<p>But as your incoming traffic increases you have to increase the resources as well, but we have certain hardware limits beyond which we can't upgrade our existing machine. Currently we have 24TiB RAM(which I guess is highest at the time of writing) machine provided by amazon. <a target="_blank" href="https://aws.amazon.com/blogs/aws/ec2-high-memory-update-new-18-tb-and-24-tb-instances/">For more info.</a>. But this high resourced compute machines comes at a very high cost.</p>
</li>
<li><p><strong>Horizontal Scaling </strong> :</p>
<p>To resolve the above problems(high cost/hardware limit) instead of putting all the resource into one machine, we are putting multiple machine with normal resources, so that we can handle any amount of request without worrying of hardware limitation. When traffic grows we can simply add more servers(&amp; vice versa) and the website will run smoothly. We can simply achieve this using "autoscaling" feature on <a target="_blank" href="https://aws.amazon.com/autoscaling/">AWS</a>. </p>
<p>But the catch with vertical scaling is, we need to implement <a target="_blank" href="https://abhisekh.in/system-design-fundamentals-part-1">load balancer</a> which can distribute the traffic equally among all the machines and have to make our web servers(machines) stateless to able to provide responses to user from any machine irrespective of what machine it was logged in first. </p>
<p><strong><em>What do I mean by stateless ?</em></strong> </p>
<p>If you have build any web application with some authentication or used cookies for storing particular information about the user for a constant time. Typically when you using a cookies for a particular session(user), these details reside with in that machine only. So let's say if a user performs logging in <em>ServerA</em> but due to huge request load balancer redirects the same user to another <em>ServerB</em> after login succed. But this <em>ServerB</em> doesn't have any knowledge about the session created in ServerA. So then ServerB again asks user to login. If you have 'n' machines then in worst case the user have to login in every machine(n) to use the application which is very bad User experience. </p>
<p>To mitigate the above problem <strong>stateless</strong> approach comes handy. </p>
<p>In this approach when a user logs in or done something, we are keeping track of the whole session in a separate database. (preferably NoSQL for Key-Value and simplicity and low latency). So every time request comes from a particular user, web server first checks the the DB for session details and responds accordingly. </p>
<p>Now after stateless implementation, UserA performs login in ServerA and when login succeeded it stores all the needed details to the database(like <code>userId:{session_details}</code>). Then due to high load, load balancer redirects UserA to ServerX. But this time ServerX goes first to DB and look through the session if it finds user logged in then it will redirects user to home/product page. </p>
<p>So in that way if we implement <strong>Vertical Scaling</strong>, each request will be independent of which machines it is was logged in or performed some actions as we keeping global track of the session via DB. So we can add as many machines we want to.</p>
</li>
</ol>
<p>The best possible solution will be mixture of both Vertical &amp; Horizontal Scaling. We can add multiple machine with medium resources to handle incoming traffic with stateless architecture. </p>
<p>Let me know your thoughts on it. Will love to discuss any further addition/feedback about this post. </p>
<p>Ending with a quote : </p>
<blockquote>
<p>"Design is not just what it looks like and feels like. Design is how it works." - Steve Jobs</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[System Design Fundamentals - Part 1]]></title><description><![CDATA[A journey of thousand miles starts with a single step.

Building a complex system which is scalable, provides fault tolerance with other cool stuff also starts with something very simple. 

Single Server Set Up :  
First we will be starting off with ...]]></description><link>https://abhisekh.in/system-design-fundamentals-part-1</link><guid isPermaLink="true">https://abhisekh.in/system-design-fundamentals-part-1</guid><category><![CDATA[System Design]]></category><category><![CDATA[engineering]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Sun, 11 Sep 2022 13:47:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662903843846/ESOK5Mblj.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>A journey of thousand miles starts with a single step.</p>
</blockquote>
<p>Building a complex system which is scalable, provides fault tolerance with other cool stuff also starts with something very simple. </p>
<ol>
<li><p><strong>Single Server Set Up : </strong> </p>
<p>First we will be starting off with single server means there will be only two component, <strong>One </strong>is Server and <strong>another </strong> is Client that's all. If you are thinking about where will be databases, the database will also reside within the server.</p>
<p>So when client request to the server, server fetches the relevant data from it's internal DB and compute within the server and responds back with a adequate response.  But as you can see, we are having a big problem here with this set up and that is Single Point Of Failure(SPOF). Simply put if your server goes down then your entire website goes down with it and if worse that your server's DB got corrupted then you will lose all the data and many cases it is unrecoverable.</p>
</li>
<li><p><strong>Individual machine for Server &amp; Database : </strong></p>
<p>To mitigate the above scenario, we can separate the Server and Database into different machine(VMs). Then all traffic will be going through Server and whenever it needs some data from DB it can access it over a network call.<strong> By implementing this infrastructure, we can </strong>scale<strong> our Server and Database independently.</strong> So if your website is getting lots of traffic, you can just add more VMs to the server and vice versa.</p>
</li>
<li><p>There are two types scaling : *</p>
<ul>
<li><p><strong> Vertical Scaling </strong>: If we are adding more resource(CPU,RAM,GPU) to one machine only then it's called vertical Scaling. As your loads increase the you will be adding more and more resource to one machine only. But there is hardware limit we need to think of in this scenario as currently one machine can only have limited amount of resource.</p>
</li>
<li><p><strong>Horizontal Scaling </strong>: Instead of adding more resource to one machine, we adding multiple machine with required amount of resource as Server. So as the load increases we will be only adding more machine as a Server.</p>
</li>
</ul>
<p>Ideal Solution for scaling will be hybrid of Vertical &amp; Horizontal scaling where we adding machines with medium resources when the traffic increases.
We will talk about pros and cons of VS &amp; HS in some other article.</p>
</li>
<li><p><strong>Load Balancer : </strong></p>
<p>The need of load balancer increases as we scaling our servers because when the traffic increases we need to ensure that all the traffic aren't going to only one server. In that case due to overload, the server's response time will be increases and eventually crashes.</p>
<p>A load balancer is machine itself whose work is to evenly distributes incoming traffic among all web servers that are defined in the load balancer set.</p>
<p>So, lets see how load balancer works behind the scene.</p>
<p><strong> <em>Normal Flow</em></strong> :</p>
<p>When a client goes to website and hit a domain name(eg. https://abhisekh.in) then the first thing happens is your machine send a DNS request to DNS server asking what is the IP of the "https://abhisekh.in". Once DNS provides the IP(Server IP), then browser sends an HTTP request to that IP and that IP(which is the server itself) react with a valid response. This is how normal website works.  But if we are using load balancer then there will be another level in between of DNS and the actual web server.</p>
<p><strong><em>Load balancer Flow</em></strong> :</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662903203468/iIffj0BrF.png" alt="Load balancer.png" /></p>
<p> Client hits a domain name, DNS request goes to DNS server and DNS server responds with the IP of the load balancer then your browser hits the load balancer then the load balancer sees the request &amp; redirects your request to one of the web server and then web server receives the request &amp; send a response to load balancer and then it forward that response to you.</p>
<p>To keep the security tight, we should place the web server in the private network(local) of the load balancer so only load balancer can access over private IP and not exposed to outer world. Private IPs are IP addresses which are reachable only between machines within same network.</p>
</li>
</ol>
<p>To keep the article short, we will be discussing other fundamentals in upcoming blogs. (eg : How to handle database failures, Cache, CDN etc..)</p>
<p>Additional Study Material : <a target="_blank" href="https://www.nginx.com/resources/glossary/load-balancing/">Load Balancer in Depth</a></p>
]]></content:encoded></item><item><title><![CDATA[What is RPA ? Why use it ?]]></title><description><![CDATA[RPA stands for Robotics Process Automation. We use RPA technology to mimic a human behaviors while interacting with a computer application and automating repetitive and rule-based tasks.
RPA technology can automate back-office tasks, data entry, data...]]></description><link>https://abhisekh.in/what-is-rpa</link><guid isPermaLink="true">https://abhisekh.in/what-is-rpa</guid><category><![CDATA[rpa]]></category><category><![CDATA[automation]]></category><category><![CDATA[blueprism]]></category><category><![CDATA[RPA Basics]]></category><dc:creator><![CDATA[Abhisekh Mukherjee]]></dc:creator><pubDate>Sun, 04 Sep 2022 17:36:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/2EJCSULRwC8/upload/v1662544877094/-LpXW6MXb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>RPA stands for Robotics Process Automation. We use RPA technology to mimic a human behaviors while interacting with a<strong> computer application </strong>and automating repetitive and rule-based tasks.</p>
<p>RPA technology can automate back-office tasks, data entry, data validation, and many other labor-intensive tasks, without having to modify their existing IT architecture, firms can automate their digital processes across numerous applications and systems using <strong>RPA</strong>. </p>
<p>By Implementing RPA across a wide range of businesses and processes, Companies now creating new efficiencies and freeing employees from repetitive monotony and focusing the human workforce more on creative task.</p>
<p>The automated application can be  anything from a web based application to Desktop application(like SAP,JDE) or legacy systems that don't have APIs, virtual desktop infrastructures (VDIs), or database access.</p>
<p>Employees with minimal to no programming expertise can be rapidly trained to use RPA tools. The entire project is based on the RPA chart, which allows a flowchart designer to graphically link, drag, and drop icons to represent process phases.</p>
<p>These automation Softwares works in Top-Down approach and it's follows sequential execution unlike JS(Promise hell :( .</p>
<p><strong>Reasons for using this technology : </strong></p>
<ol>
<li><p>RPA eliminates manual errors, allowing employees to focus on more strategic tasks.</p>
</li>
<li><p>RPA does not necessitate programming knowledge. Employees with any topic expertise can be rapidly trained to use RPA tools.    </p>
</li>
<li><p>RPA robots are less expensive than a full-time human, hence a business can save up to 30% of its total costs by automating repetitive tasks.</p>
</li>
<li><p>If you want to learn RPA technology and be a RPA developer, then Average salary of RPA Dev in India is : 4 Lak to 14 Lakh  per annum which is pretty good.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662543015456/Bue9IiVr2.png" alt="image.png" /></p>
]]></content:encoded></item></channel></rss>