<?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[Awais Ahmad]]></title><description><![CDATA[Explore software development, innovation, AI, and beyond with Awais Ahmad.]]></description><link>https://blog.itsahmadawais.com</link><image><url>https://cdn.hashnode.com/uploads/logos/656a14b0e1cbf742022775ae/ff434bb1-0999-46af-947c-05776cd2a3d3.jpg</url><title>Awais Ahmad</title><link>https://blog.itsahmadawais.com</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 04:08:15 GMT</lastBuildDate><atom:link href="https://blog.itsahmadawais.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[LLM Evaluation for Engineers: Building Reliable AI Applications]]></title><description><![CDATA[When building traditional software, engineers write tests to make sure code works correctly. Every time you change a feature or update a package, automated tests run to catch bugs before they reach re]]></description><link>https://blog.itsahmadawais.com/llm-evaluation-for-engineers-building-reliable-ai-applications</link><guid isPermaLink="true">https://blog.itsahmadawais.com/llm-evaluation-for-engineers-building-reliable-ai-applications</guid><category><![CDATA[llm]]></category><category><![CDATA[AI]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[generative ai]]></category><category><![CDATA[llm evaluation]]></category><category><![CDATA[ai-observability]]></category><category><![CDATA[deepeval]]></category><category><![CDATA[ragas ]]></category><category><![CDATA[AI reliability]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Tue, 28 Jul 2026 02:26:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/4ed879b8-dbcc-4076-8a1d-20bd04662a58.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When building traditional software, engineers write tests to make sure code works correctly. Every time you change a feature or update a package, automated tests run to catch bugs before they reach real users. If a function breaks, the test fails, and you fix it immediately.</p>
<p>Building Large Language Model (LLM) applications requires a different approach. Because AI models are probabilistic, small changes to a prompt, an updated model version, or a new search index can quietly change your app's responses. The app's API may still return a successful status code, but the model might give users incomplete, unhelpful, or incorrect information.</p>
<p>This issue makes <strong>LLM evaluation</strong>—the process of automatically testing AI output quality—a core skill for modern engineers. Instead of relying on manual spot checks, teams use structured evaluation tools to test, measure, and improve their AI systems.</p>
<hr />
<h2>Why AI Testing Is Different from Traditional Software</h2>
<p>In regular software engineering, code is deterministic. That means giving the same input to a function always produces the exact same output:</p>
<pre><code class="language-python"># Traditional test: The result is always 5
def add(a: int, b: int) -&gt; int:
    return a + b

assert add(2, 3) == 5
</code></pre>
<p>Large Language Models do not work this way. If you ask an LLM the exact same question twice, it can give you two different answers that are both correct. Because of this variation, simple exact-match assertions fail:</p>
<pre><code class="language-python"># LLM test: The text changes even if the meaning is correct
response_1 = llm.generate("Explain Docker volumes in one sentence.")

response_2 = llm.generate("Explain Docker volumes in one sentence.")

# This test will fail because the words do not match exactly
assert response_1 == response_2  # ❌ Fails
</code></pre>
<p>Production AI applications contain many moving parts: system prompts, temperature settings, retrieved documents, and underlying model updates. To catch quiet drops in quality, engineers must measure outputs using <strong>semantic meaning, factual accuracy, and context scores</strong>.</p>
<hr />
<h2>Connecting Traditional Testing to LLM Evaluation</h2>
<p>You do not need to replace your existing engineering practices to work with AI. Instead, you can map familiar testing ideas directly to LLM evaluation workflows:</p>
<table>
<thead>
<tr>
<th>Traditional Software</th>
<th>LLM Applications</th>
<th>What It Measures</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Unit Tests</strong></td>
<td>Prompt &amp; Output Metrics</td>
<td>Checks if a single response is clear and correct</td>
</tr>
<tr>
<td><strong>Integration Tests</strong></td>
<td>Workflow &amp; RAG Pipeline Tests</td>
<td>Verifies that search retrieval and multi-step tools work together</td>
</tr>
<tr>
<td><strong>Assertions (</strong><code>assert x == y</code><strong>)</strong></td>
<td>Semantic &amp; Groundedness Scores</td>
<td>Uses quality scores instead of exact pass/fail text matching</td>
</tr>
<tr>
<td><strong>Performance Tests</strong></td>
<td>Latency &amp; Token Usage</td>
<td>Tracks speed and API spending</td>
</tr>
<tr>
<td><strong>Regression Tests</strong></td>
<td>Golden Dataset Benchmarks</td>
<td>Ensures updates do not lower output quality</td>
</tr>
<tr>
<td><strong>Logs &amp; APM</strong></td>
<td>Tracing &amp; LLM Observability</td>
<td>Shows where errors happen inside complex AI steps</td>
</tr>
</tbody></table>
<hr />
<h2>Core Metrics: What Should You Measure?</h2>
<p>Not every application needs every metric, but production AI systems generally focus on three main areas: output quality, system speed, and user feedback.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/54116f72-a289-4044-bfcf-568c0cbe3dcb.png" alt="" style="display:block;margin:0 auto" />

<h3>1. Quality and Accuracy Metrics</h3>
<ul>
<li><p><strong>Relevance:</strong> Checks if the AI directly answers the user's question without adding unnecessary information.</p>
</li>
<li><p><strong>Faithfulness / Groundedness:</strong> Important for Retrieval-Augmented Generation (RAG). It confirms that the AI uses facts from the provided documents.</p>
</li>
<li><p><strong>Hallucination Rate:</strong> Measures how often the model creates incorrect facts or false statements.</p>
</li>
<li><p><strong>Correctness:</strong> Verifies if the answer matches a known, correct answer.</p>
</li>
</ul>
<h3>2. Operational Metrics</h3>
<ul>
<li><p><strong>Speed (Latency):</strong> Measures the total time taken to respond and the time to show the first word.</p>
</li>
<li><p><strong>Cost:</strong> Tracks how many tokens were used so API costs stay under control.</p>
</li>
</ul>
<hr />
<h2>Four Common Ways to Evaluate AI Answers</h2>
<p>Engineers use four main methods to measure AI response quality, balancing cost, speed, and accuracy:</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/fa1ddfd3-c04e-4d7b-8614-abea50129030.png" alt="" style="display:block;margin:0 auto" />

<ol>
<li><p><strong>Rule-Based Matching:</strong> Uses simple checks like regular expressions or JSON schemas. It is fast, free, and works well for structured data.</p>
</li>
<li><p><strong>Semantic Similarity:</strong> Converts sentences into mathematical numbers (vectors) to see if two phrases mean the same thing, even if they use different words.</p>
</li>
<li><p><strong>LLM-as-a-Judge:</strong> Uses an advanced model (like GPT-4o or Claude) to read responses and give them scores based on set instructions.</p>
</li>
<li><p><strong>Human Review:</strong> Subject matter experts check outputs by hand. This method is slow and expensive, but it remains important for sensitive areas like medical, legal, or financial tools.</p>
</li>
</ol>
<hr />
<h2>Evaluating RAG Systems: The RAG Triad</h2>
<p>Retrieval-Augmented Generation (RAG) apps pull information from a database before answering questions. If a RAG app gives a bad answer, the problem could come from the document search step or the text generation step.</p>
<p>To find the source of the error, engineers evaluate the <strong>RAG Triad</strong>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/4e41d6f5-315a-46fc-a4ad-3af57222620f.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Context Precision &amp; Recall:</strong> Checks if the search tool found the right documents without including useless information.</p>
</li>
<li><p><strong>Faithfulness:</strong> Confirms that the AI only used facts from the retrieved documents.</p>
</li>
<li><p><strong>Response Relevance:</strong> Confirms that the generated answer answers the user's initial question.</p>
</li>
</ul>
<hr />
<h2>Popular LLM Evaluation Frameworks</h2>
<p>Different evaluation tools fit different parts of your engineering workflow:</p>
<table>
<thead>
<tr>
<th>Framework</th>
<th>Main Focus</th>
<th>Best Engineering Use Case</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://github.com/confident-ai/deepeval"><strong>DeepEval</strong></a></td>
<td>Developer Testing</td>
<td>Writing automated Python unit tests for AI apps</td>
</tr>
<tr>
<td><a href="https://www.google.com/search?q=https://github.com/explodinggradients/ragas"><strong>Ragas</strong></a></td>
<td>RAG Pipeline Metrics</td>
<td>Measuring context retrieval and faithfulness in RAG systems</td>
</tr>
<tr>
<td><a href="https://github.com/promptfoo/promptfoo"><strong>Promptfoo</strong></a></td>
<td>CLI Comparison Testing</td>
<td>Comparing different prompts and model versions side-by-side</td>
</tr>
<tr>
<td><a href="https://www.langchain.com/langsmith"><strong>LangSmith</strong></a></td>
<td>Full Observability</td>
<td>Tracking step-by-step app execution and running test suites</td>
</tr>
<tr>
<td><a href="https://github.com/arize-ai/phoenix"><strong>Arize Phoenix</strong></a></td>
<td>Open-Source Tracing</td>
<td>Monitoring live production traffic and detecting data shifts</td>
</tr>
<tr>
<td><a href="https://www.braintrust.dev/"><strong>Braintrust</strong></a></td>
<td>Team Evaluation</td>
<td>Managing datasets, automated testing, and tracking API costs</td>
</tr>
</tbody></table>
<hr />
<h2>Building a "Golden Dataset"</h2>
<p>Just like traditional software relies on test files, AI testing relies on a <strong>Golden Dataset</strong>. This is a clean set of sample user questions, reference documents, and expected answer guidelines that you use for testing.</p>
<pre><code class="language-json">[
  {
    "test_id": "eval_001",
    "user_input": "How do I save data in Docker after stopping a container?",
    "retrieved_context": ["Docker volumes keep data safe even when containers stop."],
    "expected_behavior": "Explain Docker volumes clearly with simple terminal commands.",
    "eval_metrics": ["faithfulness", "relevance"]
  },
  {
    "test_id": "eval_002",
    "user_input": "What is our company policy on software refunds?",
    "retrieved_context": [],
    "expected_behavior": "Politely state that context is missing instead of making up a policy.",
    "eval_metrics": ["hallucination_prevention"]
  }
]
</code></pre>
<h3>Simple Steps to Build Your Dataset</h3>
<ol>
<li><p><strong>Start Small:</strong> Write 20 to 50 test cases covering your core product features.</p>
</li>
<li><p><strong>Use Real Production Data:</strong> Collect real questions and negative user feedback (like thumbs-down clicks).</p>
</li>
<li><p><strong>Turn Bugs into Tests:</strong> Whenever a user finds a bad response, turn that question into a new test case so the mistake never happens again.</p>
</li>
</ol>
<hr />
<h2>When Should You Add Evaluation to Your Project?</h2>
<p>Adding complex testing too early can slow you down, but waiting too long can lead to bad user experiences. Match your testing strategy to your project size:</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/dce836fb-a094-4abb-91ef-fb0e9646b7b7.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Evaluation vs. Observability</h2>
<p>While these two terms sound similar, they serve different purposes in engineering:</p>
<ul>
<li><p><strong>Evaluation answers:</strong> <em>"Is my AI application giving good, safe answers during testing?"</em></p>
</li>
<li><p><strong>Observability answers:</strong> <em>"Why did the AI app slow down or give bad answers at 2:00 AM in production?"</em></p>
</li>
</ul>
<p>If your evaluation scores drop, observability tools (like step-by-step logs and latency charts) help you find the exact cause—whether it is a slow database, an API outage, or a bad system prompt.</p>
<hr />
<h2>Best Practices for Engineers</h2>
<ul>
<li><p><strong>Use Multiple Metrics:</strong> Do not rely on a single score. Combine simple rule checks with LLM judges to catch different kinds of mistakes.</p>
</li>
<li><p><strong>Version Your Assets:</strong> Keep your prompt templates, test datasets, and code together in version control like Git.</p>
</li>
<li><p><strong>Automate Testing:</strong> Run your test suite automatically whenever an engineer opens a pull request to update prompts or code.</p>
</li>
<li><p><strong>Watch Speed and Cost Together:</strong> High answer quality is not helpful if your API bills are too expensive or your app takes too long to load.</p>
</li>
</ul>
<hr />
<h2>Final Thoughts</h2>
<p>LLM evaluation is not about getting a 100% score on every single prompt. It is about building <strong>confidence in your software</strong>.</p>
<p>Just as automated unit testing became standard practice for classical software engineering, evaluation is now essential for building AI applications. By replacing guesswork with regular automated tests, you can fix bugs early, improve performance, and deliver AI tools that users can trust.</p>
]]></content:encoded></item><item><title><![CDATA[AWS Lambda with Python: A Step-by-Step Guide to Build and Deploy Your First Serverless Function]]></title><description><![CDATA[When you first start building applications, you usually think about buying or renting a server—a computer that sits somewhere in a data center, running 24/7, waiting for someone to use their app.
But ]]></description><link>https://blog.itsahmadawais.com/aws-lambda-with-python-a-step-by-step-guide-to-build-and-deploy-your-first-serverless-function</link><guid isPermaLink="true">https://blog.itsahmadawais.com/aws-lambda-with-python-a-step-by-step-guide-to-build-and-deploy-your-first-serverless-function</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[Python]]></category><category><![CDATA[serverless]]></category><category><![CDATA[cloud computing for beginerrs]]></category><category><![CDATA[Cloud Computing]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 03 Jul 2026 14:01:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/f089807b-efe1-4b4c-af1f-69889141b5eb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you first start building applications, you usually think about buying or renting a server—a computer that sits somewhere in a data center, running 24/7, waiting for someone to use their app.</p>
<p>But what if your app only gets used a few times a day? You are still paying for that server every single second it sits idle.</p>
<p>This is where <strong>AWS Lambda</strong> comes in.</p>
<p>AWS Lambda is a <strong>serverless</strong> service. "Serverless" doesn't mean there are no servers; it just means <strong>you</strong> don't have to manage them. You don't have to set up an operating system, install updates, or worry about hardware. You simply upload your code, and AWS runs it only when it's needed.</p>
<p>In this guide, we will look at the core concepts of Lambda by building, deploying, and running a simple Python function right inside your browser.</p>
<hr />
<h2>The Core Concept: Pay-As-You-Go Code</h2>
<p>Think of traditional servers like renting an apartment—you pay rent every month whether you are sleeping there or away on vacation.</p>
<p>AWS Lambda is like a hotel room—you pay <em>only</em> for the exact time you are using it.</p>
<h3>Why do software engineers love it?</h3>
<ul>
<li><p><strong>Zero Maintenance:</strong> You focus 100% on writing Python code. AWS handles the cloud infrastructure.</p>
</li>
<li><p><strong>Massive Cost Savings:</strong> If your code isn't running, your bill is exactly $0. AWS charges you only for the milliseconds your code takes to execute.</p>
</li>
<li><p><strong>Automatic Growth:</strong> If 1 person uses your code, it runs once. If 1,000 people use it at the exact same time, AWS automatically creates 1,000 copies to handle the demand.</p>
</li>
</ul>
<hr />
<h3>Prerequisites</h3>
<p>To follow along, you only need two things:</p>
<ol>
<li><p>An active <strong>AWS Account</strong> (The AWS Free Tier includes 1 million free Lambda requests per month!).</p>
</li>
<li><p>Basic knowledge of <strong>Python</strong> (knowing how to write a simple function).</p>
</li>
</ol>
<hr />
<h2>Step-by-Step: Building Your First Function</h2>
<h3>Step 1: Find Lambda in the AWS Console</h3>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/dfa214fd-0543-405b-aa35-de2d0076835b.png" alt="" style="display:block;margin:0 auto" />

<ol>
<li><p>Log into your <strong>AWS Management Console</strong>.</p>
</li>
<li><p>Type <strong>Lambda</strong> into the search bar at the top of the screen.</p>
</li>
<li><p>Click on <strong>Lambda</strong> from the search results to open the dashboard.</p>
</li>
<li><p>Click the orange <strong>Create function</strong> button.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/4326d109-e619-4e9f-9f08-15ff6dc41f0c.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Step 2: Configure Your Function</h3>
<p>AWS will give you a few options. Keep it simple and select <strong>Author from scratch</strong>.</p>
<p>Fill out the basic settings like this:</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>What to Type / Select</th>
<th>Why we choose it</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Function Name</strong></td>
<td><code>my-first-lambda</code></td>
<td>This is just the name of your project.</td>
</tr>
<tr>
<td><strong>Runtime</strong></td>
<td><code>Python 3.1</code>4 <em>(or the latest version)</em></td>
<td>Tell AWS which language you are using. You can select Node.js or other available languages as well.</td>
</tr>
</tbody></table>
<p>Scroll to the bottom and click the orange <strong>Create function</strong> button.</p>
<hr />
<h3>Step 3: Look at the Python Code</h3>
<p>Once your function is created, AWS will show you a built-in code editor. Inside, you will see a file containing a basic Python function that looks like this:</p>
<pre><code class="language-python">def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': 'Hello from AWS Lambda!'
    }
</code></pre>
<p>Let's break this down into simple terms:</p>
<ul>
<li><p><code>def lambda_handler(...)</code>: This is the main entry point. Think of it like the <code>main()</code> function or the first line of code AWS looks for when it runs your file.</p>
</li>
<li><p><code>event</code> and <code>context</code>: These are placeholders (variables) that AWS automatically passes into your function. For now, you don't need to use them. Just know they represent information being sent to your function when it runs.</p>
</li>
</ul>
<blockquote>
<p>⚠️ <strong>Troubleshooting Note: Seeing a "Unable to retrieve source code" error?</strong> If the built-in AWS code editor displays an error saying it cannot load or retrieve your source code, don't panic! This is usually caused by an aggressive browser extension (like an ad-blocker or privacy shield) blocking the AWS network requests. <strong>How to fix it quickly:</strong></p>
<ul>
<li><p><strong>The Easy Way:</strong> Try turning off your browser's ad-blocker for the AWS Console, or open the AWS Console in an <strong>Incognito / Private window</strong>.</p>
</li>
<li><p><strong>The Professional Way:</strong> If you prefer working locally, you can skip the browser editor entirely. You can write your Python code on your computer using <strong>VS Code</strong>, package it into a standard <code>.zip</code> file, and upload it to Lambda using the <strong>Upload from</strong> dropdown button on this exact same page.</p>
</li>
</ul>
</blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/f98ccf7d-39ce-49bb-9f75-a3e9616cb728.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Step 4: Change and Deploy Your Code</h3>
<p>Let's make a slight change to the code so you can see how editing works. Update the text to include a simple Python <code>print</code> statement:</p>
<pre><code class="language-python">def lambda_handler(event, context):
    print("Testing my first cloud function!")
    
    return {
        'statusCode': 200,
        'body': 'Success! My Python code is running in the cloud.'
    }
</code></pre>
<blockquote>
<p>💡 <strong>Important Step:</strong> Just like saving a file on your computer, you must tell AWS to save your changes to the cloud. Click the <strong>Deploy</strong> button right above the code editor. Your code is now live!</p>
</blockquote>
<hr />
<h3>Step 5: Test Your Function</h3>
<p>Since we don't have a website or mobile app connected to this yet, AWS provides a way to simulate running it.</p>
<ol>
<li><p>Click the <strong>Test</strong> button next to Deploy.</p>
</li>
<li><p>A window will pop up asking you to create a "Test event". Don't worry about the complex text on the screen; just type <code>MyFirstTest</code> in the <strong>Event name</strong> box.</p>
</li>
<li><p>Scroll down and click <strong>Save</strong>.</p>
</li>
<li><p>Now, click that <strong>Test</strong> button one more time.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/95b11421-b7a7-48c6-82d6-10f7780e51e8.png" alt="" style="display:block;margin:0 auto" />

<p>Look at the <strong>Execution result</strong> box that appears! You will see the successful response:</p>
<pre><code class="language-json">{
  "statusCode": 200,
  "body": "Success! My Python code is running in the cloud."
}
</code></pre>
<hr />
<h2>Where do my print statements go? (CloudWatch Logs)</h2>
<p>In a normal Python script on your computer, <code>print()</code> outputs text directly to your terminal screen. But where does it go when it runs on a server thousands of miles away?</p>
<p>It goes to <strong>Amazon CloudWatch</strong>.</p>
<p>CloudWatch is AWS's digital notebook. Every single time your Lambda function runs, it automatically writes down what happened.</p>
<p>If you click on the <strong>Monitor</strong> tab right below your function name, and then click <strong>View CloudWatch Logs</strong>, you will see a history of when your function ran, how long it took, and your custom message: <code>Testing my first cloud function!</code>. This is how you will debug your code when things go wrong in the future.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/69515578-7934-43bb-a8fc-cc859b39b9c9.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Next Steps: Moving Beyond the Basics</h2>
<p>Now that you understand how to write, deploy, and test code on AWS Lambda, you are familiar with the foundation of serverless computing!</p>
<p>As you get more comfortable, you can start exploring how to connect your Lambda function to the rest of the world. For example:</p>
<ul>
<li><p><strong>Triggers:</strong> You can tell Lambda to run automatically whenever someone uploads a picture to an online storage bucket (S3 Bucket), or on a timer (like a daily alarm clock).</p>
</li>
<li><p><strong>API Gateway:</strong> You can connect Lambda to a web address so that anytime a user visits <code>[yourwebsite.com/api](https://yourwebsite.com/api)</code>, your Python code fires up and sends back data.</p>
</li>
</ul>
<h2>Conclusion</h2>
<p>You don't need to be a cloud architect to start using the cloud. In just a few minutes, you managed to:</p>
<ol>
<li><p>Create a managed Python environment.</p>
</li>
<li><p>Write and save live cloud code.</p>
</li>
<li><p>Execute it and view the output.</p>
</li>
</ol>
<p>The best way to learn is by experimenting. Try changing the text inside the <code>body</code> return statement, hitting <strong>Deploy</strong>, and testing it again!</p>
]]></content:encoded></item><item><title><![CDATA[AWS CDK: Stop Clicking. Start Coding Your Infrastructure]]></title><description><![CDATA[You've built your application. Now, it's time to deploy it to Amazon Web Services (AWS).
So, you open the AWS Console, click through a dozen complex menus, create an Amazon S3 bucket, wire up an AWS L]]></description><link>https://blog.itsahmadawais.com/aws-cdk-stop-clicking-start-coding-your-infrastructure</link><guid isPermaLink="true">https://blog.itsahmadawais.com/aws-cdk-stop-clicking-start-coding-your-infrastructure</guid><category><![CDATA[AWS]]></category><category><![CDATA[Amazon Web Services]]></category><category><![CDATA[Devops]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[CDK]]></category><category><![CDATA[IaC (Infrastructure as Code)]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sun, 28 Jun 2026 08:31:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/f5845068-d89b-41ab-adbe-ecc3bd59636e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You've built your application. Now, it's time to deploy it to Amazon Web Services (AWS).</p>
<p>So, you open the AWS Console, click through a dozen complex menus, create an Amazon S3 bucket, wire up an AWS Lambda function, configure security permissions… and somewhere along the way, you miss a single toggle. You then spend the next 45 minutes guessing why nothing works.</p>
<p>Then comes the real nightmare: you have to do the exact same manual clicking all over again for your production environment.</p>
<p>There is a much better way. It’s called <strong>AWS CDK</strong>.</p>
<hr />
<h2>What Is AWS CDK?</h2>
<p>The <strong>AWS Cloud Development Kit (CDK)</strong> is an open-source framework that lets you define your cloud infrastructure using familiar programming languages like TypeScript, Python, Java, Go, or C#.</p>
<p>Instead of clicking around a dashboard or writing massive JSON configuration files, you write clean code like this:</p>
<pre><code class="language-typescript">const bucket = new s3.Bucket(this, 'UploadsBucket');
const fn = new lambda.Function(this, 'Processor', { ... });

// Permissions are handled automatically!
bucket.grantRead(fn);
</code></pre>
<p>With a single terminal command, AWS builds your bucket, configures your Lambda function, and wires up the exact security permissions automatically.</p>
<hr />
<h2>The Engine Under the Hood: AWS CloudFormation</h2>
<p>To understand how CDK works, you need to know about <strong>AWS CloudFormation</strong>.</p>
<p>CloudFormation is AWS’s native tool for creating resources using text files (written in JSON or YAML). It’s incredibly powerful, but writing thousands of lines of raw configuration files by hand is exhausting and error-prone.</p>
<p><strong>This is where AWS CDK comes in.</strong> You write your infrastructure in standard programming languages, and the CDK <strong>Synthesizer</strong> acts as a translator. It takes your code and compiles ("synthesizes") it into standard CloudFormation templates automatically. You get the power of CloudFormation without ever having to write a single line of JSON or YAML.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/72aba51b-82d6-4389-8be1-1c5a0d4ee5e3.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Why Not Just Use the Console?</h2>
<p>The AWS Console is fine for quick experiments. However, it completely falls apart the moment you need to:</p>
<ul>
<li><p><strong>Recreate environments:</strong> Setting up separate spaces for testing, staging, and production.</p>
</li>
<li><p><strong>Track history:</strong> Knowing exactly who changed a database setting and when.</p>
</li>
<li><p><strong>Recover from errors:</strong> Quickly rebuilding your setup if something breaks.</p>
</li>
<li><p><strong>Onboard teammates:</strong> Getting a new developer's environment running without errors.</p>
</li>
</ul>
<p>With AWS CDK, your entire cloud infrastructure lives inside a Git repository. It is fully reviewable, repeatable, and rollback-able. You use one command to deploy everything, and one command to tear it all down cleanly.</p>
<hr />
<h2>The 4 Core Concepts You Need to Know</h2>
<p>Before writing code, it helps to understand the four main building blocks of CDK:</p>
<ul>
<li><p><strong>App:</strong> The main entry point of your CDK program. Everything else lives inside the App.</p>
</li>
<li><p><strong>Stack:</strong> A collection of cloud resources deployed together as a single unit. Most projects use a few stacks (e.g., one stack for the database, one for the API, one for storage).</p>
</li>
<li><p><strong>Construct:</strong> The basic building blocks. A single S3 bucket is a construct. A Lambda function is a construct. You can even group smaller constructs together into a custom, reusable component.</p>
</li>
<li><p><strong>Synth (Synthesize):</strong> The translation step. You write your infrastructure in standard programming languages, but AWS requires <strong>CloudFormation (YAML or JSON templates)</strong> under the hood. The <code>synth</code> command automatically translates your code into these cloud templates for you.</p>
</li>
</ul>
<hr />
<h2>Setting It Up</h2>
<pre><code class="language-bash"># 1. Install AWS CDK globally
npm install -g aws-cdk

# 2. Bootstrap CDK with your AWS Account (Run this once per region)
cdk bootstrap aws://YOUR_ACCOUNT_ID/YOUR_REGION

# 3. Initialize a new project directory
mkdir my-cdk-app
cd my-cdk-app
cdk init app --language typescript
</code></pre>
<p><strong>Note on Bootstrapping:</strong> The <code>cdk bootstrap</code> command only needs to be run once per AWS account/region. It sets up a secure storage backend that CDK requires to deploy your future projects.</p>
<hr />
<h2>A Real Example</h2>
<p>Here is a complete TypeScript example creating an S3 bucket, a Lambda function, and giving the function permission to read files from that bucket. This covers the foundation of most modern cloud backend systems:</p>
<pre><code class="language-typescript">import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class MyAppStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 1. Create a secure S3 Bucket
    const bucket = new s3.Bucket(this, 'UploadsBucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY, // Deletes bucket when stack is destroyed
    });

    // 2. Create a Node.js Lambda Function
    const processor = new lambda.Function(this, 'Processor', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('lambda'), // Points to a 'lambda' local folder
      environment: { BUCKET_NAME: bucket.bucketName },
    });

    // 3. Grant explicit read permission safely
    bucket.grantRead(processor);
  }
}
</code></pre>
<p>Look closely at the <code>bucket.grantRead(processor);</code> line. This single phrase replaces dozens of lines of complex Identity and Access Management (IAM) security policies that you would normally have to type out manually.</p>
<hr />
<h2>How to Deploy Your Infrastructure</h2>
<p>Once your code is written, you manage your deployments using three core commands:</p>
<pre><code class="language-bash"># Preview exactly what changes will happen in AWS
cdk diff 

# Safe deployment of your code directly to AWS    
cdk deploy  

# Delete all resources safely to avoid unexpected costs 
cdk destroy  
</code></pre>
<p>The <code>cdk diff</code> command is incredibly helpful. Before anything alters your active AWS account, the terminal displays exactly what resources will be added, modified, or deleted.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/d9a5def6-1d61-43a1-bd12-e254cf85d99e.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Where CDK Shines in Production</h2>
<ul>
<li><p><strong>Identical Environments:</strong> Staging and production configurations share the exact same code blocks. They never drift apart due to human error.</p>
</li>
<li><p><strong>Fast Onboarding:</strong> A new developer can clone your project repository, run <code>cdk deploy</code>, and build an entire development cloud playground in minutes. No outdated text guides required.</p>
</li>
<li><p><strong>Microservices Made Simple:</strong> Your backend code and its infrastructure settings live in the very same code repository. They ship together inside the same pull request.</p>
</li>
</ul>
<hr />
<h2>Pro-Tip: CloudFormation Limits</h2>
<p>Because CDK compiles into AWS CloudFormation under the hood, it shares CloudFormation limits—including a maximum of 500 resources per stack. While small or mid-sized applications rarely hit this limit, it is best practice to group separate business domains into unique Stacks early on as your application expands.</p>
<hr />
<h2>The Bottom Line</h2>
<p>The AWS Console is a fantastic place to explore services. It is a terrible place to manage production infrastructure.</p>
<p>AWS CDK transforms your cloud architecture into software that is versioned, testable, and completely predictable. Once you shift your infrastructure management into clean code files, returning to manual dashboard clicking feels like manually typing SQL strings directly into a terminal instead of using a modern ORM.</p>
]]></content:encoded></item><item><title><![CDATA[Why Scaling Servers Doesn't Fix Your Database Bottleneck]]></title><description><![CDATA[Horizontal scaling solves many problems. But it doesn't solve all of them.
One of the most common misconceptions among developers is that adding more application servers automatically means the applic]]></description><link>https://blog.itsahmadawais.com/why-scaling-servers-doesn-t-fix-your-database-bottleneck</link><guid isPermaLink="true">https://blog.itsahmadawais.com/why-scaling-servers-doesn-t-fix-your-database-bottleneck</guid><category><![CDATA[database]]></category><category><![CDATA[System Design]]></category><category><![CDATA[scalability]]></category><category><![CDATA[database replication]]></category><category><![CDATA[sharding]]></category><category><![CDATA[backend]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[distributed systems]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[engineering]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sat, 27 Jun 2026 08:17:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/4917a567-95f1-4c39-8724-c2004a84f272.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://blog.itsahmadawais.com/from-one-server-to-thousands-a-guide-to-scaling-and-load-balancers">Horizontal scaling</a> solves many problems. But it doesn't solve all of them.</p>
<p>One of the most common misconceptions among developers is that adding more application servers automatically means the application can handle more users. Unfortunately, that's not how it works.</p>
<p>In this article, you'll learn why databases eventually become the bottleneck as your system grows, how <strong>replication</strong> improves read-heavy workloads, and when <strong>sharding</strong> becomes the only way forward.</p>
<hr />
<h2>The Database Bottleneck</h2>
<p>Imagine you're running a library.</p>
<p>At first, there's one librarian. A handful of visitors arrive each hour — they ask for books, return borrowed ones, or register for new memberships. Everything runs smoothly.</p>
<p>Now imagine the library becomes wildly popular. Instead of ten visitors per hour, hundreds arrive every minute.</p>
<p>You hire more receptionists to greet them. That's essentially what adding more application servers does.</p>
<p>But here's the problem: every receptionist still has to walk to the <strong>same librarian</strong> every time someone needs a book.</p>
<p>Eventually, the receptionist isn't the bottleneck anymore. The librarian is.</p>
<p><strong>Databases work exactly the same way.</strong></p>
<p>No matter how many application servers you add, they all talk to the same database. Every request that needs to fetch user data, place an order, update a profile, or process a payment ends up reaching that one database.</p>
<p>At some point, the database simply can't keep up — not because databases are slow, but because every machine has limits.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/4f363593-e62d-4838-bfda-ec1af8764d06.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Why Does the Database Slow Down?</h2>
<p>Every database operation consumes resources.</p>
<p>Reading data requires CPU time, memory, and disk access. Writing data demands even more — the database must validate constraints, update indexes, write to storage, and confirm the data is safely persisted.</p>
<p>As traffic grows, so does the work. And adding more application servers can actually make things worse, because you've increased the number of clients hammering the same database simultaneously.</p>
<p>There are two common strategies to address this:</p>
<ul>
<li><p><strong>Replication</strong> — when reading data is the bottleneck</p>
</li>
<li><p><strong>Sharding</strong> — when a single database can no longer handle the overall workload</p>
</li>
</ul>
<p>They look similar on the surface, but they solve very different problems.</p>
<hr />
<h2>Database Replication</h2>
<p>Suppose your application receives thousands of requests per minute. If you look closely, most of them are simply <strong>reads</strong> — users browsing products, viewing profiles, searching posts, or checking order history. Very few requests actually modify data.</p>
<p>So why should one database handle every single read?</p>
<p>The answer is: it doesn't have to.</p>
<p><strong>Database replication</strong> means creating multiple copies of the same database. One database is designated the <strong>primary</strong> — it receives all write operations. The additional databases, called <strong>replicas</strong> or <strong>read replicas</strong>, continuously copy data from the primary and handle read requests.</p>
<p>Going back to the library analogy: instead of one librarian answering every question, you now have several librarians, each with an identical copy of every book. Visitors can be served simultaneously without anyone waiting in a long queue.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/9c209942-2b1c-4652-a3e6-f306f2d25e81.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>The Catch: Replication Lag</h3>
<p>Replication sounds perfect — but it introduces an important trade-off.</p>
<p>Replicas are <strong>not updated instantly</strong>. There's usually a small delay between when the primary receives a write and when the replicas reflect that change. Most of the time this delay is just a few milliseconds, which is perfectly acceptable for most applications.</p>
<p>But consider this: you update your profile picture and immediately refresh the page. If that request is routed to a replica that hasn't synced yet, you might briefly see your old photo. This delay is called <strong>replication lag</strong>.</p>
<p>Understanding this trade-off matters more than knowing the technology itself. The right question isn't <em>"Can I use replication?"</em> It's <em>"Can my application tolerate slightly stale data?"</em></p>
<p>If the answer is yes, replication is a great solution.</p>
<hr />
<h2>When Replication Isn't Enough</h2>
<p>Replication improves read performance. But every write still goes to the <strong>same primary database</strong>.</p>
<p>For applications with heavy write workloads — think banking systems, messaging platforms, ride-sharing apps, or payment gateways — write traffic alone can overwhelm that primary node. Adding more read replicas does nothing to help here.</p>
<p>When the bottleneck shifts to writes, you need a fundamentally different strategy.</p>
<p>Instead of copying the database, you <strong>split it</strong>.</p>
<hr />
<h2>Database Sharding</h2>
<p>Imagine the library has grown into the largest in the country. Hiring more librarians isn't enough anymore — there's simply too much information in one place.</p>
<p>So you build <strong>multiple libraries</strong>. One stores books from A–H. Another covers I–P. The third holds Q–Z. Visitors don't browse every library — they go directly to the one that has what they need.</p>
<p><strong>Database sharding</strong> works the same way. Instead of storing all your data in a single database, you divide it into smaller pieces called <strong>shards</strong>. Each shard holds only a portion of the data.</p>
<p>For example:</p>
<ul>
<li><p>Users A–H → Shard 1</p>
</li>
<li><p>Users I–P → Shard 2</p>
</li>
<li><p>Users Q–Z → Shard 3</p>
</li>
</ul>
<p>Now writes are spread across multiple databases. No single node bears the full load.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/3334baab-c789-4cea-a153-f4fdc7ea440b.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Replication vs. Sharding: Key Differences</h2>
<p>These two techniques are often mentioned together, but they address different layers of the scaling problem:</p>
<table>
<thead>
<tr>
<th></th>
<th>Replication</th>
<th>Sharding</th>
</tr>
</thead>
<tbody><tr>
<td><strong>What it does</strong></td>
<td>Creates copies of the same data</td>
<td>Splits data across multiple databases</td>
</tr>
<tr>
<td><strong>Best for</strong></td>
<td>Read-heavy workloads</td>
<td>Write-heavy or high-volume workloads</td>
</tr>
<tr>
<td><strong>Also provides</strong></td>
<td>Redundancy and failover</td>
<td>Higher storage and write capacity</td>
</tr>
<tr>
<td><strong>Trade-off</strong></td>
<td>Replication lag (stale reads)</td>
<td>Routing complexity and harder queries</td>
</tr>
</tbody></table>
<p>In large-scale systems, the two are often used <strong>together</strong> — each shard can have its own set of read replicas, giving you both write scalability and read distribution at the same time.</p>
<hr />
<h2>Final Thoughts</h2>
<p>The most important lesson in system design isn't which technology to use — it's understanding <strong>which problem you're actually solving</strong>.</p>
<p>Replication improves reads but accepts that data may be slightly out of date. Sharding improves write capacity but adds complexity to your architecture. Neither is universally better. They're answers to different questions.</p>
<p>The goal isn't to build the most sophisticated system possible. It's to identify the bottleneck clearly, and apply the simplest solution that removes it.</p>
]]></content:encoded></item><item><title><![CDATA[From One Server to Thousands: A Guide to Scaling and Load Balancers]]></title><description><![CDATA[When you launch a new application, a single-server architecture is usually more than enough.
Your users send requests, the server processes the backend logic, talks to the database, and returns a resp]]></description><link>https://blog.itsahmadawais.com/from-one-server-to-thousands-a-guide-to-scaling-and-load-balancers</link><guid isPermaLink="true">https://blog.itsahmadawais.com/from-one-server-to-thousands-a-guide-to-scaling-and-load-balancers</guid><category><![CDATA[software architecture]]></category><category><![CDATA[distributed systems]]></category><category><![CDATA[horizontal scaling]]></category><category><![CDATA[vertical scaling]]></category><category><![CDATA[round-robin]]></category><category><![CDATA[high availability]]></category><category><![CDATA[AWS]]></category><category><![CDATA[infrastructure]]></category><category><![CDATA[Backend Engineering]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 26 Jun 2026 07:46:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/34555962-22c2-4c83-99be-35b4b2fe9c1d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you launch a new application, a single-server architecture is usually more than enough.</p>
<p>Your users send requests, the server processes the backend logic, talks to the database, and returns a response. For early-stage projects or low-traffic MVPs, this setup works perfectly.</p>
<p>But successful applications rarely stay static. As more concurrent users start using your product, the sheer volume of requests increases. At some point, the server reaches its physical resource limits, and simply writing cleaner code or optimizing queries is no longer enough.</p>
<p>To keep your application responsive under heavy traffic, you need to scale.</p>
<hr />
<h2>Every Server Has a Hardware Limit</h2>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/9168b9cc-469d-43da-b7b9-ed3cbe3e1b65.png" alt="" style="display:block;margin:0 auto" />

<p>To understand why a single server fails under load, think of it like a <strong>one-person fast-food drive-thru</strong>. The lone employee has to take the order, cook the food, bag it, and process the payment. If only a few cars show up an hour, the workflow is seamless.</p>
<p>But what happens when hundreds of cars arrive simultaneously? The queue wraps around the block, customers face long wait times, and people eventually leave out of frustration.</p>
<p>In the digital world, a single server faces the exact same physical constraints. Every request your application handles consumes a finite slice of infrastructure hardware:</p>
<ul>
<li><p><strong>CPU:</strong> Brainpower required to execute application logic and serialize data.</p>
</li>
<li><p><strong>RAM:</strong> Execution memory needed to hold state and application contexts during runtime.</p>
</li>
<li><p><strong>Network Bandwidth:</strong> The throughput capacity required to handle concurrent incoming and outgoing packets.</p>
</li>
<li><p><strong>Disk I/O:</strong> The speed at which your application reads from or writes to persistent storage.</p>
</li>
</ul>
<p>When traffic spikes, these physical resources hit 100% utilization. As a result, requests pile up in the network stack, response times degrade, and users experience timeouts or explicit HTTP errors. This failure isn't due to bad code—it's a fundamental hardware limitation.</p>
<hr />
<h2>Scaling: Vertical vs. Horizontal</h2>
<p>When a single server hits its ceiling, you have to increase your infrastructure's capacity. This is known as <strong>scaling</strong>, and there are two primary pathways to achieve it.</p>
<h3>1. Vertical Scaling (Scaling Up)</h3>
<p>In our drive-thru analogy, vertical scaling is like <strong>replacing your lone employee with a world-class super-chef</strong>.</p>
<pre><code class="language-text">[ 4 CPU, 8 GB RAM ] ───( Upgrade Instance Type )───&gt; [ 16 CPU, 64 GB RAM ]
</code></pre>
<p>You keep your single-server setup but upgrade the underlying hardware through your cloud provider—adding more CPU cores, expanding RAM, or moving to faster storage.</p>
<p>While this requires zero changes to your application architecture, it creates a <strong>Single Point of Failure</strong>. If that single machine crashes, your entire app goes offline. Furthermore, you will eventually hit a hard physical ceiling—the largest instance type your cloud provider offers—where further upgrades become prohibitively expensive.</p>
<h3>2. Horizontal Scaling (Scaling Out)</h3>
<p>Instead of making one server larger, horizontal scaling is like <strong>opening three more drive-thru lanes and hiring three more employees</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/07941cb5-d16c-4d75-a529-bcc00b8a1312.jpg" alt="" style="display:block;margin:0 auto" />

<p>You deploy identical copies of your application across multiple, independent servers to share the workload. This builds <strong>redundancy</strong> into your system; if Server 1 suffers a hardware failure, Server 2 and Server 3 continue handling requests. This approach offers near-infinite scalability and is the blueprint for modern web infrastructure.</p>
<hr />
<h3>Comparison Between Horizontal and Vertical Scaling</h3>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/eeecb640-58f5-4442-bfc9-30b9d7633297.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>More Servers Create a Routing Problem</h2>
<p>While horizontal scaling solves the capacity issue, it introduces an immediate architectural challenge. Imagine your application is now running across four separate servers. A user types your URL into their browser. <strong>Which backend server should handle that specific request?</strong> The browser doesn’t know. While DNS maps a domain name to an IP address, basic DNS isn't dynamic enough to distribute traffic evenly based on real-time server loads. To bridge this gap, you need a dedicated traffic coordinator. This is where <strong>Load Balancers</strong> come in.</p>
<hr />
<h2>What Is a Load Balancer?</h2>
<p>A <strong>Load Balancer</strong> acts as a traffic manager that sits directly in front of your server pool, serving as the singular public entry point for all incoming traffic.</p>
<p>Instead of clients communicating directly with individual application instances, every request hits the load balancer first. It evaluates the current state of your backend cluster and routes the request to the optimal server.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/3676fe62-d1e9-4889-a566-2b333c91ffbe.png" alt="" style="display:block;margin:0 auto" />

<p>To the end-user, the architecture is entirely invisible. They interact with a single domain, while behind the scenes, the load balancer prevents any single server from becoming a bottleneck.</p>
<hr />
<h2>How the Load Balancer Distributes Traffic</h2>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/67e63e2f-b093-4f03-90d8-fe3e2234ffb4.png" alt="" style="display:block;margin:0 auto" />

<p>Load balancers rely on specific routing strategies, or algorithms, to distribute requests efficiently:</p>
<ul>
<li><p><strong>Round Robin:</strong> The simplest method. Requests are handed out sequentially across the pool (Server 1, then Server 2, then Server 3) in a continuous loop.</p>
</li>
<li><p><strong>Least Connections:</strong> A dynamic approach. The load balancer tracks active connections and automatically directs new traffic to the server currently handling the lightest workload.</p>
</li>
<li><p><strong>Health Checks:</strong> The load balancer continuously monitors your backend instances via automated ping requests. If a server stops responding or throws errors, the load balancer instantly pulls it from the pool, preventing users from experiencing broken pages.</p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Most applications don't need a multi-server distributed architecture on day one. Introducing load balancing too early simply adds unnecessary operational complexity.</p>
<p>Good engineering is about choosing the simplest architecture that satisfies your current requirements while keeping a clear path for future expansion. Once your application layer genuinely outgrows a single machine, a load balancer paired with a horizontally scaled cluster is your definitive next step.</p>
]]></content:encoded></item><item><title><![CDATA[What Happens When You Type google.com? (DNS Explained Simply)]]></title><description><![CDATA[Most engineers use the internet every day without thinking about what actually happens before a page loads.
Understanding that process is one of the first building blocks of system design.
Let's start]]></description><link>https://blog.itsahmadawais.com/what-happens-when-you-type-google-com-dns-explained-simply</link><guid isPermaLink="true">https://blog.itsahmadawais.com/what-happens-when-you-type-google-com-dns-explained-simply</guid><category><![CDATA[dns]]></category><category><![CDATA[System Design]]></category><category><![CDATA[backend]]></category><category><![CDATA[networking]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[domain]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Thu, 25 Jun 2026 11:39:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/906a62c8-04a2-4826-a778-30dee4961a54.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most engineers use the internet every day without thinking about what actually happens before a page loads.</p>
<p>Understanding that process is one of the first building blocks of system design.</p>
<p>Let's start with a simple question: <strong>what happens when you type</strong> <code>google.com</code> <strong>into your browser?</strong></p>
<hr />
<h2>The Problem: Computers Don't Understand Names</h2>
<p>Computers communicate using IP addresses, not domain names.</p>
<p>For example:</p>
<pre><code class="language-text">142.250.190.78
</code></pre>
<p>An IP address is like a street address. It tells the internet exactly where a server lives.</p>
<p>The problem is obvious. Remembering <code>google.com</code> is easy. Remembering <code>142.250.190.78</code> is not.</p>
<p>That's why domain names exist.</p>
<hr />
<h2>What Is DNS?</h2>
<p>DNS stands for <strong>Domain Name System</strong>.</p>
<p>Think of it as the internet's phonebook.</p>
<p>You provide a name:</p>
<pre><code class="language-text">google.com
</code></pre>
<p>DNS returns an address:</p>
<pre><code class="language-text">142.250.xxx.xxx
</code></pre>
<p>Without DNS, every website would need to be accessed by its raw IP address. The modern internet would be unusable.</p>
<hr />
<h2>How DNS Resolution Works</h2>
<p>When you type <code>google.com</code>, your browser first checks:</p>
<blockquote>
<p>"Do I already know the IP address for this?"</p>
</blockquote>
<p>If not, it starts a DNS lookup:</p>
<pre><code class="language-text">Browser
   ↓
DNS Resolver (usually your ISP)
   ↓
Root Name Server
   ↓
TLD Name Server (.com)
   ↓
Authoritative Name Server (google.com)
   ↓
IP Address returned to browser
</code></pre>
<p>Once the browser has the IP address, it knows exactly where to send the request.</p>
<p>This entire process typically completes in milliseconds.</p>
<hr />
<h2>Why DNS Caching Matters</h2>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/edd632c9-e549-4fd7-ae7b-210514471753.png" alt="" style="display:block;margin:0 auto" />

<p>Every DNS lookup takes time. If your browser had to repeat this process on every request, the internet would feel noticeably slower.</p>
<p>To solve this, DNS responses are cached at multiple levels:</p>
<ul>
<li><p><strong>Browser cache</strong> — your browser stores recent lookups</p>
</li>
<li><p><strong>Operating system cache</strong> — your OS keeps its own DNS records</p>
</li>
<li><p><strong>ISP cache</strong> — your internet provider caches lookups across all its users</p>
</li>
</ul>
<p>When your browser already knows <code>google.com → 142.250.xxx.xxx</code>, it skips the lookup entirely.</p>
<p>This is why websites often load faster on the second visit.</p>
<hr />
<h2>Why This Matters for System Design</h2>
<p>Most engineers never think about DNS until something breaks.</p>
<p>But DNS sits at the very beginning of every request your users make. Understanding it helps you reason about:</p>
<ul>
<li><p>Why a website becomes unreachable even when your server is running fine</p>
</li>
<li><p>Why DNS outages can take down entire companies</p>
</li>
<li><p>Why latency exists before a request even reaches your application</p>
</li>
<li><p>How traffic gets routed to the correct server across the globe</p>
</li>
</ul>
<p>DNS is also the foundation for more advanced concepts like load balancing, failover, and CDN routing.</p>
<p>Before any of that complexity kicks in, a simple lookup has already happened. Silently. In milliseconds. Every single time.</p>
]]></content:encoded></item><item><title><![CDATA[Event-Driven Architecture: A Practical Guide for Beginners]]></title><description><![CDATA[Most engineers discover Event-Driven Architecture (EDA) through tools first. They hear about Kafka, RabbitMQ, AWS SQS, or Google Cloud Pub/Sub, and immediately want to implement them.
But when designi]]></description><link>https://blog.itsahmadawais.com/event-driven-architecture-a-practical-guide-for-beginners</link><guid isPermaLink="true">https://blog.itsahmadawais.com/event-driven-architecture-a-practical-guide-for-beginners</guid><category><![CDATA[System Design]]></category><category><![CDATA[backend]]></category><category><![CDATA[architecture]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Wed, 24 Jun 2026 06:42:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/330e3113-675a-4521-a633-c2bb17a66838.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most engineers discover <strong>Event-Driven Architecture (EDA)</strong> through tools first. They hear about <strong>Kafka, RabbitMQ, AWS SQS, or Google Cloud Pub/Sub</strong>, and immediately want to implement them.</p>
<p>But when designing scalable backend systems, the real question isn't <em>"Which messaging tool should I use?"</em></p>
<p>The real question is: <strong>"What architectural problem am I actually trying to solve?"</strong></p>
<hr />
<h2>The Monolith Problem: A Simple Example</h2>
<p>Imagine you are building a standard e-commerce application. When a customer clicks "Place Order," several distinct processes need to trigger across your system:</p>
<ul>
<li><p>Save the order details to the database</p>
</li>
<li><p>Send a customer confirmation email</p>
</li>
<li><p>Update the inventory count</p>
</li>
<li><p>Generate a PDF invoice</p>
</li>
<li><p>Notify the warehouse shipping team</p>
</li>
<li><p>Update the real-time analytics dashboard</p>
</li>
</ul>
<p>When building an early-stage <strong>monolith architecture</strong>, many development teams structure the backend code like this:</p>
<pre><code class="language-plaintext">Order Service
 ├── Save Order (Database Write)
 ├── Send Email (SMTP Call)
 ├── Update Inventory (Stock Service)
 ├── Generate Invoice (Billing Service)
 ├── Notify Warehouse (Fulfillment Service)
 └── Update Analytics (Data Pipeline)
</code></pre>
<p>At first, this direct, synchronous approach works perfectly. But as the business grows, more third-party integrations appear, and more microservices are added to the codebase.</p>
<p>Suddenly, the <code>Order Service</code> knows way too much about every other system. A single order placement becomes tightly coupled to multiple external dependencies. If the email provider flakes or the analytics pipeline experiences latency, the entire checkout process chokes or crashes for the user.</p>
<hr />
<h3>Visualizing Tight Coupling in Microservices</h3>
<p>Here is how direct API calls create dependency hell as an application scales:</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/aa14c74d-3ed6-4f5c-b036-0141f7b1bb96.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>The Core Concept: Shifting to Events</h2>
<p>The fundamental rule of clean system design is separation of concerns. The <code>Order Service</code> shouldn't care how the inventory management system works. It shouldn't care how transactional emails are queued, and it definitely shouldn't care how backend analytics are calculated.</p>
<p>Its only job is to process the transaction. Once the order is validated, it should simply state a fact: <strong>An order was placed.</strong></p>
<p>Everything else that happens afterward is just a consequence of that historical event.</p>
<p>This is where <strong>Event-Driven Architecture</strong> completely changes the paradigm. Instead of directly calling five different APIs synchronously, the <code>Order Service</code> broadcasts an immutable message—an <strong>event</strong>—called <code>OrderPlaced</code>.</p>
<p>It drops this message directly into an <strong>Event Bus</strong> (also known as a Message Broker).</p>
<blockquote>
<p>📬 <strong>What is an Event Bus?</strong> Think of it as a digital post office. The Order Service just drops off the mail and leaves. It doesn't care how the mail gets sorted or when it gets delivered; its job is done, allowing it to immediately serve the next customer.</p>
</blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/e136202f-6988-41b5-845e-cb369135f1ca.png" alt="" style="display:block;margin:0 auto" />

<p>Other independent background services subscribe to this specific event channel. Each microservice reacts completely independently. The <code>Order Service</code> doesn't know—and doesn't need to know—who is listening on the other side of the event broker.</p>
<hr />
<h3>Visualizing Asynchronous Event Flow</h3>
<p>By introducing an event bus, we completely decouple the publisher from the consumers:</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/9be2e448-9baa-4ac7-afb2-6c4c84017fac.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Why Companies Adopt Event-Driven Architecture</h2>
<p>When transitioning from a monolith to distributed systems, implementing an event-driven pattern offers four massive advantages for technical teams:</p>
<h3>1. Loose Coupling</h3>
<p>Services become entirely autonomous. The <code>Order Service</code> will never break or experience downtime just because the team managing the <code>Analytics Service</code> pushed a breaking change to their deployment.</p>
<h3>2. Independent Scalability</h3>
<p>Different backend workloads experience different architectural strains. Your data analytics engine might need to process millions of minor tracking events, while your email service only handles a few thousand messages. An event broker allows you to scale the infrastructure for individual components based on their specific resource needs.</p>
<h3>3. Frictionless Integrations</h3>
<p>What happens if your business decides to add a new AI-driven fraud detection service? Instead of modifying, testing, and redeploying the core <code>Order Service</code> code, you simply tell the new fraud detection microservice to subscribe to the existing <code>OrderPlaced</code> event stream.</p>
<h3>4. High Fault Tolerance and Resilience</h3>
<p>If your analytics database crashes or goes offline for maintenance, <strong>user orders can still be placed without interruption.</strong> The event broker safely stores the <code>OrderPlaced</code> messages in a queue. Once the analytics service recovers, it simply picks up right where it left off, processing the backlog without losing a single byte of data.</p>
<hr />
<h2>Event-Driven Architecture vs. Monolith: When Do You Actually Need It?</h2>
<p>A classic mistake made by engineering teams is spinning up a complex Kafka cluster on Day 1. Most software applications do not require the overhead of a distributed event broker initially.</p>
<p>You should realistically consider moving to an <strong>Event-Driven Architecture</strong> only when:</p>
<ul>
<li><p>Multiple distinct systems need to react to the exact same business trigger.</p>
</li>
<li><p>Your external third-party integrations are constantly increasing.</p>
</li>
<li><p>Specific microservices require entirely independent infrastructure scaling.</p>
</li>
<li><p>Tight code coupling is actively slowing down your team's deployment velocity.</p>
</li>
<li><p>Asynchronous processing is perfectly acceptable for the end-user experience.</p>
</li>
</ul>
<blockquote>
<p><strong>Senior Reminder:</strong> Notice that none of these core engineering problems explicitly mention tools like Kafka or RabbitMQ. The architectural bottleneck must appear first; the choice of technology comes second.</p>
</blockquote>
<hr />
<h2>When to Avoid Event-Driven Architecture</h2>
<p>Sometimes, a standard, synchronous HTTP API call is still the best engineering tool for the job. Avoid adding the complexity of an event bus when:</p>
<ul>
<li><p>The application is small, or you are still in the early MVP validation phase.</p>
</li>
<li><p>Your backend workflows are straightforward and linear.</p>
</li>
<li><p>The system demands immediate, synchronous, real-time responses.</p>
</li>
<li><p>The operational complexity of managing queues outweighs any architectural benefit.</p>
</li>
</ul>
<p>Introducing a message broker too early forces your team to manage distributed system bugs (like out-of-order messages, network partitions, and duplicate events) before you actually have a scaling problem.</p>
<hr />
<h3>Visualizing the Complexity Trade-off</h3>
<p>Choosing the right architectural pattern depends entirely on your current scale:</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/a56d2e30-3a86-47ee-9ebd-50db73be3b2e.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>The Senior Engineer Mindset</h2>
<p>Junior/Mid-level developers often ask technical questions centered on tools: <em>"Should we use Kafka or AWS SQS for this project?"</em></p>
<p>Senior engineers shift the focus entirely to the underlying system constraints: <em>"What specific problem are we trying to solve by introducing asynchronous messaging?"</em></p>
<p>Ultimately, <strong>Event-Driven Architecture</strong> isn't about specific technologies. It is an intentional design philosophy focused on reducing system coupling, improving scalability, and allowing backend applications to evolve over time. The technology you pick is just an implementation detail—the structural thinking is what actually matters.</p>
<h3>Final Thought</h3>
<p>Before you introduce complex infrastructure to your stack, ask yourself: <strong>"What breaks tomorrow if we keep this design simple today?"</strong> If the honest answer is "nothing," then the simplest solution is always the best engineering choice.</p>
]]></content:encoded></item><item><title><![CDATA[How Software Systems Evolve: From MVP to Modern Architectures]]></title><description><![CDATA[Most system design discussions jump straight into complex architecture patterns—monoliths, microservices, event-driven systems, and distributed databases.
But in real engineering, systems don’t begin ]]></description><link>https://blog.itsahmadawais.com/how-software-systems-evolve-from-mvp-to-modern-architectures</link><guid isPermaLink="true">https://blog.itsahmadawais.com/how-software-systems-evolve-from-mvp-to-modern-architectures</guid><category><![CDATA[System Design]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[System Design Concepts]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 19 Jun 2026 07:44:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/0b181a40-89a9-46bf-9324-1a641d163630.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most system design discussions jump straight into complex architecture patterns—monoliths, microservices, event-driven systems, and distributed databases.</p>
<p>But in real engineering, systems don’t begin with these decisions. They begin with a simple product idea and an urgent need to ship something quickly.</p>
<p>Systems don’t start as “architectures.” They start simple, and architecture emerges as they scale. Once you see this evolution, each architectural style becomes a practical response to a specific kind of pressure—not just a theoretical choice.</p>
<hr />
<h2>The MVP Phase: Start Simple, Learn Fast</h2>
<p>Every product starts as an MVP (Minimum Viable Product). At this stage, the goal is validation, not technical perfection. You are trying to answer basic business questions:</p>
<ul>
<li><p>Do users actually want this?</p>
</li>
<li><p>Does the product solve a real problem?</p>
</li>
<li><p>What should we build next?</p>
</li>
</ul>
<p>Because of this, teams optimize for fast development cycles, minimal coordination overhead, and rapid iteration.</p>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/1bb7c1e6-7034-4fe8-830d-5ba2d32fa419.jpg" alt="" style="display:block;margin:0 auto" />

<p>Most MVP systems are built as a <strong>monolith</strong>—a single backend codebase, one database, and one single deployment unit where all the core business logic is bundled together.</p>
<blockquote>
<p><strong>Important:</strong> This is not “bad design.” It is the most efficient, pragmatic setup when requirements are still unclear and changing daily.</p>
</blockquote>
<hr />
<h2>Modern Reality: Frontend and Backend Evolve Differently</h2>
<p>Today’s systems are rarely symmetric. The frontend and backend move at different speeds and handle entirely different constraints.</p>
<h3>1. Frontend: Naturally Modular by Default</h3>
<p>Modern frontend systems are inherently modular out of the box. They are built using frameworks like React or Next.js and structured around isolated components, pages, and routes.</p>
<p>They are deployed independently via <strong>CDNs</strong> (Content Delivery Networks—servers distributed globally to deliver files fast) or <strong>edge platforms</strong> that run code closer to the user.</p>
<p>In large-scale companies, this goes even further:</p>
<ul>
<li><p><strong>Micro-frontends:</strong> Splitting the UI so different teams can deploy the checkout page and the user profile completely independently.</p>
</li>
<li><p><strong>BFF (Backend-for-Frontend) layers:</strong> A tiny, custom API layer built specifically to format data nicely for the mobile app or web app, saving the frontend from making ten different API calls.</p>
</li>
</ul>
<p>In practice, because of modern deployment tools, the frontend often behaves like a distributed system much earlier than the backend does.</p>
<h3>2. Backend: Stability and Consistency First</h3>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/1f8f45ac-1318-4ba1-9319-9ec70969c213.jpg" alt="" style="display:block;margin:0 auto" />

<p>Backends evolve more conservatively because they hold the keys to the castle: data consistency, core business logic, and transactions.</p>
<p>Most backend systems start with frameworks like Python (Django, FastAPI), Node.js (Express, NestJS), or Java (Spring Boot). They remain monolithic longer because <strong>debugging distributed systems is incredibly hard.</strong> Operational overhead increases the second you add more servers, and early-stage teams are usually too small to handle that complexity.</p>
<p>So, while the frontend becomes modular early on, the backend typically stays centralized until real scaling pressure forces a change.</p>
<hr />
<h2>When the Monolith Starts to Break</h2>
<p>As systems grow, the monolith starts showing friction. This isn't because it was poorly designed; it’s because the context has changed.</p>
<h3>Common signals of system strain:</h3>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/f337320e-eab9-4904-8cc9-8c86b31933e4.jpg" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Team Friction:</strong> Multiple teams are stepping on each other's toes inside the exact same codebase, causing constant git merge conflicts.</p>
</li>
<li><p><strong>Deployment Bottlenecks:</strong> A tiny bug fix in the shipping module requires testing and redeploying the entire system, making deployments slow and risky.</p>
</li>
<li><p><strong>Scaling Inefficiency:</strong> The video processing feature needs massive CPU power, but because it’s trapped inside the monolith, you have to duplicate the <em>entire</em> backend on expensive servers just to scale that one feature.</p>
</li>
</ul>
<p>At this point, architectural changes stop being an academic preference. They become a survival necessity.</p>
<hr />
<h2>The 5 Stages of Architecture Evolution</h2>
<img src="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/167fbacb-34c7-47a4-ba89-ed0cf2610363.jpg" alt="" style="display:block;margin:0 auto" />

<p>Real systems rarely jump straight from a simple monolith to a massively complex Google-level microservices cluster. Instead, they progress through gradual stepping stones:</p>
<ul>
<li><p><strong>1. The Monolith (MVP Stage):</strong> A single codebase and database. It’s the fastest, cheapest way to validate an idea and ship.</p>
</li>
<li><p><strong>2. The Modular Monolith:</strong> The system is still deployed as one single unit, but the code inside is strictly separated into clean, isolated domains (e.g., the <code>Payment</code> code cannot directly access the <code>Inventory</code> database tables without a formal internal interface). This makes it incredibly easy to maintain and refactor later.</p>
</li>
<li><p><strong>3. The Service Extraction Phase:</strong> The team takes one specific, high-strain domain (like video processing or payment handling) and splits it out into its own independent service, while leaving the rest of the application inside the core monolith.</p>
</li>
<li><p><strong>4. Microservices Architecture:</strong> The system becomes a collection of highly autonomous, independent services with separate databases and separate deployments. This unlocks massive team speed but requires mature DevOps, deep monitoring, and infrastructure automation.</p>
</li>
<li><p><strong>5. Event-Driven Systems:</strong> Instead of services calling each other directly and waiting for a response (which creates a chain of dependencies), they communicate asynchronously by publishing events to an event broker like <strong>Kafka</strong> or <strong>RabbitMQ</strong>. Components become completely decoupled.</p>
</li>
</ul>
<hr />
<h2>What Real Systems Look Like Today</h2>
<p>In production, <strong>most successful companies run hybrid architectures, not pure textbook patterns.</strong> A typical modern setup looks like a mix of everything:</p>
<ul>
<li><p><strong>Frontend:</strong> React / Next.js apps deployed independently on the edge.</p>
</li>
<li><p><strong>Backend:</strong> A solid modular monolith handling 80% of the standard business logic, with 2 or 3 isolated microservices handles high-scale domains.</p>
</li>
<li><p><strong>Async Layer:</strong> A message queue or event broker (like Kafka or AWS SQS) handling background tasks.</p>
</li>
<li><p><strong>Data Layer:</strong> A combination of PostgreSQL for core user data, Redis for fast caching, and Elasticsearch for fast text searching.</p>
</li>
</ul>
<p>This hybrid nature is completely intentional. Real systems evolve pragmatically—not ideologically.</p>
<hr />
<h2>The Key Takeaway</h2>
<p>Architecture is not a static choice you make on Day 1 and live with forever. It is a continuous response to scaling pressure, team structures, and system complexity.</p>
<p>Instead of asking: <em>“Which architecture should I use?”</em></p>
<p>A much better, more senior question is: <strong>“Where is the system creating friction today, and what is the smallest structural change I can make to reduce it?”</strong></p>
<p>This exact mindset is what separates theoretical system design knowledge from real-world engineering judgment.</p>
]]></content:encoded></item><item><title><![CDATA[Building Reliable LLM Systems: From API Calls to Distributed Systems]]></title><description><![CDATA[Traditional software is predictable. You type something in, and you get the exact same result out every single time. Your database works, your code runs, and everything behaves.
But the moment you add]]></description><link>https://blog.itsahmadawais.com/building-reliable-llm-systems-from-api-calls-to-distributed-systems</link><guid isPermaLink="true">https://blog.itsahmadawais.com/building-reliable-llm-systems-from-api-calls-to-distributed-systems</guid><category><![CDATA[AI]]></category><category><![CDATA[AI development]]></category><category><![CDATA[distributed system]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Tue, 26 May 2026 06:30:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/656a14b0e1cbf742022775ae/0ffd0e57-bf6a-43ba-8e11-d855f455ef9f.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Traditional software is predictable. You type something in, and you get the exact same result out every single time. Your database works, your code runs, and everything behaves.</p>
<p>But the moment you add an AI model (like an LLM) to your app, that predictability breaks. You aren't calling a standard piece of code anymore; you are dealing with a system that guesses the next word.</p>
<p>That changes how you have to build your software.</p>
<hr />
<h2>The Big Shift: "Using AI" vs. "Engineering AI Systems"</h2>
<p>When most developers start out, they just make a simple API call:</p>
<pre><code class="language-python">response = llm.generate(prompt)
</code></pre>
<p>It looks like a normal function, but in the real world, LLMs behave like a messy external service. At scale, they bring a lot of headaches:</p>
<ul>
<li><p><strong>They freeze or time out:</strong> Responses can take seconds or fail entirely.</p>
</li>
<li><p><strong>They break rules:</strong> They make things up (hallucinate) or send back bad data formats.</p>
</li>
<li><p><strong>They get expensive:</strong> High traffic can lead to massive, unexpected bills.</p>
</li>
</ul>
<p>Moving from a basic demo to a real product means you have to stop treating AI like a simple function and start treating it like unpredictable infrastructure.</p>
<hr />
<h2>How LLMs Compare to Traditional Software</h2>
<p>Because AI models are unpredictable, you have to build your system assuming they <em>will</em> fail.</p>
<p>Here is how standard tech compares to AI tech:</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Standard API</th>
<th>AI Model (LLM)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Results</strong></td>
<td>Same every time</td>
<td>Changes slightly every time</td>
</tr>
<tr>
<td><strong>Output Type</strong></td>
<td>Clean, structured data</td>
<td>Raw text or messy data</td>
</tr>
<tr>
<td><strong>Speed</strong></td>
<td>Fast and predictable</td>
<td>Slow and random</td>
</tr>
<tr>
<td><strong>Testing</strong></td>
<td>Easy (Right vs. Wrong)</td>
<td>Hard (Needs grading)</td>
</tr>
</tbody></table>
<hr />
<h2>How to Fix "Retry Storms"</h2>
<p>When an LLM takes too long, a basic app will immediately try calling it again. If that fails, it tries again.</p>
<p>Before you know it, one user request turns into dozens of automatic retries:</p>
<pre><code class="language-plaintext">1 Request → 3 Retries → 9 Retries → 27 Retries
</code></pre>
<p>If thousands of users are on your app, your system will accidentally flood the AI provider with traffic. This makes the outage worse and gets your account blocked.</p>
<h3>The Fix: Wait and Stagger</h3>
<p>Instead of retrying immediately, smart systems do two things:</p>
<ol>
<li><p><strong>Back off:</strong> Wait a bit longer between each try (like 1 second, then 2 seconds, then 4 seconds).</p>
</li>
<li><p><strong>Add Jitter (Randomness):</strong> Don't let every computer retry at the exact same second. Make them wait a random amount of time (like 3.2 seconds or 4.5 seconds). This spreads out the traffic so your servers don't crash all at once.</p>
</li>
</ol>
<hr />
<h2>Why You Need Message Queues</h2>
<p>In a basic app, a user clicks a button and waits on the screen while the AI thinks. If the AI is slow, the whole app grinds to a halt.</p>
<p>To fix this, companies use <strong>Message Queues</strong> (like Amazon SQS or RabbitMQ). Think of it like a waiting line at a fast-food restaurant:</p>
<pre><code class="language-plaintext">User Request → Waiting Line (Queue) → Workers → AI Processes It → Saved to Database
</code></pre>
<p>Instead of making the user stare at a loading spinner, the app takes the request, puts it in line, and lets background workers handle the AI processing. This protects your app from crashing when traffic spikes.</p>
<hr />
<h2>Real-Time vs. Batch: When to Use Which</h2>
<p>You don't need to run every single AI task instantly. Splitting your tasks saves money and keeps your app fast.</p>
<h3>Real-Time AI</h3>
<ul>
<li><p><strong>Best for:</strong> Chatbots, live helpers, typing assistants.</p>
</li>
<li><p><strong>The Catch:</strong> It’s hard to keep fast, and expensive when a lot of people use it at once.</p>
</li>
</ul>
<h3>Batch AI (In Groups)</h3>
<ul>
<li><p><strong>Best for:</strong> Summarizing long files overnight, sorting data, creating search tags.</p>
</li>
<li><p><strong>The Benefit:</strong> It’s way cheaper, handles errors gracefully, and runs when your servers are quiet.</p>
</li>
</ul>
<hr />
<h2>The Core Problem: Speed vs. Quality vs. Cost</h2>
<p>With normal code, making it faster doesn't make it more expensive. With AI, everything is connected in a three-way balancing act:</p>
<p>$$\text{Speed} \longleftrightarrow \text{Quality} \longleftrightarrow \text{Cost}$$</p>
<ul>
<li><p>If you want <strong>better quality</strong>, you need a bigger model, which is <strong>slower</strong> and <strong>costs more</strong>.</p>
</li>
<li><p>If you want it <strong>cheaper</strong>, you use a smaller model, but the <strong>quality drops</strong>.</p>
</li>
<li><p>If your app slows down by even half a second, requests pile up, your servers work harder, and your bill goes up.</p>
</li>
</ul>
<hr />
<h2>Testing and Monitoring AI Is Way Harder</h2>
<p>If a normal app breaks, it usually throws a clear error code (like <code>404 Not Found</code>).</p>
<p>An AI app can look like it worked perfectly, give you a successful code, but send back completely wrong information or broken text.</p>
<h3>Watching the App</h3>
<p>You can't just check if your servers are turned on. You have to track:</p>
<ul>
<li><p>Which version of the prompt you used.</p>
</li>
<li><p>How many words (tokens) the AI spent.</p>
</li>
<li><p>How often the AI sends back broken data.</p>
</li>
</ul>
<h3>Testing the Code</h3>
<p>You can't use simple math tests anymore. You can't write a test that says <code>2 + 2 must equal 4</code>. Instead, you have to write tests that check if the answer "looks reasonable." Dealing with these gray areas is the hardest part of building with AI today.</p>
<hr />
<h2>Conclusion</h2>
<p>The hardest part of building an AI company isn't writing a clever prompt or picking the best model.</p>
<p>The real challenge is building a stable system that doesn't crash when the AI gets slow, expensive, or weird. The future belongs to engineers who can build reliable apps using unpredictable tools.</p>
]]></content:encoded></item><item><title><![CDATA[How to Build a GraphQL API with Node.js, Express.js, and MongoDB]]></title><description><![CDATA[GraphQL has become a powerful alternative to traditional REST APIs. It provides a flexible and efficient way to interact with data through a single endpoint. In this tutorial, I'll guide you through the process of setting up a GraphQL server using No...]]></description><link>https://blog.itsahmadawais.com/how-to-build-a-graphql-api-with-nodejs-expressjs-and-mongodb</link><guid isPermaLink="true">https://blog.itsahmadawais.com/how-to-build-a-graphql-api-with-nodejs-expressjs-and-mongodb</guid><category><![CDATA[GraphQL with Mongo DB]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express.js]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[REST API]]></category><category><![CDATA[Hasura]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sun, 19 Jan 2025 10:42:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737283299455/ed65e612-e642-4ed6-9494-05223d95d75e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>GraphQL has become a powerful alternative to traditional REST APIs. It provides a flexible and efficient way to interact with data through a single endpoint. In this tutorial, I'll guide you through the process of setting up a GraphQL server using <strong>Node.js</strong>, <strong>Express.js</strong>, and <strong>MongoDB</strong>.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>Before we dive into the code, here’s what you should already know:</p>
<ul>
<li><p><strong>Node.js</strong></p>
</li>
<li><p><strong>Express.js</strong></p>
</li>
<li><p><strong>MongoDB</strong></p>
</li>
</ul>
<p>If you’re not familiar with any of these, just make sure they’re installed on your machine and you're ready to go.</p>
<h3 id="heading-step-1-set-up-the-project"><strong>Step 1: Set Up the Project</strong></h3>
<p>Let’s start by creating a new directory for the project and initializing a Node.js application.</p>
<ol>
<li><p><strong>Create a directory</strong> for the project:</p>
<pre><code class="lang-bash"> mkdir graphql-node-express-mongo
</code></pre>
</li>
<li><p><strong>Navigate</strong> into the directory:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> graphql-node-express-mongo
</code></pre>
</li>
<li><p><strong>Initialize the npm project</strong>:</p>
<pre><code class="lang-bash"> npm init -y
</code></pre>
</li>
</ol>
<p>Now we’ll install the dependencies to set up the Express server, connect to MongoDB, and provide GraphQL capabilities:</p>
<pre><code class="lang-bash">npm install express express-graphql graphql mongoose dotenv
</code></pre>
<ul>
<li><p><strong>express</strong>: Web framework for Node.js.</p>
</li>
<li><p><strong>express-graphql</strong>: Middleware to integrate GraphQL with Express.</p>
</li>
<li><p><strong>graphql</strong>: The core GraphQL library.</p>
</li>
<li><p><strong>mongoose</strong>: ODM (Object Data Modeling) library for MongoDB.</p>
</li>
<li><p><strong>dotenv</strong>: Helps load environment variables from a <code>.env</code> file.</p>
</li>
</ul>
<h3 id="heading-step-2-setting-up-mongodb"><strong>Step 2: Setting Up MongoDB</strong></h3>
<p>If you don’t have MongoDB set up yet, here’s what to do:</p>
<ul>
<li><p>For <strong>local MongoDB</strong>, install it and start the MongoDB server.</p>
</li>
<li><p>For <strong>MongoDB Atlas</strong> (cloud), create a free cluster and grab your connection string.</p>
</li>
</ul>
<p>Once you have the connection string, create a <code>.env</code> file in the root folder and add the MongoDB URI:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># .env</span>
MONGO_DB_URI = <span class="hljs-string">"&lt;Your MongoDB Connection String&gt;"</span>
</code></pre>
<p>This will ensure your MongoDB credentials are kept secure.</p>
<h3 id="heading-step-3-create-the-graphql-schema"><strong>Step 3: Create the GraphQL Schema</strong></h3>
<p>Next, we’ll define the GraphQL schema. Create a new file called <code>schema.js</code> in the root of your project.</p>
<h4 id="heading-define-the-mongodb-schema">Define the MongoDB Schema</h4>
<p>Let’s start with a simple <strong>User model</strong> for MongoDB.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// models/User.js</span>
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> userSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
  <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">email</span>: <span class="hljs-built_in">String</span>,
});

<span class="hljs-keyword">const</span> User = mongoose.model(<span class="hljs-string">'User'</span>, userSchema);

<span class="hljs-built_in">module</span>.exports = User;
</code></pre>
<h4 id="heading-define-the-graphql-schema">Define the GraphQL Schema</h4>
<p>Now, let’s create the GraphQL schema, including queries and mutations.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// schema.js</span>
<span class="hljs-keyword">const</span> { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLList } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'graphql'</span>);
<span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./models/User'</span>);

<span class="hljs-comment">// Define the GraphQL User Type</span>
<span class="hljs-keyword">const</span> UserType = <span class="hljs-keyword">new</span> GraphQLObjectType({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'User'</span>,
  <span class="hljs-attr">fields</span>: <span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">id</span>: { <span class="hljs-attr">type</span>: GraphQLString },
    <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: GraphQLString },
    <span class="hljs-attr">email</span>: { <span class="hljs-attr">type</span>: GraphQLString },
  }),
});

<span class="hljs-comment">// Root Query to fetch users</span>
<span class="hljs-keyword">const</span> RootQuery = <span class="hljs-keyword">new</span> GraphQLObjectType({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'RootQueryType'</span>,
  <span class="hljs-attr">fields</span>: {
    <span class="hljs-attr">users</span>: {
      <span class="hljs-attr">type</span>: <span class="hljs-keyword">new</span> GraphQLList(UserType),
      resolve(parent, args) {
        <span class="hljs-keyword">return</span> User.find(); <span class="hljs-comment">// Fetch all users from MongoDB</span>
      },
    },
    <span class="hljs-attr">user</span>: {
      <span class="hljs-attr">type</span>: UserType,
      <span class="hljs-attr">args</span>: { <span class="hljs-attr">id</span>: { <span class="hljs-attr">type</span>: GraphQLString } },
      resolve(parent, args) {
        <span class="hljs-keyword">return</span> User.findById(args.id); <span class="hljs-comment">// Fetch a user by ID</span>
      },
    },
  },
});

<span class="hljs-comment">// Mutation to add a new user</span>
<span class="hljs-keyword">const</span> Mutation = <span class="hljs-keyword">new</span> GraphQLObjectType({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Mutation'</span>,
  <span class="hljs-attr">fields</span>: {
    <span class="hljs-attr">addUser</span>: {
      <span class="hljs-attr">type</span>: UserType,
      <span class="hljs-attr">args</span>: {
        <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: GraphQLString },
        <span class="hljs-attr">email</span>: { <span class="hljs-attr">type</span>: GraphQLString },
      },
      resolve(parent, args) {
        <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">new</span> User({
          <span class="hljs-attr">name</span>: args.name,
          <span class="hljs-attr">email</span>: args.email,
        });
        <span class="hljs-keyword">return</span> user.save(); <span class="hljs-comment">// Save the new user to MongoDB</span>
      },
    },
  },
});

<span class="hljs-comment">// Create the GraphQL Schema</span>
<span class="hljs-keyword">const</span> schema = <span class="hljs-keyword">new</span> GraphQLSchema({
  <span class="hljs-attr">query</span>: RootQuery,
  <span class="hljs-attr">mutation</span>: Mutation,
});

<span class="hljs-built_in">module</span>.exports = schema;
</code></pre>
<h3 id="heading-step-4-set-up-the-express-server"><strong>Step 4: Set Up the Express Server</strong></h3>
<p>Now, let’s wire everything up by setting up the <strong>Express server</strong> and <strong>GraphQL middleware</strong>. Create a file called <code>server.js</code> in your project’s root folder.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// server.js</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);
<span class="hljs-keyword">const</span> { graphqlHTTP } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express-graphql'</span>);
<span class="hljs-keyword">const</span> dotenv = <span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>);
<span class="hljs-keyword">const</span> schema = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./schema'</span>);

<span class="hljs-comment">// Load environment variables from the .env file</span>
dotenv.config();

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Connect to MongoDB</span>
mongoose.connect(process.env.MONGO_DB_URI, {
  <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">useUnifiedTopology</span>: <span class="hljs-literal">true</span>,
})
  .then(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'MongoDB connected'</span>))
  .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err));

<span class="hljs-comment">// Set up the GraphQL endpoint</span>
app.use(<span class="hljs-string">'/graphql'</span>, graphqlHTTP({
  schema,
  <span class="hljs-attr">graphiql</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// Enable GraphiQL for testing queries</span>
}));

<span class="hljs-comment">// Start the server</span>
app.listen(<span class="hljs-number">4000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Server running on http://localhost:4000/graphql'</span>);
});
</code></pre>
<h3 id="heading-step-5-testing-the-graphql-api"><strong>Step 5: Testing the GraphQL API</strong></h3>
<p>Once your server is running, open <a target="_blank" href="http://localhost:4000/graphql"><code>http://localhost:4000/graphql</code></a> in your browser. You should see <strong>GraphiQL</strong>, a web-based IDE for testing GraphQL queries.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737282978495/7d5a6dd0-0855-4eac-a268-a20ff0063f71.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-test-query-fetch-all-users">Test Query: Fetch All Users</h4>
<p>To fetch all users, enter this query in the GraphiQL interface:</p>
<pre><code class="lang-graphql">{
  users {
    name
    email
  }
}
</code></pre>
<h4 id="heading-test-mutation-add-a-new-user">Test Mutation: Add a New User</h4>
<p>To add a new user, run this mutation:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">mutation</span> {
  addUser(<span class="hljs-symbol">name:</span> <span class="hljs-string">"Jane Doe"</span>, <span class="hljs-symbol">email:</span> <span class="hljs-string">"jane.doe@example.com"</span>) {
    name
    email
  }
}
</code></pre>
<p>You should see the newly added user in the response.</p>
<h3 id="heading-step-6-conclusion"><strong>Step 6: Conclusion</strong></h3>
<p>Congratulations! You’ve successfully built a GraphQL API with <strong>Node.js</strong>, <strong>Express.js</strong>, and <strong>MongoDB</strong>. In this tutorial, you’ve learned how to:</p>
<ul>
<li><p>Set up a <strong>MongoDB</strong> connection.</p>
</li>
<li><p>Create <strong>GraphQL queries</strong> and <strong>mutations</strong>.</p>
</li>
<li><p>Set up an <strong>Express server</strong> to serve your GraphQL API.</p>
</li>
</ul>
<p>This is just the beginning. You can now expand your API by adding authentication, pagination, or more complex queries and mutations.</p>
<h3 id="heading-next-steps"><strong>Next Steps:</strong></h3>
<ul>
<li><p>Implement <strong>authentication</strong> (e.g., using JWT tokens).</p>
</li>
<li><p>Add <strong>pagination</strong> for handling large data sets.</p>
</li>
<li><p>Deploy your application to services like <strong>Vercel</strong> or <strong>AWS</strong> for production.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Fixing 404 Errors on Vercel: How to Deploy a TypeScript Express.js Node.js App]]></title><description><![CDATA[Vercel is widely popular for deploying applications, and while it's quite simple to deploy frontend apps or basic Node.js applications, deploying backend apps with TypeScript and Express.js can be a bit tricky. During a recent deployment of a TypeScr...]]></description><link>https://blog.itsahmadawais.com/fixing-404-errors-on-vercel-how-to-deploy-a-typescript-expressjs-nodejs-app</link><guid isPermaLink="true">https://blog.itsahmadawais.com/fixing-404-errors-on-vercel-how-to-deploy-a-typescript-expressjs-nodejs-app</guid><category><![CDATA[Deploy Typescript Express.js App]]></category><category><![CDATA[Express]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Vercel]]></category><category><![CDATA[deployment]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Tue, 14 Jan 2025 07:36:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736839802963/046a9cd0-849b-4655-a14c-f4c5c71429f3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Vercel is widely popular for deploying applications, and while it's quite simple to deploy frontend apps or basic Node.js applications, deploying backend apps with TypeScript and Express.js can be a bit tricky. During a recent deployment of a TypeScript Express.js app on Vercel, I encountered a 404 error that I couldn't find a proper solution for—especially since I was using module aliases for the backend. However, after considerable effort, I managed to resolve the issue, and in this article, I will guide you on how to seamlessly deploy your TypeScript Express.js app on Vercel.</p>
<h4 id="heading-common-issue-404-errors-on-deployment">Common Issue: 404 Errors on Deployment</h4>
<p>Sometimes, even after deploying your app on Vercel, you may still encounter a 404 error. This could happen due to several reasons such as incorrect configurations, API routes not being recognized, or module alias issues. Let’s walk through how to avoid these issues and deploy your app smoothly.</p>
<hr />
<h3 id="heading-step-1-initialize-a-typescript-expressjs-project">Step 1: Initialize a TypeScript Express.js Project</h3>
<p>First, you need to initialize your TypeScript Express.js project.</p>
<ol>
<li><p><strong>Initialize the project</strong>:</p>
<pre><code class="lang-bash"> npm init -y
</code></pre>
</li>
<li><p><strong>Install dependencies</strong> for TypeScript and Express:</p>
<pre><code class="lang-bash"> npm install express
 npm install typescript @types/node @types/express --save-dev
</code></pre>
</li>
<li><p><strong>Set up</strong> <code>tsconfig.json</code>:<br /> This file will configure how TypeScript compiles your project.</p>
<p> Create a <code>tsconfig.json</code> file:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"compilerOptions"</span>: {
     <span class="hljs-attr">"target"</span>: <span class="hljs-string">"ES2020"</span>,
     <span class="hljs-attr">"module"</span>: <span class="hljs-string">"commonjs"</span>,
     <span class="hljs-attr">"esModuleInterop"</span>: <span class="hljs-literal">true</span>,
     <span class="hljs-attr">"allowSyntheticDefaultImports"</span>: <span class="hljs-literal">true</span>,
     <span class="hljs-attr">"noImplicitAny"</span>: <span class="hljs-literal">true</span>,
     <span class="hljs-attr">"moduleResolution"</span>: <span class="hljs-string">"node"</span>,
     <span class="hljs-attr">"sourceMap"</span>: <span class="hljs-literal">true</span>,
     <span class="hljs-attr">"outDir"</span>: <span class="hljs-string">"dist"</span>,
     <span class="hljs-attr">"baseUrl"</span>: <span class="hljs-string">"."</span>,
     <span class="hljs-attr">"paths"</span>: {
       <span class="hljs-attr">"*"</span>: [
         <span class="hljs-string">"node_modules/*"</span>,
         <span class="hljs-string">"src/types/*"</span>
       ]
     }
   }
 }
</code></pre>
</li>
<li><p><strong>Add mandatory scripts</strong> in <code>package.json</code>: In your <code>package.json</code>, you’ll need to add the following scripts:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"scripts"</span>: {
     <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node dist/server.js"</span>,
     <span class="hljs-attr">"build"</span>: <span class="hljs-string">"tsc"</span>,
     <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"nodemon src/server.ts"</span>
   }
 }
</code></pre>
</li>
</ol>
<hr />
<h3 id="heading-step-2-set-up-the-vercel-configuration">Step 2: Set Up the Vercel Configuration</h3>
<p>Now, let's configure the Vercel deployment.</p>
<ol>
<li><p><strong>Create a</strong> <code>vercel.json</code> file:<br /> This configuration file tells Vercel how to build and route your app. Here's an example configuration:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"version"</span>: <span class="hljs-number">2</span>,
   <span class="hljs-attr">"builds"</span>: [
     {
       <span class="hljs-attr">"src"</span>: <span class="hljs-string">"dist/server.js"</span>,
       <span class="hljs-attr">"use"</span>: <span class="hljs-string">"@vercel/node"</span>
     }
   ],
   <span class="hljs-attr">"routes"</span>: [
     {
       <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/(.*)"</span>,
       <span class="hljs-attr">"dest"</span>: <span class="hljs-string">"dist/server.js"</span>
     }
   ],
   <span class="hljs-attr">"buildCommand"</span>: <span class="hljs-string">"npm run build"</span>,
   <span class="hljs-attr">"outputDirectory"</span>: <span class="hljs-string">"dist"</span>
 }
</code></pre>
<p> <strong>Explanation</strong>:</p>
<ul>
<li><p><code>builds</code>: Defines the build process and points to the <code>dist/server.js</code> file.</p>
</li>
<li><p><code>routes</code>: Routes incoming requests to <code>dist/server.js</code>.</p>
</li>
<li><p><code>buildCommand</code>: The command that Vercel uses to build the app (<code>npm run build</code>).</p>
</li>
<li><p><code>outputDirectory</code>: Specifies that Vercel should look in the <code>dist</code> directory for the final build output.</p>
</li>
</ul>
</li>
</ol>
<hr />
<h3 id="heading-step-3-handle-module-aliases">Step 3: Handle Module Aliases</h3>
<pre><code class="lang-json"><span class="hljs-comment">//package.json</span>
{
    ...,
    <span class="hljs-attr">"_moduleAliases"</span>: {
        <span class="hljs-attr">"@"</span>: <span class="hljs-string">"dist"</span>
    },
    ...
}
</code></pre>
<p>If you're using module aliases, especially with paths like <code>"@": "dist"</code>, Vercel may not recognize them during the build process. To resolve this:</p>
<ol>
<li><p><strong>Install</strong> <code>tsc-alias</code>: This tool helps decouple the aliases during the build process.</p>
<pre><code class="lang-bash"> npm install tsc-alias --save-dev
</code></pre>
</li>
<li><p><strong>Update the</strong> <code>build</code> script in <code>package.json</code> to use <code>tsc-alias</code>:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"scripts"</span>: {
     <span class="hljs-attr">"build"</span>: <span class="hljs-string">"tsc &amp;&amp; tsc-alias"</span>
   }
 }
</code></pre>
<p> This ensures that after TypeScript compiles your project, <code>tsc-alias</code> will replace any aliases with the correct paths.</p>
</li>
</ol>
<hr />
<h3 id="heading-step-4-deploying-to-vercel">Step 4: Deploying to Vercel</h3>
<p>Once your project is set up, it's time to deploy it to Vercel.</p>
<ol>
<li><p><strong>Push your code to GitHub</strong>:<br /> Make sure your project is pushed to a GitHub repository.</p>
</li>
<li><p><strong>Link your GitHub project with Vercel</strong>:</p>
<ul>
<li><p>Go to the <a target="_blank" href="https://vercel.com">Vercel dashboard</a>.</p>
</li>
<li><p>Click on “New Project” and import your GitHub repository.</p>
</li>
<li><p>Set “Framework Preset” to “Other”.</p>
</li>
</ul>
</li>
<li><p><strong>Deployment</strong>:</p>
<ul>
<li><p>After linking your project, Vercel will begin the build process and deploy the app.</p>
</li>
<li><p>If everything is configured correctly, you should be able to access your app at the provided Vercel URL.</p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736839934766/0150c63a-be2c-4f49-a22d-817c6fcaa29e.png" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-step-5-troubleshooting-404-errors">Step 5: Troubleshooting 404 Errors</h3>
<p>Sometimes, you may still encounter 404 errors after deployment. Here are a few things to check:</p>
<ol>
<li><p><strong>Incorrect File Paths</strong>:<br /> Ensure that the file paths are correctly specified in your <code>vercel.json</code> file, especially the entry point (<code>dist/server.js</code>).</p>
</li>
<li><p><strong>Missing API Endpoints</strong>:<br /> Verify that all your API routes are properly defined and exported from your <code>server.ts</code> file.</p>
</li>
<li><p><strong>Serverless Function Issues</strong>:<br /> Vercel treats each API endpoint as a serverless function. Ensure that the structure of your app matches the expected serverless function format (i.e., files in the <code>/api</code> directory).</p>
</li>
<li><p><strong>TypeScript Build Errors</strong>:<br /> If you made any changes to the TypeScript configuration, run <code>npm run build</code> locally to check for any errors before deploying.</p>
</li>
</ol>
<hr />
<h3 id="heading-conclusion">Conclusion</h3>
<p>Deploying a TypeScript Express.js app on Vercel can be a smooth experience once you understand the configuration and handling of module aliases. In this article, we covered the essential steps to set up your TypeScript Express.js app, handle build issues, and deploy it to Vercel while fixing common 404 errors. By following this guide, you should be able to deploy your app seamlessly to Vercel and ensure that it works as expected.</p>
<p>Happy deploying!</p>
]]></content:encoded></item><item><title><![CDATA[Tokenization with React.js: Creating Scalable Design Systems for Modern Applications]]></title><description><![CDATA[Creating scalable, maintainable, and efficient applications is a core goal in today's web development landscape. With the rise of design systems, developers need a robust method to manage design elements that work seamlessly across various platforms....]]></description><link>https://blog.itsahmadawais.com/tokenization-with-reactjs-creating-scalable-design-systems-for-modern-applications</link><guid isPermaLink="true">https://blog.itsahmadawais.com/tokenization-with-reactjs-creating-scalable-design-systems-for-modern-applications</guid><category><![CDATA[React]]></category><category><![CDATA[Tokenization]]></category><category><![CDATA[Design Systems]]></category><category><![CDATA[styled-components]]></category><category><![CDATA[UI]]></category><category><![CDATA[ui ux designer]]></category><category><![CDATA[UI Design]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sat, 04 Jan 2025 19:31:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736018984226/b4eedfe0-3c07-4dd8-aedd-5b562572cace.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Creating scalable, maintainable, and efficient applications is a core goal in today's web development landscape. With the rise of design systems, developers need a robust method to manage design elements that work seamlessly across various platforms. Tokenization is one such method that simplifies the process and enhances collaboration between design and development teams. In this article, we will dive into tokenization, how it can be implemented in React.js, and the best practices for building scalable design systems.</p>
<h2 id="heading-what-is-tokenization">What is Tokenization?</h2>
<p>In the context of design systems, <strong>tokenization</strong> refers to the practice of converting design properties (such as colors, typography, spacing, etc.) into reusable, consistent values called tokens. These tokens act as the building blocks of the design system, providing a way to maintain visual consistency across an application, even as it grows in size and complexity.</p>
<p>Design tokens are typically abstracted into a centralized file or configuration and can represent:</p>
<ul>
<li><p><strong>Colors</strong> (primary, secondary, background, etc.)</p>
</li>
<li><p><strong>Typography</strong> (font sizes, line heights, font families)</p>
</li>
<li><p><strong>Spacing</strong> (margins, paddings, etc.)</p>
</li>
<li><p><strong>Borders, Shadows, and Other UI Elements</strong></p>
</li>
</ul>
<p>Tokens allow design teams to maintain a single source of truth for the design elements, making the application easier to scale and maintain over time.</p>
<p><a target="_blank" href="https://www.itsahmadawais.com/#contact"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736017864554/30ddfe22-2f5d-4aa9-8bf2-dc29a4730aef.png" alt class="image--center mx-auto" /></a></p>
<h2 id="heading-examples-of-famous-apps-that-use-tokenization">Examples of Famous Apps That Use Tokenization</h2>
<p>Many large-scale applications have adopted tokenization to build consistent, scalable design systems. Here are some examples of famous companies using tokenization:</p>
<ul>
<li><p><strong>Spotify</strong>: The music streaming giant uses design tokens in its design system to ensure consistency in UI elements such as buttons, typography, and branding, making their design adaptable across devices.</p>
</li>
<li><p><strong>Shopify</strong>: Shopify’s Polaris design system leverages tokenization to maintain consistent visual styles, allowing developers and designers to work together efficiently.</p>
</li>
<li><p><strong>IBM's Carbon Design System</strong>: IBM uses tokens to define key design properties across their applications, ensuring uniformity in user experience across various platforms.</p>
</li>
<li><p><strong>Salesforce Lightning</strong>: Salesforce’s design system uses tokens to maintain visual consistency in its cloud services, providing a solid foundation for rapid feature development.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736007912403/9a48e2d5-ce6e-41d1-8d39-8313e90f40f2.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-why-tokenization-matters">Why Tokenization Matters</h2>
<p>Tokenization plays a vital role in maintaining consistency, speeding up development, and enhancing collaboration across teams. Here are several reasons why tokenization is important:</p>
<h3 id="heading-1-consistency-across-platforms">1. <strong>Consistency Across Platforms</strong></h3>
<p>Tokens ensure that the same design properties (e.g., colors, typography) are used consistently across multiple platforms and devices. This makes it easier to deliver a cohesive user experience regardless of the environment.</p>
<h3 id="heading-2-faster-iterations">2. <strong>Faster Iterations</strong></h3>
<p>When design tokens are centralized, making changes becomes much faster. For instance, changing the color of a primary button or adjusting spacing can be done by simply modifying a value in the token file, and it will automatically propagate throughout the app.</p>
<h3 id="heading-3-improved-collaboration">3. <strong>Improved Collaboration</strong></h3>
<p>Designers and developers can work more seamlessly with a shared understanding of design tokens. This reduces the chances of inconsistencies and errors in the implementation of visual elements, enhancing teamwork and communication.</p>
<h3 id="heading-4-scalability">4. <strong>Scalability</strong></h3>
<p>As applications grow, maintaining visual consistency can become a complex task. Tokenization makes it easier to scale design systems by ensuring that design updates can be applied globally without affecting individual components or layouts.</p>
<h3 id="heading-5-maintainability">5. <strong>Maintainability</strong></h3>
<p>By keeping all design-related properties in one centralized location, tokenization makes it easier to maintain and update the design system, especially as the product evolves or new features are added.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736013758206/2bc2bf06-d791-44e7-b257-f9f285ad37f0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-implementing-tokenization-in-reactjs">Implementing Tokenization in React.js</h2>
<p>Implementing tokenization in a React.js project involves defining your design tokens and then using them within your React components. Here's a step-by-step guide to getting started:</p>
<h3 id="heading-step-1-set-up-the-react-project">Step 1: Set Up the React Project</h3>
<p>Begin by setting up a React.js project using TypeScript for better type safety and maintainability. You can easily create a new project using Create React App or Vite.</p>
<pre><code class="lang-bash">npx create-react-app my-app --template typescript
</code></pre>
<h3 id="heading-step-2-define-design-tokens">Step 2: Define Design Tokens</h3>
<p>Design tokens are typically stored in a JavaScript or TypeScript object, or in a JSON file. Here’s an example of a theme file with defined tokens for colors, spacing, and typography:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// src/theme.ts</span>
<span class="hljs-keyword">const</span> theme = {
  colors: {
    primary: <span class="hljs-string">"#6200ee"</span>,
    secondary: <span class="hljs-string">"#03dac6"</span>,
    background: <span class="hljs-string">"#ffffff"</span>,
  },
  spacing: {
    small: <span class="hljs-string">"8px"</span>,
    medium: <span class="hljs-string">"16px"</span>,
    large: <span class="hljs-string">"24px"</span>,
  },
  typography: {
    fontSize: <span class="hljs-string">"16px"</span>,
    fontFamily: <span class="hljs-string">"'Roboto', sans-serif"</span>,
  },
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> theme;
</code></pre>
<h3 id="heading-step-3-use-tokens-in-components">Step 3: Use Tokens in Components</h3>
<p>Now that you have defined the tokens, you can use them within styled components. Here's an example of a <code>Button</code> component that uses the tokens for styling:</p>
<pre><code class="lang-tsx">// src/components/Button.tsx
import React from 'react';
import styled from 'styled-components';
import theme from '../theme';

const Button = styled.button`
  background-color: ${theme.colors.primary};
  padding: ${theme.spacing.medium};
  color: #fff;
  font-size: ${theme.typography.fontSize};
  border: none;
  border-radius: 4px;
  cursor: pointer;
`;

const ButtonComponent: React.FC = () =&gt; {
  return &lt;Button&gt;Click Me&lt;/Button&gt;;
};

export default ButtonComponent;
</code></pre>
<h3 id="heading-step-4-dynamic-theming-lightdark-mode">Step 4: Dynamic Theming (Light/Dark Mode)</h3>
<p>To support multiple themes (e.g., light and dark mode), you can use React Context or CSS variables. Below is an example of how you might toggle themes using React Context:</p>
<pre><code class="lang-tsx">// src/context/ThemeContext.tsx
import React, { createContext, useState, ReactNode } from 'react';

type Theme = 'light' | 'dark';

interface ThemeContextType {
  theme: Theme;
  toggleTheme: () =&gt; void;
}

const ThemeContext = createContext&lt;ThemeContextType | undefined&gt;(undefined);

const ThemeProvider: React.FC&lt;{ children: ReactNode }&gt; = ({ children }) =&gt; {
  const [theme, setTheme] = useState&lt;Theme&gt;('light');

  const toggleTheme = () =&gt; {
    setTheme((prevTheme) =&gt; (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    &lt;ThemeContext.Provider value={{ theme, toggleTheme }}&gt;
      {children}
    &lt;/ThemeContext.Provider&gt;
  );
};

export { ThemeProvider, ThemeContext };
</code></pre>
<h2 id="heading-best-practices-for-tokenization-in-reactjs">Best Practices for Tokenization in React.js</h2>
<p>To ensure your tokenization strategy is effective, follow these best practices:</p>
<ul>
<li><p><strong>Clear and Consistent Naming</strong>: Use clear and descriptive names for your tokens. For example, use <code>primary-color</code> rather than <code>color1</code> for better clarity and understanding.</p>
</li>
<li><p><strong>Modularize Tokens</strong>: Organize your tokens into logical groups (e.g., colors, typography, spacing) to keep them modular and maintainable. This allows for easier updates and scaling.</p>
</li>
<li><p><strong>Use Tools for Token Management</strong>: Tools like <a target="_blank" href="https://github.com/amzn/style-dictionary">Style Dictionary</a> and <a target="_blank" href="https://github.com/salesforce-ux/theo">Theo</a> can help automate the process of generating and managing design tokens.</p>
</li>
<li><p><strong>Document Tokens</strong>: Proper documentation is crucial. Keep a reference guide to help developers and designers understand how to use the tokens in their workflow.</p>
</li>
<li><p><strong>Ensure Accessibility</strong>: When defining colors, check for accessibility standards like sufficient contrast between text and background colors.</p>
</li>
</ul>
<p><a target="_blank" href="https://www.itsahmadawais.com/#contact"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736012485900/ad64d367-11c7-48c7-9ab5-46ef86f50222.png" alt class="image--center mx-auto" /></a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Tokenization is a powerful technique for creating scalable, maintainable, and consistent design systems. By abstracting design properties into reusable tokens, you can improve the development process, enhance collaboration, and make it easier to scale your applications. When implemented in React.js, tokenization allows developers to create visually consistent user interfaces with minimal effort, enabling faster iterations and greater flexibility.</p>
<h2 id="heading-call-to-action">Call to Action</h2>
<p>Want to implement tokenization in your next project? Let’s connect! Whether you're starting from scratch or looking to integrate tokenization into an existing React.js project, I can help you build a scalable design system that suits your needs.</p>
<p><a target="_blank" href="https://www.itsahmadawais.com/#contact"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736006567685/496f6d2e-e31c-48fa-97ef-1da9dedd2639.png" alt class="image--center mx-auto" /></a></p>
]]></content:encoded></item><item><title><![CDATA[Understanding Image Classification: Basics and Benefits]]></title><description><![CDATA[Image classification is a key technology in the field of artificial intelligence (AI) and machine learning. It helps computers understand and identify objects in images, which is useful in many areas of life. This article will explain what image clas...]]></description><link>https://blog.itsahmadawais.com/understanding-image-classification-basics-and-benefits</link><guid isPermaLink="true">https://blog.itsahmadawais.com/understanding-image-classification-basics-and-benefits</guid><category><![CDATA[AI]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[image processing]]></category><category><![CDATA[image classification]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[machine learning models]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sun, 15 Sep 2024 07:20:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726384746871/17099637-5dd8-4bcb-b225-73a580a997af.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Image classification is a key technology in the field of artificial intelligence (AI) and machine learning. It helps computers understand and identify objects in images, which is useful in many areas of life. This article will explain what image classification is, how it works, and why it is important.</p>
<h2 id="heading-what-is-image-classification"><strong>What is Image Classification?</strong></h2>
<p>Image classification is the process of teaching a computer to recognize and categorize objects within an image. For example, a computer can learn to distinguish between pictures of cats, dogs, and birds. This ability to categorize images helps in automating tasks that involve visual data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726353372729/6e250dd8-83e2-4752-beeb-a5592fe33699.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-does-image-classification-work"><strong>How Does Image Classification Work?</strong></h2>
<ol>
<li><p><strong>Collecting Data:</strong> The first step in image classification is gathering a large set of images. These images must be labeled correctly to teach the computer what each image represents.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726354870853/b58aa46a-1017-47fb-882b-cc6762ca4b4a.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Training the Model:</strong> Using a special kind of AI model called a neural network, the computer learns from the labeled images. During training, the model examines each image and tries to understand the features that define each category.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726355405599/25db9a75-7835-44a7-9b20-742fbe826e6e.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Testing the Model:</strong> After training, the model is tested with new images it hasn't seen before. This helps to check if the model can accurately classify these new images.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726356435829/7e281773-cad2-4b05-93fd-d978bbb4831a.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Making Predictions:</strong> Once the model is trained and tested, it can be used to make predictions on new images. For example, you can show it a picture of a cat, and it will tell you if the image contains a cat or not.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726356092553/5415b1ec-fd51-44bf-90a5-ba15029ffffe.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-applications-of-image-classification"><strong>Applications of Image Classification</strong></h2>
<p>Image classification has many practical uses in our daily lives. Some of the common applications include:</p>
<ul>
<li><p><strong>Healthcare:</strong> Identifying diseases from medical images.</p>
</li>
<li><p><strong>Security:</strong> Recognizing faces for security purposes.</p>
</li>
<li><p><strong>Retail:</strong> Sorting and organizing products in stores.</p>
</li>
<li><p><strong>Social Media:</strong> Tagging people in photos automatically.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726384022064/37596704-c974-401f-8f95-df5ab89605af.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-why-is-image-classification-important"><strong>Why is Image Classification Important?</strong></h2>
<p>Image classification helps in many ways, making processes faster and more efficient. It reduces the need for manual work and allows computers to handle large amounts of visual data quickly. This technology is advancing rapidly and continues to make significant impacts in various fields.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726384434395/91360dd5-cad8-43ec-914a-22a0f859ec51.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Image classification is a powerful tool in AI that enables computers to recognize and categorize images. By understanding how it works and its applications, we can appreciate how it contributes to various aspects of our lives. As technology continues to evolve, image classification will play an even greater role in shaping our world.</p>
]]></content:encoded></item><item><title><![CDATA[Scalable Data Storage: Which Database is Right for You?]]></title><description><![CDATA[In today’s data-driven world, selecting the right database is crucial for the success of data-centric applications. With the explosion of data and the increasing need for scalable solutions, it’s more important than ever to make an informed choice. T...]]></description><link>https://blog.itsahmadawais.com/scalable-data-storage-which-database-is-right-for-you</link><guid isPermaLink="true">https://blog.itsahmadawais.com/scalable-data-storage-which-database-is-right-for-you</guid><category><![CDATA[Databases]]></category><category><![CDATA[data]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[cockroachdb]]></category><category><![CDATA[SQL]]></category><category><![CDATA[NoSQL]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sat, 07 Sep 2024 22:41:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725748779926/b4bd61eb-fdad-4937-98e2-f916832dc417.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In today’s data-driven world, selecting the right database is crucial for the success of data-centric applications. With the explosion of data and the increasing need for scalable solutions, it’s more important than ever to make an informed choice. This article will guide you through understanding the various scalable data storage solutions and help you choose the best database for your application’s needs.</p>
<h2 id="heading-understanding-scalable-data-storage">Understanding Scalable Data Storage</h2>
<p>Scalable data storage solutions are designed to handle increasing amounts of data efficiently. They ensure that as your data grows, the system can scale without compromising performance or reliability. Scalability can be achieved through various methods, including horizontal scaling (adding more machines) and vertical scaling (upgrading existing machines).</p>
<h2 id="heading-types-of-databases">Types of Databases</h2>
<h3 id="heading-1-rlational-databases-rdbms"><strong>1. Rlational Databases (RDBMS)</strong></h3>
<p>Relational databases, such as MySQL, PostgreSQL, and Microsoft SQL Server, are known for their structured data storage using tables with defined relationships. They are ideal for applications requiring complex queries, transactions, and data integrity.</p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Strong consistency and reliability.</p>
</li>
<li><p>Support for complex queries and transactions.</p>
</li>
<li><p>Mature technology with extensive community and support.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Scaling vertically can be expensive.</p>
</li>
<li><p>Less flexible for handling unstructured data.</p>
</li>
</ul>
<h3 id="heading-2-nosql-databases"><strong>2. NoSQL Databases</strong></h3>
<p>NoSQL databases like MongoDB, Cassandra, and Couchbase are designed to handle unstructured or semi-structured data. They offer flexibility in data modeling and are optimized for high performance and scalability.</p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Horizontal scaling capabilities.</p>
</li>
<li><p>Flexibility in data modeling.</p>
</li>
<li><p>Better suited for large-scale, distributed systems.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>May lack strong consistency models.</p>
</li>
<li><p>Limited support for complex queries and transactions.</p>
</li>
</ul>
<h3 id="heading-3-newsql-databases"><strong>3. NewSQL Databases</strong></h3>
<p>NewSQL databases, such as Google Spanner and CockroachDB, combine the best features of traditional RDBMS and NoSQL databases. They provide scalability and performance while maintaining SQL compatibility.</p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>High scalability with SQL-like query capabilities.</p>
</li>
<li><p>Strong consistency and support for ACID transactions.</p>
</li>
<li><p>Good for applications requiring both scalability and transactional integrity.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Emerging technology with varying maturity levels.</p>
</li>
<li><p>Can be complex to set up and manage.</p>
</li>
</ul>
<h2 id="heading-choosing-the-right-database">Choosing the Right Database</h2>
<p>Selecting the appropriate database for your application depends on various factors, including the nature of your data, performance requirements, and scalability needs.</p>
<ol>
<li><p><strong>Data Structure</strong></p>
<ul>
<li><p><strong>Structured Data:</strong> If your application primarily deals with structured data and requires complex queries and transactions, a relational database might be the best choice.</p>
</li>
<li><p><strong>Unstructured Data:</strong> For applications handling large volumes of unstructured or semi-structured data, NoSQL databases offer the flexibility and scalability needed.</p>
</li>
</ul>
</li>
<li><p><strong>Scalability Requirements</strong></p>
<ul>
<li><p><strong>Horizontal Scalability:</strong> If you anticipate significant growth and need to scale out across multiple servers, consider NoSQL databases or NewSQL solutions.</p>
</li>
<li><p><strong>Vertical Scalability:</strong> For applications that can benefit from upgrading existing hardware, traditional RDBMS might suffice.</p>
</li>
</ul>
</li>
<li><p><strong>Consistency vs. Availability</strong></p>
<ul>
<li><p><strong>Strong Consistency:</strong> If your application requires strong consistency and ACID transactions, RDBMS and some NewSQL databases are suitable.</p>
</li>
<li><p><strong>Availability and Partition Tolerance:</strong> If your application prioritizes availability and can tolerate eventual consistency, NoSQL databases might be more appropriate.</p>
</li>
</ul>
</li>
<li><p><strong>Performance Needs</strong></p>
<ul>
<li><strong>High Throughput and Low Latency:</strong> For applications requiring high performance and low latency, NoSQL databases or NewSQL solutions can provide the necessary speed and efficiency.</li>
</ul>
</li>
<li><p><strong>Cost Considerations</strong></p>
<ul>
<li><strong>Infrastructure Costs:</strong> Consider the costs of scaling your infrastructure, whether vertically or horizontally, and choose a database that aligns with your budget and scaling strategy.</li>
</ul>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Choosing the right database for your data-centric application is a critical decision that impacts performance, scalability, and overall success. By understanding the strengths and limitations of different types of databases, you can make an informed choice that aligns with your application's specific needs. Whether you opt for a traditional RDBMS, a flexible NoSQL database, or a modern NewSQL solution, the key is to ensure that your database choice supports your application's growth and performance requirements effectively.</p>
]]></content:encoded></item><item><title><![CDATA[Top AI Trends to Watch in 2024: What Beginners Should Know]]></title><description><![CDATA[Hey developers! If you're curious about AI but haven't jumped in yet, you're in the right place. AI is becoming one of the most exciting areas in tech, and 2024 is full of opportunities for everyone, whether you're experienced or just starting out. N...]]></description><link>https://blog.itsahmadawais.com/top-ai-trends-to-watch-in-2024-what-beginners-should-know</link><guid isPermaLink="true">https://blog.itsahmadawais.com/top-ai-trends-to-watch-in-2024-what-beginners-should-know</guid><category><![CDATA[AI]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[automation]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Sun, 18 Aug 2024 16:28:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723996637728/f8206874-d6b6-4aa3-9ff8-be1faa55da37.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey developers! If you're curious about AI but haven't jumped in yet, you're in the right place. AI is becoming one of the most exciting areas in tech, and 2024 is full of opportunities for everyone, whether you're experienced or just starting out. Now is the perfect time to see what AI can do.</p>
<p>In this article, we’ll cover the top AI trends to watch in 2024. Don’t worry—these trends are easy to understand, and they’re for anyone interested in how AI is changing technology and how you can start exploring it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723996330159/bbd08e67-10b5-47c0-a7d4-22c670453f03.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-generative-ai-creativity-at-your-fingertips">Generative AI: Creativity at Your Fingertips</h2>
<p>Imagine being able to create content—like images, music, or even code—just by typing a few words. That's the power of Generative AI, and it's one of the hottest trends right now. Tools like OpenAI's ChatGPT and DALL·E are leading the charge, making it easier than ever to generate creative outputs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723996747017/8db131fb-1338-4e1b-90ee-417cb6990f81.png" alt class="image--center mx-auto" /></p>
<p><strong>Note:</strong> DALL-E is not allowing new users but if you want to use this feature, you can switch to a ChatGPT Plus account.</p>
<p><strong>Why You Should Care:</strong><br />Generative AI is perfect for automating creative tasks. If you’re a developer who loves tinkering with code but isn't much of an artist, generative AI can help you create stunning visuals or even write content for you.</p>
<p><strong>How to Get Started:</strong><br />Check out platforms like OpenAI's Playground, where you can experiment with generating text and images with minimal setup. It's super beginner-friendly!</p>
<h2 id="heading-2-ai-powered-automation-more-time-to-code">2. AI-Powered Automation: More Time to Code</h2>
<p>Automation isn’t new, but AI is taking it to the next level. Think beyond basic scripts—AI can now handle complex tasks like data analysis, customer service, and even software testing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723997859647/b5dddf15-017c-4b9e-8ea1-43cf73551872.png" alt class="image--center mx-auto" /></p>
<p><strong>Why You Should Care:</strong><br />As developers, we’re always looking for ways to save time. AI-powered automation lets you focus on the fun stuff (like coding new features) while the AI handles the repetitive tasks.</p>
<p><strong>How to Get Started:</strong><br />Look into tools like <strong>Zapier</strong> or <strong>UiPath</strong>, which offer AI-driven automation that’s easy to set up, even if you don’t have a lot of experience with AI.</p>
<h2 id="heading-3-ai-in-healthcare-code-that-saves-lives">3. AI in Healthcare: Code That Saves Lives</h2>
<p>AI is making waves in healthcare, and it’s not just hype. From diagnosing diseases to personalizing treatments, AI is revolutionizing the way we approach medicine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723997996081/6c455964-774e-4b95-85de-9fe870b7ec33.png" alt class="image--center mx-auto" /></p>
<p><strong>Why You Should Care:</strong><br />Healthcare is one of the most impactful areas where AI can make a difference. If you're looking to work on projects that have a real-world impact, healthcare AI is a field to watch.</p>
<p><strong>How to Get Started:</strong><br />Explore datasets like those from <strong>Kaggle’s</strong> healthcare competitions. They’re a great way to practice building AI models that solve real-world problems.</p>
<h2 id="heading-4-ai-powered-personalization-making-users-happy">4. AI-Powered Personalization: Making Users Happy</h2>
<p>Ever wonder how Netflix knows exactly what you want to watch next? That’s AI-powered personalization in action. In 2024, this trend is only going to get bigger, as companies use AI to tailor experiences to individual users.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723998211378/4bcd0d4b-bc2a-4255-b8e6-99eff8c2e2ad.png" alt class="image--center mx-auto" /></p>
<p><strong>Why You Should Care:</strong><br />Personalization can drastically improve user experience, which is key to keeping users engaged with your apps or websites.</p>
<p><strong>How to Get Started:</strong><br />Try out recommendation engine APIs like those from Amazon or Google. They’re easy to integrate into your projects and can give you a feel for how AI-powered personalization works.</p>
<h2 id="heading-5-ai-for-everyone-the-rise-of-no-code-ai">5. AI for Everyone: The Rise of No-Code AI</h2>
<p>Finally, let’s talk about accessibility. AI is becoming more user-friendly, thanks to no-code and low-code platforms. These tools allow you to build AI models without needing deep programming skills.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723998648340/d77004f9-7220-4df4-bcd0-41859e1ba960.png" alt class="image--center mx-auto" /></p>
<p><strong>Why You Should Care:</strong><br />No-code AI platforms democratize AI, making it accessible to everyone. If you're just starting out, these tools are a fantastic way to begin your AI journey without getting bogged down in the technical details.</p>
<p><strong>How to Get Started:</strong><br />Platforms like Teachable Machine and RunwayML let you create AI models with simple drag-and-drop interfaces. Give them a try to see how easy AI can be!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>And there you have it—some of the top AI trends to keep an eye on in 2024. Whether you're interested in automation, ethical AI, or just want to start experimenting with no-code platforms, there's something here for everyone. The world of AI is expanding fast, and now’s the perfect time to get involved.</p>
<p>So, what are you waiting for? Dive in and start exploring these trends. Who knows, maybe your next project will be powered by AI!</p>
]]></content:encoded></item><item><title><![CDATA[Ultimate Guide to Learning React.js with ChatGPT and OpenAI]]></title><description><![CDATA[React.js is a popular JavaScript library for building user interfaces and has become an essential tool for modern web development. If you are getting started or know very little about React, this article explores the right approach to master it with ...]]></description><link>https://blog.itsahmadawais.com/ultimate-guide-to-learning-reactjs-with-chatgpt-and-openai</link><guid isPermaLink="true">https://blog.itsahmadawais.com/ultimate-guide-to-learning-reactjs-with-chatgpt-and-openai</guid><category><![CDATA[Learn React.js]]></category><category><![CDATA[React]]></category><category><![CDATA[coding]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[AI]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[#codingNewbies]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 02 Aug 2024 14:23:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/8qEB0fTe9Vw/upload/83624c3263e47c128b527015ae092095.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>React.js is a popular JavaScript library for building user interfaces and has become an essential tool for modern web development. If you are getting started or know very little about React, this article explores the right approach to master it with the use of ChatGPT.</p>
<h2 id="heading-why-learn-with-ai">Why learn with AI?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722606738211/4d69d4d2-a26a-414c-80f4-d6030b7f0895.png" alt class="image--center mx-auto" /></p>
<p>AI has become an essential tool in today's world. Before the arrival of AI tools like ChatGPT and Gemini, the learning curve for developers involved learning new concepts, encountering problems, and searching for solutions on Google or StackOverflow. However, with the arrival of AI tools, this learning curve has transformed. Developers now prefer to type their problems into ChatGPT and receive code solutions directly. But here's a question, Is this a threat to developers that AI can code and replace developers?</p>
<p>As someone beautifully said:</p>
<blockquote>
<p>"AI cannot replace labors and human-work completely, but people using AI can perform better at their jobs and work."</p>
</blockquote>
<p>It's now up to you whether you want to embrace this trend and learn with AI or just sit back and believe that AI can do everything. Even though AI has improved significantly over the years, you still need to provide it with instructions to perform specific tasks.</p>
<h2 id="heading-chatgpt-a-powerful-learning-tool">ChatGPT: A Powerful Learning Tool</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722607008068/dec1d27b-db0d-434d-a40b-89a3b7842461.png" alt class="image--center mx-auto" /></p>
<p>Since most programming languages share common attributes, with differences primarily in syntax and folder structure for libraries and frameworks, learning them becomes easier. You can use ChatGPT to get help with various topics - whether you need a course outline for React.js, have a code problem that needs solving, or are looking for ideas. ChatGPT is a valuable tool for assistance and guidance.</p>
<h2 id="heading-learning-react-with-chatgpt">Learning React with ChatGPT</h2>
<p>Learning React is not straightforward where you master it in one hour and then immediately build a top-notch website. You'll need to start with the basics first.</p>
<p>Pre-requisites:</p>
<ul>
<li><p>HTML</p>
</li>
<li><p>CSS</p>
</li>
<li><p>JavaScript</p>
</li>
</ul>
<p>You must have foundational knowledge of HTML, CSS, and Javascript before you learn React.js.</p>
<h3 id="heading-starting-with-course-outline">Starting with Course Outline</h3>
<p>Getting a course outline is the crucial step before you start learning anything or even before reading a book. We can generate an outline using ChaGPT but I won't recommend it if you're an absolute beginner, you will be lost with a lot of topics that might not be important at the moment. However, you can learn the following topics one by one and practice them on CodeSandbox, which we will learn later about CodeSandbox:</p>
<ul>
<li><p>Creating a Project with CodeSandbox</p>
</li>
<li><p>JSX, JSX vs HTML</p>
</li>
<li><p>Components and Types</p>
<ul>
<li><p>Functional Components</p>
</li>
<li><p>Class Components (Just Overview)</p>
</li>
</ul>
</li>
<li><p>Props</p>
</li>
<li><p>States</p>
</li>
<li><p>Event Handling</p>
</li>
<li><p>Conditional Rendering</p>
</li>
<li><p>Rendering Lists</p>
</li>
<li><p>Component Life Cycle Methods</p>
</li>
<li><p>Hooks - Introduction to hooks</p>
<ul>
<li><p>useState</p>
</li>
<li><p>useEffect</p>
</li>
<li><p>useRef</p>
</li>
</ul>
</li>
<li><p>Styling in React</p>
<ul>
<li><p>Inline Styling</p>
</li>
<li><p>Using CSS Classes</p>
</li>
</ul>
</li>
</ul>
<p>Alternatively, if you want to create your own outline using ChatGPT, type the following prompt:</p>
<blockquote>
<p>"I want to learn React.js. Generate me an outline to learn it step by step."</p>
</blockquote>
<p>ChaGPT will generate an outline for you. The response can be varied based on your prompt.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722581367499/80ee38f3-6717-47ea-8350-c571ebe5b0d4.png" alt class="image--center mx-auto" /></p>
<p>For our prompt, the outline begins with "<strong>Fundamentals of JavaScript ES6</strong>". If you do not have foundational knowledge in JavaScript, HTML, and CSS, make sure to learn those first before diving into React.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722581320285/340362c9-64f0-40e4-9e0f-e375e3416a75.png" alt class="image--center mx-auto" /></p>
<p>In the second part, the outline starts with React. It recommends starting with the basics of React and then learning topics such as React components, event handling, conditional rendering, and more.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722581346815/a2170d67-6309-4115-a5d0-34d80a7dd8d5.png" alt class="image--center mx-auto" /></p>
<p>The outline generated by ChatGPT is wonderful. However, we want to learn fast by eliminating the non-mandatory topics, for now, we we can follow my suggested list.</p>
<h3 id="heading-creating-reactjs-app-with-codesandbox">Creating React.js App with CodeSandbox</h3>
<p>CodeSandbox is an excellent tool for developing applications in the cloud. It removes the need to set up a local environment, enabling you to code, run, and develop your apps entirely online.</p>
<p>Visit <a target="_blank" href="https://codesandbox.io/">https://codesandbox.io/</a> and sign in. If you haven't registered yet, you'll need to create an account first.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722608811131/1a985725-58a6-44b2-9565-89845f6a96e3.png" alt class="image--center mx-auto" /></p>
<p>Once your account is ready, select <strong>Sandbox</strong> from the top bar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722582575275/7932fcca-9db6-46d9-9218-2e75038bef1a.png" alt class="image--center mx-auto" /></p>
<p>You will see a list of templates to choose from. Select the first one labeled "React."</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722582587098/36e3bd47-b44d-43b7-ba6f-2de21927cabf.png" alt class="image--center mx-auto" /></p>
<p>Once you've selected the template, you'll be prompted to enter configurations, such as the Sandbox Name. Click the <strong>"Create Sandbox"</strong> button to proceed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722583111610/672de1a0-ee08-45f9-b7f9-44216627147b.png" alt class="image--center mx-auto" /></p>
<p>It will set up the project for you.</p>
<ul>
<li><p><strong>Explorer:</strong> It shows all the files and available folders. Initially it will you the default project files and folders.</p>
</li>
<li><p><strong>Content Editor:</strong> Whichever file you select to edit, will show in the content editor section.</p>
</li>
<li><p><strong>Live Preview:</strong> Whatever changes you make, it will show you in real time.</p>
</li>
</ul>
<p>The entry file for the project will be <strong>index.js</strong>. However, you the entry</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722586067356/76b59d35-8bf0-4940-bd26-e25dc72535bc.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-learning-the-topics-use-chatgpt">Learning the topics: Use ChatGPT</h3>
<p><strong>JSX and JSX vs HTML</strong></p>
<p>As the first React.js - related topic in our list is <strong>"JSX and JSX vs HTML"</strong>, let's type the following prompt on ChatGPT and learn it:</p>
<blockquote>
<p>"What's JSX? What's the difference between HTML and JSX?"</p>
</blockquote>
<p>ChatGPT can provide quick insights on the topic you're learning about. If you find the answer is not relevant, you can re-generate the response or adjust your prompt to request a more concise answer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722606038323/333ec349-f8d4-44f6-9f7a-b7c4401e0b20.png" alt class="image--center mx-auto" /></p>
<p>For the answer, ChatGPT also provides examples to demonstrate the differences between HTML and JSX. In case it does not provide any example, you can type a prompt to request an example as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722606050300/c9d98c25-f612-40c8-a891-507f95bebf8f.png" alt class="image--center mx-auto" /></p>
<p>The next topic in the list is components.</p>
<p><strong>Component</strong></p>
<p>Let's type the following prompt to ask ChatGPT to answer it:</p>
<blockquote>
<p>"What are components in React.js? Discuss its types. Give examples."</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722606256320/980dc08b-3a98-4830-b9ce-2ac12857e68c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722606274881/01318bfb-b988-4a10-abe7-4a0737bf91f4.png" alt class="image--center mx-auto" /></p>
<p>Similarly, you can search for other topics while practicing on CodeSandbox. If you find that you do not understand a topic, you can always adjust your prompt to get a concise, clearer, and more relevant answer.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In today’s rapidly evolving world of AI, the learning curve for developers has changed significantly. To take full advantage of these advancements, it's crucial to learn how to work with popular AI tools like ChatGPT to enhance your learning experience.</p>
]]></content:encoded></item><item><title><![CDATA[A Beginner's Guide to Using Git and GitHub: Commands and Usage]]></title><description><![CDATA[Git and GitHub have become essential tools for developers, enabling collaboration, version control, and project management. However, for beginners, navigating Git commands and GitHub usage can seem daunting. In this article, we'll provide a beginner-...]]></description><link>https://blog.itsahmadawais.com/a-beginners-guide-to-using-git-and-github-commands-and-usage</link><guid isPermaLink="true">https://blog.itsahmadawais.com/a-beginners-guide-to-using-git-and-github-commands-and-usage</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[version control]]></category><category><![CDATA[Gitcommands]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 09 Feb 2024 11:41:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/LG8ToawE8WQ/upload/be801c219de54a47d8257fe338bf32b4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Git and GitHub have become essential tools for developers, enabling collaboration, version control, and project management. However, for beginners, navigating Git commands and GitHub usage can seem daunting. In this article, we'll provide a beginner-friendly guide to understanding Git commands and using GitHub effectively.</p>
<h2 id="heading-what-is-git"><strong>What is Git?</strong></h2>
<p>Git is a distributed version control system designed to track changes in source code during software development. It allows multiple developers to collaborate on projects, keeping track of changes, and managing different versions of code.</p>
<h3 id="heading-key-concepts-in-git"><strong>Key Concepts in Git:</strong></h3>
<p>Before diving into Git commands, it's essential to understand some key concepts:</p>
<ol>
<li><p><strong>Repository (Repo):</strong> A repository is a collection of files and folders, along with their revision history. It's the central storage location for a project.</p>
</li>
<li><p><strong>Commit:</strong> A commit is a snapshot of changes made to files in a repository. It represents a specific version of the project at a given point in time.</p>
</li>
<li><p><strong>Branch:</strong> A branch is a parallel version of the codebase, allowing developers to work on features or fixes independently without affecting the main codebase.</p>
</li>
<li><p><strong>Pull Request (PR):</strong> A pull request is a proposed change submitted by a developer to merge their code changes into the main branch of a repository.</p>
</li>
</ol>
<h2 id="heading-basic-git-commands"><strong>Basic Git Commands:</strong></h2>
<pre><code class="lang-bash"><span class="hljs-comment"># Initialize a new Git repository</span>
git init

<span class="hljs-comment"># Clone a remote repository to your local machine</span>
git <span class="hljs-built_in">clone</span> [repository_url]

<span class="hljs-comment"># Add changes to the staging area before committing</span>
git add [file_name]

<span class="hljs-comment"># Commit changes with a descriptive message</span>
git commit -m <span class="hljs-string">"commit_message"</span>

<span class="hljs-comment"># Push committed changes to a remote repository</span>
git push

<span class="hljs-comment"># Fetch changes from a remote repository and merge them into the current branch</span>
git pull

<span class="hljs-comment"># List all branches in the repository</span>
git branch

<span class="hljs-comment"># Switch to a different branch</span>
git checkout [branch_name]

<span class="hljs-comment"># Merge changes from one branch into another</span>
git merge [branch_name]
</code></pre>
<h2 id="heading-github-usage"><strong>GitHub Usage:</strong></h2>
<p>GitHub is a web-based platform built on top of Git, providing additional features for collaboration and project management.</p>
<ol>
<li><p><strong>Create a Repository:</strong> Click on the "New" button to create a new repository on GitHub. Give it a name, description, and choose visibility settings.</p>
</li>
<li><p><strong>Clone Repository:</strong> Use the "Clone or download" button to copy the repository URL. Then, use the <code>git clone</code> command to clone the repository to your local machine.</p>
</li>
<li><p><strong>Branches and Pull Requests:</strong> Create branches for new features or fixes using the branch button. After making changes, create a pull request to propose merging your changes into the main branch.</p>
</li>
<li><p><strong>Collaborate:</strong> GitHub allows multiple developers to collaborate on a project by forking repositories, creating issues, and reviewing pull requests.</p>
</li>
<li><p><strong>Explore Projects:</strong> Explore trending repositories, contribute to open-source projects, or showcase your work by creating your profile and repositories.</p>
</li>
</ol>
<h2 id="heading-conclusion"><strong>Conclusion:</strong></h2>
<p>Git and GitHub are powerful tools for version control and collaboration in software development. By understanding basic Git commands and GitHub usage, developers can effectively manage their projects, collaborate with teams, and contribute to open-source communities. Start by practicing the commands mentioned above and exploring GitHub's features to become proficient in using these essential tools.</p>
]]></content:encoded></item><item><title><![CDATA[Arrays in JavaScript - Methods for JavaScript Arrays]]></title><description><![CDATA[Arrays play a fundamental role in JavaScript, offering a versatile and dynamic way to store and manipulate data. In this article, we will delve into the world of JavaScript arrays, focusing on essential array methods that empower developers to effici...]]></description><link>https://blog.itsahmadawais.com/arrays-in-javascript-methods-for-javascript-arrays</link><guid isPermaLink="true">https://blog.itsahmadawais.com/arrays-in-javascript-methods-for-javascript-arrays</guid><category><![CDATA[arrays]]></category><category><![CDATA[array methods]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[javascript array methods]]></category><category><![CDATA[#javascript, #arrays, #programming, #webdevelopment, #JavaScriptmethods, #arraymanipulation, #arrayoperations]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Mon, 11 Dec 2023 18:58:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UYsBCu9RP3Y/upload/13868447707901b7f6467e37bd01fd56.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Arrays play a fundamental role in JavaScript, offering a versatile and dynamic way to store and manipulate data. In this article, we will delve into the world of JavaScript arrays, focusing on essential array methods that empower developers to efficiently handle and transform data.</p>
<h3 id="heading-understanding-javascript-arrays">Understanding JavaScript Arrays</h3>
<p>At its core, an array is a data structure that allows you to store multiple values within a single variable. In JavaScript, arrays can hold various data types, making them incredibly flexible.</p>
<h3 id="heading-creating-arrays">Creating Arrays</h3>
<p>Before we dive into array methods, let's explore how to create arrays in JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Creating an array of numbers</span>
<span class="hljs-keyword">let</span> 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>];

<span class="hljs-comment">// Creating an array of strings</span>
<span class="hljs-keyword">let</span> fruits = [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'orange'</span>, <span class="hljs-string">'banana'</span>];

<span class="hljs-comment">// Creating a mixed-type array</span>
<span class="hljs-keyword">let</span> mixedArray = [<span class="hljs-number">1</span>, <span class="hljs-string">'hello'</span>, <span class="hljs-literal">true</span>, <span class="hljs-literal">null</span>];
</code></pre>
<h3 id="heading-essential-javascript-array-methods">Essential JavaScript Array Methods</h3>
<h4 id="heading-1-push-and-pop">1. <code>push()</code> and <code>pop()</code></h4>
<p>The <code>push()</code> method adds one or more elements to the end of an array, while <code>pop()</code> removes the last element from the array.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> colors = [<span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'blue'</span>];
colors.push(<span class="hljs-string">'yellow'</span>); <span class="hljs-comment">// Adds 'yellow' to the end</span>
<span class="hljs-keyword">let</span> removedColor = colors.pop(); <span class="hljs-comment">// Removes and returns 'blue'</span>
</code></pre>
<h4 id="heading-2-shift-and-unshift">2. <code>shift()</code> and <code>unshift()</code></h4>
<p><code>shift()</code> removes the first element from an array, and <code>unshift()</code> adds one or more elements to the beginning.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> cities = [<span class="hljs-string">'New York'</span>, <span class="hljs-string">'Paris'</span>, <span class="hljs-string">'Tokyo'</span>];
cities.shift(); <span class="hljs-comment">// Removes 'New York'</span>
cities.unshift(<span class="hljs-string">'London'</span>); <span class="hljs-comment">// Adds 'London' to the beginning</span>
</code></pre>
<h4 id="heading-3-slice">3. <code>slice()</code></h4>
<p>The <code>slice()</code> method extracts a portion of an array and returns a new array without modifying the original.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> 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>];
<span class="hljs-keyword">let</span> slicedNumbers = numbers.slice(<span class="hljs-number">1</span>, <span class="hljs-number">4</span>); <span class="hljs-comment">// Returns [2, 3, 4]</span>
</code></pre>
<h4 id="heading-4-splice">4. <code>splice()</code></h4>
<p><code>splice()</code> is used to add or remove elements from a specific index in an array.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> fruits = [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'orange'</span>, <span class="hljs-string">'banana'</span>];
fruits.splice(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-string">'grape'</span>, <span class="hljs-string">'kiwi'</span>); <span class="hljs-comment">// Removes 'orange' and adds 'grape' and 'kiwi'</span>
</code></pre>
<h4 id="heading-5-map">5. <code>map()</code></h4>
<p>The <code>map()</code> method creates a new array by applying a function to each element of the original array.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> 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>];
<span class="hljs-keyword">let</span> doubledNumbers = numbers.map(<span class="hljs-function"><span class="hljs-params">num</span> =&gt;</span> num * <span class="hljs-number">2</span>); <span class="hljs-comment">// Returns [2, 4, 6, 8, 10]</span>
</code></pre>
<h4 id="heading-6-filter">6. <code>filter()</code></h4>
<p><code>filter()</code> creates a new array with elements that pass a specific condition.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> 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>];
<span class="hljs-keyword">let</span> evenNumbers = numbers.filter(<span class="hljs-function"><span class="hljs-params">num</span> =&gt;</span> num % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>); <span class="hljs-comment">// Returns [2, 4]</span>
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>JavaScript array methods provide powerful tools for manipulating data efficiently. By mastering these methods, developers can streamline their code and enhance the functionality of their applications. Whether you're a beginner or an experienced developer, a solid understanding of JavaScript arrays and their methods is crucial for building robust and dynamic web applications.</p>
]]></content:encoded></item><item><title><![CDATA[Difference between controlled and uncontrolled components in React.js]]></title><description><![CDATA[When working with forms in React.js, developers often encounter the terms "controlled components" and "uncontrolled components." These concepts represent two distinct approaches to managing form elements and their states within a React application. I...]]></description><link>https://blog.itsahmadawais.com/difference-between-controlled-and-uncontrolled-components-in-reactjs</link><guid isPermaLink="true">https://blog.itsahmadawais.com/difference-between-controlled-and-uncontrolled-components-in-reactjs</guid><category><![CDATA[React]]></category><category><![CDATA[forms]]></category><category><![CDATA[react js]]></category><category><![CDATA[components]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 08 Dec 2023 17:30:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/OqtafYT5kTw/upload/4ac1904c52b66f7880ca170d56b9f8c5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working with forms in React.js, developers often encounter the terms "controlled components" and "uncontrolled components." These concepts represent two distinct approaches to managing form elements and their states within a React application. In this blog post, we'll delve into the differences between controlled and uncontrolled components, providing insights into when and why you might choose one over the other.</p>
<h2 id="heading-controlled-components">Controlled Components:</h2>
<p>Controlled components in React.js are those in which the state of form elements, such as input fields, checkboxes, and radio buttons, is managed and controlled by React. This is achieved by binding the value of the form elements to the state and updating that state through event handlers, typically the <code>onChange</code> event.</p>
<p>Let's take a look at an example of a controlled component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> ControlledComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [inputValue, setInputValue] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setInputValue(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
      <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
      <span class="hljs-attr">value</span>=<span class="hljs-string">{inputValue}</span>
      <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
    /&gt;</span></span>
  );
};
</code></pre>
<p>In this example, the <code>inputValue</code> state reflects the current value of the input field, and any changes to the input are managed through the <code>handleChange</code> event handler.</p>
<h2 id="heading-uncontrolled-components">Uncontrolled Components:</h2>
<p>On the other hand, uncontrolled components allow form elements to maintain their own state within the DOM, without direct interference from React. The state is managed by the DOM itself, and you can access the values using refs.</p>
<p>Consider the following example of an uncontrolled component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> UncontrolledComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> inputRef = useRef();

  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    alert(<span class="hljs-string">`Input Value: <span class="hljs-subst">${inputRef.current.value}</span>`</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{inputRef}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Get Input Value<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>In this case, the <code>inputRef</code> is used to access the current value of the input field directly from the DOM.</p>
<p>Choosing Between Controlled and Uncontrolled Components:</p>
<p>The decision to use controlled or uncontrolled components depends on the specific requirements of your application.</p>
<ul>
<li><p><strong>Controlled Components:</strong> Use them when you need centralized control over the form elements' state, such as when implementing validation or manipulating input before updating the state.</p>
</li>
<li><p><strong>Uncontrolled Components:</strong> Opt for uncontrolled components when integrating React with non-React code or when you prefer to let the DOM handle the form element state.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion:</h2>
<p>Understanding the distinction between controlled and uncontrolled components in React empowers developers to make informed decisions when building forms. Whether you need fine-grained control over state or prefer a more hands-off approach, React provides the flexibility to choose the best strategy for your application's needs.</p>
]]></content:encoded></item><item><title><![CDATA[Create a Build for Your React.js App]]></title><description><![CDATA[In this blog post, I'll show you how to make a build for your React.js app. But first, you might be wondering: Why bother with a build?
Let's talk about why it's important to create a build for your React.js application.
So, you've finished making yo...]]></description><link>https://blog.itsahmadawais.com/create-a-build-for-your-reactjs-app</link><guid isPermaLink="true">https://blog.itsahmadawais.com/create-a-build-for-your-reactjs-app</guid><category><![CDATA[react.js build]]></category><category><![CDATA[how to create react.js build]]></category><category><![CDATA[npm run build]]></category><dc:creator><![CDATA[Awais Ahmad]]></dc:creator><pubDate>Fri, 01 Dec 2023 17:49:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ieic5Tq8YMk/upload/789e91a6d66b6a53f679d81f0c62fb57.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this blog post, I'll show you how to make a build for your React.js app. But first, you might be wondering: Why bother with a build?</p>
<p>Let's talk about why it's important to create a build for your React.js application.</p>
<p>So, you've finished making your website with React.js, and now it's time to get it online. To do that, you'll need to host the build folder.</p>
<p>Here's a simple step to create build folder: Open your React.js project and just type this command:</p>
<pre><code class="lang-bash">npm run build
</code></pre>
<p>This command does something cool – it makes a new build folder right there in your project. Inside, you'll find all the static files and content ready to roll.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1701452858574/8571ca87-c0e1-4e8c-aa3a-69469f0b6c52.png" alt class="image--center mx-auto" /></p>
<p>Now, let's test it out:</p>
<pre><code class="lang-bash">npm i -g serve  <span class="hljs-comment"># Install the 'serve' package globally</span>
npx serve build  <span class="hljs-comment"># Run the project locally</span>
</code></pre>
<p>This will let you check how your project looks and behaves in action.</p>
]]></content:encoded></item></channel></rss>