<?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[Mone'm]]></title><description><![CDATA[A passionate backend engineer from Egypt. We can discuss some topics in Database, Backend, AWS and Node.js 
For work: ahmedmoniem922@gmail.com]]></description><link>https://ahmedmonem.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 01 Sep 2026 07:38:32 GMT</lastBuildDate><atom:link href="https://ahmedmonem.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Scaling Your Web Application: A Comprehensive Guide to Scalability.]]></title><description><![CDATA[The Basic Application
The basic web application usually is just an application runs on a single machine, the client sends a request and the server makes some processing and responds to that client as shown in fig(1.0)

The Problem
The problem with th...]]></description><link>https://ahmedmonem.hashnode.dev/scaling-your-web-application-a-comprehensive-guide-to-scalability</link><guid isPermaLink="true">https://ahmedmonem.hashnode.dev/scaling-your-web-application-a-comprehensive-guide-to-scalability</guid><category><![CDATA[scalability]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[AWS]]></category><category><![CDATA[cluster]]></category><category><![CDATA[backend]]></category><category><![CDATA[System Design]]></category><dc:creator><![CDATA[Ahmed Mone'm]]></dc:creator><pubDate>Fri, 08 Dec 2023 19:47:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1702064724148/404e9c37-cb0b-465d-a7eb-2d75ce0f033f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-basic-application">The Basic Application</h2>
<p>The basic web application usually is just an application runs on a single machine, the client sends a request and the server makes some processing and responds to that client as shown in fig(1.0)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702064133624/d76d9e96-1261-4682-824d-9e778cded45a.png" alt="fig(1.0)" /></p>
<h3 id="heading-the-problem">The Problem</h3>
<p>The problem with this architecture is that the server can handle a limited number of requests, and if the number of requests exceeds the server capacity, the server will crash. or the client will wait for a long time to get a response. Also, the server is a single point of failure, if the server crashes, the whole application will be down. and this is why we need to scale our application.</p>
<h2 id="heading-scalability-types">Scalability Types</h2>
<h3 id="heading-vertical-scaling">Vertical Scaling:</h3>
<p>Vertical scaling means that you scale by adding more power (CPU, RAM) to an existing machine to make your application handle more requests.<br />But this is not a good solution because you will reach a limit where you can't add more power to your machine, and also, it's expensive in addition to the downtime that you will have to add more power to your machine. Also, it's not a good solution for high availability because you will have a <strong>single point of failure</strong>.<br />So vertical scaling is not a good solution for scalability if you want to scale applications that handles limited number of requests, and you don't care about high availability like your <strong>personal blog</strong>, then vertical scaling is a good solution for you.</p>
<h3 id="heading-horizontal-scaling">Horizontal Scaling:</h3>
<p>Horizontal scaling means that you scale by adding more machines to your pool of resources, so instead of having a single machine handling all requests, you will have multiple machines handling the requests. This is a good solution because you can add as many machines as you want, and it's a good solution for high availability because you can have multiple machines handling the requests, so if one machine crashes, the other machines will handle the requests.<br />So horizontal scaling is a good solution for scalability if you want to scale applications that handles a large number of requests, and you care about high availability like your <strong>e-commerce website</strong>, then horizontal scaling is a good solution for you.<br />But the problem with horizontal scaling is that it's not easy to implement, you need to make your application distributed, and you need to make sure that all machines are in sync, and you need to make sure that the requests are distributed equally between the machines which adds more complexity to your application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702064134997/07796274-c46d-49a8-8cc3-f42bfa2c9827.webp" alt="Horizontal Scaling" /></p>
<h2 id="heading-load-balancer">Load Balancer</h2>
<p>As we knew, horizontal scaling is all about adding more machines to your pool of resources, but how to distribute the requests between these machines? we need some kind of mechanism to do that, and this mechanism is called <strong>Load Balancer</strong>.<br />Load balancer is a server that distributes the requests between the machines. Load balancers usually have a public IP address, and the client will send the request to the load balancer, and the load balancer will distribute the request between the machines which have private IP addresses.</p>
<h3 id="heading-load-balancing-algorithms">load balancing algorithms.</h3>
<p>Load balancers use different algorithms to distribute the requests between the machines, the most common algorithms are:</p>
<ul>
<li><p><strong>Round Robin</strong>: The load balancer will distribute the requests equally between the machines.</p>
</li>
<li><p><strong>Least Connections</strong>: The load balancer will distribute the requests to the machine that has the least number of connections.</p>
</li>
<li><p><strong>Source</strong>: The load balancer will distribute the requests based on the source IP address of the client, so if the client IP address is. this algorithm usually used for distributing the requests between the machines that are in different geographical locations.</p>
</li>
</ul>
<blockquote>
<p>There are many other algorithms for load balancing, you can check this <a target="_blank" href="https://kemptechnologies.com/load-balancer/load-balancing-algorithms-techniques">link</a> for more information.</p>
</blockquote>
<h3 id="heading-use-a-well-known-load-balancer">Use a Well-Known Load Balancer</h3>
<p>You can build your own load balancer, it's just a reverse proxy server that distributes the requests between the machines, but it's better to use a well-known load balancer like <a target="_blank" href="https://www.nginx.com/">Nginx</a> or <a target="_blank" href="https://www.haproxy.org/">HAProxy</a>.</p>
<p>Here is an example of how to configure Nginx as a load balancer:</p>
<pre><code class="lang-nginx"><span class="hljs-attribute">daemon</span> <span class="hljs-literal">off</span>;                                                
<span class="hljs-attribute">error_log</span> /dev/stderr <span class="hljs-literal">info</span>;                                
<span class="hljs-section">events</span> {                                                   
  <span class="hljs-attribute">worker_connections</span> <span class="hljs-number">2048</span>;
}
<span class="hljs-section">http</span> {                                                     
  <span class="hljs-attribute">access_log</span> /dev/stdout;          <span class="hljs-comment">## this is where the logs will be written</span>
  <span class="hljs-attribute">upstream</span> my-load-balanced-app {  <span class="hljs-comment">## here is the list of machines that will handle the requests</span>
    <span class="hljs-attribute">server</span> <span class="hljs-number">129.48.33.130:8081</span>;
    <span class="hljs-attribute">server</span> <span class="hljs-number">127.0.0.1:8082</span>;

  }
  <span class="hljs-section">server</span> {
    <span class="hljs-attribute">listen</span> <span class="hljs-number">8080</span>;                    <span class="hljs-comment">## this is the port that the load balancer will listen on</span>
    <span class="hljs-attribute">location</span> / {
      <span class="hljs-attribute">proxy_pass</span> http://my-load-balanced-app;   <span class="hljs-comment">## here is the name of the upstream</span>
    }
  }
}
</code></pre>
<h2 id="heading-for-nodejs-developers">For Node.js Developers</h2>
<p>If you are a Node.js developer, you know that Node.js is single threaded which means that it uses only one CPU core, which is a problem because you can't use all the power of your machine.<br />So, at first you need to make horizontal scaling on the single machine to use all CPU cores in your machine, and then you can make horizontal scaling on multiple machines. Node.js provides a built-in module called <a target="_blank" href="https://nodejs.org/api/cluster.html"><strong>cluster</strong></a> that makes it easy to make horizontal scaling on a single machine.</p>
<h3 id="heading-cluster-module">Cluster Module</h3>
<p>The cluster module allows you to create a cluster of processes that all share server ports. and the master process will distribute the requests between the workers processes.</p>
<p>Here is an example of how to use the cluster module:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { NestFactory } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/core'</span>;
<span class="hljs-keyword">import</span> cluster <span class="hljs-keyword">from</span> <span class="hljs-string">'cluster'</span>;
<span class="hljs-keyword">import</span> { cpus } <span class="hljs-keyword">from</span> <span class="hljs-string">'os'</span>;
<span class="hljs-keyword">import</span> { AppModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.module'</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bootstrap</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> app = <span class="hljs-keyword">await</span> NestFactory.create(AppModule);

  <span class="hljs-keyword">await</span> app.listen(process.env.APP_PORT || <span class="hljs-number">3000</span>);
}

<span class="hljs-keyword">if</span> (cluster.isMaster) {
  cluster.schedulingPolicy = cluster.SCHED_RR;      <span class="hljs-comment">//  (1)</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Master <span class="hljs-subst">${process.pid}</span> is running`</span>);
  <span class="hljs-keyword">const</span> cpuCount = cpus().length;                   <span class="hljs-comment">//  (2)</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; cpuCount; i++) {
    cluster.fork();                                 <span class="hljs-comment">//  (3)</span>
  };
} <span class="hljs-keyword">else</span> {                                            <span class="hljs-comment">//  (4)</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Worker <span class="hljs-subst">${process.pid}</span> started`</span>);
  bootstrap();
}
</code></pre>
<p>the code above is an example of a simple <code>Nest.js</code> server that uses <code>Cluster</code> module, this code will create a cluster of processes that all share server ports, and the master process will distribute the requests between the workers processes.<br />Let's explain the code above:</p>
<h4 id="heading-explanation">Explanation</h4>
<p>If we are in the master process, we will create a cluster of processes and set the scheduling policy [The load balancing algorithm] to be <em>RR =&gt; Round Roben</em>, and if we are in the worker process, we will start the server.</p>
<ol>
<li><p><code>cluster.schedulingPolicy = cluster.SCHED_RR;</code>: this line of code is used to set the scheduling policy [Load balancing algorithm] for the cluster, <code>cluster.SCHED_RR</code> is a round robin algorithm. <code>cluster.SCHED_NONE</code> is another policy that make the OS distribute the requests between the workers processes, but this not recommended because the OS usually wants to minimize the number of context switches, so it will not distribute the requests equally between the workers processes. <code>cluster.SCHED_RR</code> is the default policy in all operating systems except Windows. <strong>[Now we are in Node.js v21.4.0]</strong>.</p>
</li>
<li><p><code>const cpuCount = cpus().length;</code>: this line of code is used to get the number of CPU cores in the machine, we will use this number to create the workers processes.</p>
</li>
<li><p><code>cluster.fork();</code>: this line of code is used to create a worker process.</p>
</li>
<li><p><code>else { ... }</code>: this block of code will be executed in the worker process, so the worker process will start the server.</p>
</li>
</ol>
<h2 id="heading-on-the-cloud-aws">On The Cloud [AWS]</h2>
<p>We are talking about scalability, so we need to talk about how you control the number of machines that you have, and how you add more machines to your pool of resources.<br />To be honest, I don't have a lot of experience with cloud services as I'm not a DevOps engineer, but I will try to explain the idea.<br />We want to watch the performance of our machines, and if the performance is not good, we want to add more machines to our pool of resources, and if the performance is good, we want to remove some machines from our pool of resources. I will talk about AWS.</p>
<ul>
<li><p>The compute service in AWS is called <strong>EC2</strong> which stands for <strong>Elastic Compute Cloud</strong> which is a virtual machine.</p>
</li>
<li><p>The service that watches the performance of your machines is called <strong>CloudWatch</strong> which is a monitoring service.</p>
</li>
<li><p>AWS provides a service called <strong>Auto Scaling Group (ASG)</strong> which is a service that watches the performance of your machines, and if the performance is not good, it will add more machines to your pool of resources till you reach the number of machines that you specified, and if the performance is good, it will remove some machines from your pool of resources till you reach the number of machines that you specified.</p>
</li>
<li><p>AWS also have a load balancer service called <strong>ELB</strong> which stands for <strong>Elastic Load Balancer</strong> which is a load balancer service, and it's a good solution for load balancing, you can use it instead of Nginx or HAProxy with your auto scaling group.</p>
<p>  ASG uses <strong>CloudWatch</strong> to watch the performance of your machines, and it uses <strong>EC2</strong> to add or remove machines from your pool of resources, all you need to do is to create an ASG and specify the minimum and maximum number of machines that you want to have, and ASG will do the rest for you.</p>
</li>
</ul>
<h1 id="heading-resources">Resources:</h1>
<ul>
<li><p>system design interview – an insider's guide [Book]</p>
</li>
<li><p>Node.js Design Patterns [Book]</p>
</li>
<li><p>Load Balancing Algorithms and Techniques [Article] <a target="_blank" href="https://kemptechnologies.com/load-balancer/load-balancing-algorithms-techniques">Load Balancing Algorithms, Types and Techniques - Kemp (kemptechnologies.com)</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How PostgreSQL Handles Constraints in Read Committed Isolation Level [Arabic]]]></title><description><![CDATA[‫‫ في ال read committed isolation level معروف ان كل transaction بتاخد snapshot من الداتا وتتعامل معاها وبالتالي اللي كل transaction بتعمله مفيش اي transaction تانية بتشوفه الا لما يحصل commit الطريقة دي اسمها MVCC (Multi version concurrency control)....]]></description><link>https://ahmedmonem.hashnode.dev/how-postgresql-handles-constraints-in-read-committed-isolation-level</link><guid isPermaLink="true">https://ahmedmonem.hashnode.dev/how-postgresql-handles-constraints-in-read-committed-isolation-level</guid><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Databases]]></category><category><![CDATA[SQL]]></category><category><![CDATA[ACID Transactions]]></category><category><![CDATA[backend]]></category><category><![CDATA[indexing]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[concurrency-control]]></category><dc:creator><![CDATA[Ahmed Mone'm]]></dc:creator><pubDate>Wed, 23 Aug 2023 14:00:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1701269579502/b7aa1c4b-1ed4-4b06-8656-d3537d05b4cb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>‫‫ في ال read committed isolation level معروف ان كل transaction بتاخد snapshot من الداتا وتتعامل معاها وبالتالي اللي كل transaction بتعمله مفيش اي transaction تانية بتشوفه الا لما يحصل commit الطريقة دي اسمها MVCC (Multi version concurrency control). بس السؤال بقا في حالة لو عندي constraint من التلاتة دول :Primary key, Unique, EXCLUDE USING. في الحالة دي مش هينفع يبقى في نفس الvalue في نفس ال column بس بما ان كل transaction بتاخد snapshot تشتغل فيها ففي حالة لو في 2 concurrent transactions الكلام دا معناه ان وارد كل واحده فيهم تحط نفس ال value في column عليه constraint وكدا لازم واحدة منهم تترفض والا ال constraints دي ملهاش لازمة كدا. طيب ايه اللي بيحصل بقا من postgres عشان نتفادى الموضوع دا؟ خلينا نشوف ايه اللي بيحصل عملياً وبعدها نرجع نشرح ايه اللي بيتم</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/weXMIfcLs0s">https://youtu.be/weXMIfcLs0s</a></div>
<p> </p>
<p>‫‫ كدا احنا شوفنا ال transaction بتـstuck ومبترجعش اي feedback سواء بإنها تقولك ان حصل insertion فعلا او ترجع error عادي و دا لأنها مستنية ال transaction التانية تحدد موقفها اذا كانت هتعمل commit وبالتالي ال value دي بقت موجودة بالفعل وانت بتحاول تدخل duplicated value فبترجعلك ERROR او ان ال transaction عملت rollback وبالتالي ال value اللي انت عايز تدخلها دي مش موجودة وتقدر تضيفها عادي و ال insertion هيتم. السؤال بقا الكلام دا بيحصل ازاي و ليه في حين ان المفروض transaction A مش شايفة ولا تعرف ايه اللي transaction B بتعمله؟ قالك بقا postgres بتاخد بالها من الموضوع دا بطريقة non-MVCC وهي انها بتبص على ال data structure بتاع ال index اللي موجود. ‫‫ انت لما بتضيف داتا في column عليه index الداتا دي بتروح في ال index data structure وبالتالي postgres شايفة اللي كل transaction بتعمله حتى لو هي لسه مش committed. بس لحظة! مين جاب سيرة ال index? مين قال ان في index على ال column دا؟ قالك بقا postgres بتعمل index على اي column عليه ال constraints دي من غير ماحضرتك تطلب منها انها تعمله وهي فعلا بتعمله عشان تستفيد منه في حل ال case اللي احنا بنناقشها دي. تقدر تشوف ال indexes الموجودة عندك من خلال الأمر دا</p>
<p><code>SELECT indexname FROM pg_indexes WHERE tablename = your_table_name ;</code> ‫</p>
<p>‫ زي ما واضح في الصورة دي انا عملت table وعملت id PK, username UNIQUE وبعدها جبت ال index اللي موجوده ولقيته عمل على ال username زي ما واضح</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692793865512/2d351605-0e49-4792-8062-adf61bf8281e.png" alt class="image--center mx-auto" /></p>
<p>‫ طيب ممكن يتبادر الى ذهنك سؤال مهم ماذا لو كل transaction منهم عملت insert ب value التانية بتحاول تعمل insert بنفس ال value يعني حسب الكلام اللي قولناه فوق ان كل واحدة كدا هتـstuck وتستنى التانية اللي هي برضو هتبقى stucked وبكدا كل واحدة مستنية التانية تحدد موقفها؟ ايوا بالضبط هو دا ال deadlock بعينه. postgres هتقولك <code>deadlock detected</code> وهتنجح واحدة منهم وهترجع error للتانية، اللي هتنجح هي اللي دخلت ال deadlock الأول زي ما واضح في الصورتين دول.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692798880048/14b6eed9-f1a0-4c57-8f62-27d724ee2174.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692798840970/f5f3b295-ffc3-4bb4-9310-d0fce43743c7.png" alt class="image--center mx-auto" /></p>
<p>‫ لو في اي feedback تقدر توصلي على twitter @AhmedMonm1</p>
<p>المصادر:</p>
<p>‫ 1- كورس حسين ناصر على يوديميconcurrency control chapter link: https://www.udemy.com/course/database-engines-crash-course/</p>
<p>2- The Art of PostgreSQL, Chapter 8 Indexing Strategy, Indexing for Constraints</p>
]]></content:encoded></item></channel></rss>