<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed Omeiza</title>
    <description>The latest articles on DEV Community by Ahmed Omeiza (@omeiza_ahmed).</description>
    <link>https://dev.to/omeiza_ahmed</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3393350%2F879b446b-2d46-411c-9fbb-1bed737b48fc.png</url>
      <title>DEV Community: Ahmed Omeiza</title>
      <link>https://dev.to/omeiza_ahmed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omeiza_ahmed"/>
    <language>en</language>
    <item>
      <title>Infrastructure as Code (IaC): Stop Managing Infrastructure Manually</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Fri, 16 Oct 2026 07:29:31 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/infrastructure-as-code-iac-stop-managing-infrastructure-manually-2nln</link>
      <guid>https://dev.to/omeiza_ahmed/infrastructure-as-code-iac-stop-managing-infrastructure-manually-2nln</guid>
      <description>&lt;p&gt;Imagine deploying an application to production, only to discover that the server configuration is different from your development environment.&lt;/p&gt;

&lt;p&gt;The application works perfectly locally, but fails in production.&lt;/p&gt;

&lt;p&gt;Why? Because someone forgot to configure a firewall rule, install a dependency, or update an environment variable.&lt;/p&gt;

&lt;p&gt;This is one of the problems &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; solves.&lt;/p&gt;

&lt;p&gt;Instead of manually configuring servers, databases, networks, and cloud resources, you define your infrastructure using code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Infrastructure as Code?
&lt;/h2&gt;

&lt;p&gt;Infrastructure as Code (IaC) is the practice of provisioning and managing infrastructure through machine-readable configuration files rather than manual processes.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Traditional Infrastructure Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log into your cloud provider.&lt;/li&gt;
&lt;li&gt;Create a virtual machine.&lt;/li&gt;
&lt;li&gt;Configure networking and security rules.&lt;/li&gt;
&lt;li&gt;Set up databases and storage.&lt;/li&gt;
&lt;li&gt;Repeat the process for every environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure as Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define your infrastructure in configuration files.&lt;/li&gt;
&lt;li&gt;Store those files in Git.&lt;/li&gt;
&lt;li&gt;Apply the configuration using an IaC tool.&lt;/li&gt;
&lt;li&gt;Automatically provision the required resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The infrastructure becomes reproducible, version-controlled, and easier to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Infrastructure as Code Work?
&lt;/h2&gt;

&lt;p&gt;IaC tools read configuration files describing the infrastructure you want and interact with cloud provider APIs to create or modify the required resources.&lt;/p&gt;

&lt;p&gt;For example, using Terraform, you can define an AWS S3 bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"app_storage"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-unique-app-storage-bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After configuring the AWS provider and your credentials, you can execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
terraform plan
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;terraform init&lt;/code&gt; initializes the working directory and downloads providers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform plan&lt;/code&gt; previews the proposed infrastructure changes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform apply&lt;/code&gt; applies the approved changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of manually creating the bucket through the AWS console, Terraform manages it using configuration files.&lt;/p&gt;

&lt;p&gt;And when you need to modify your infrastructure, you update the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarative vs. Imperative Infrastructure
&lt;/h2&gt;

&lt;p&gt;There are two common approaches to infrastructure automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Declarative Approach&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You describe &lt;em&gt;what&lt;/em&gt; the infrastructure should look like.&lt;/p&gt;

&lt;p&gt;The tool determines how to achieve that desired state.&lt;/p&gt;

&lt;p&gt;Example: Terraform, AWS CloudFormation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Imperative Approach&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You describe &lt;em&gt;how&lt;/em&gt; to configure the infrastructure through a sequence of commands or tasks.&lt;/p&gt;

&lt;p&gt;Example: Shell scripts and imperative automation workflows.&lt;/p&gt;

&lt;p&gt;The key difference?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Declarative = What you want.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imperative = How to achieve it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both approaches are useful, but declarative tools are particularly effective for managing the desired state of cloud infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is Infrastructure as Code Important?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Consistency Across Environments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Development, staging, and production environments can be provisioned using the same reusable configurations, with environment-specific parameters.&lt;/p&gt;

&lt;p&gt;This reduces configuration drift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Faster Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Infrastructure that previously required multiple manual configuration steps can be provisioned through automated workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Version Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Infrastructure configurations can live in Git alongside application code.&lt;/p&gt;

&lt;p&gt;You can review changes, track history, and understand how infrastructure evolves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Improved Collaboration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Infrastructure changes can go through pull requests, code reviews, testing, and approval processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Scalability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Need additional servers, databases, or networking resources?&lt;/p&gt;

&lt;p&gt;Update the configuration instead of repeating manual provisioning steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Popular Infrastructure as Code Tools
&lt;/h2&gt;

&lt;p&gt;Several tools support infrastructure automation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform:&lt;/strong&gt; Declarative infrastructure provisioning across multiple cloud providers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenTofu:&lt;/strong&gt; An open-source infrastructure provisioning tool built from Terraform's open-source lineage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CloudFormation:&lt;/strong&gt; Declarative infrastructure provisioning for AWS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pulumi:&lt;/strong&gt; Infrastructure provisioning using programming languages such as C#, Python, and TypeScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible:&lt;/strong&gt; Automation and configuration management, often used to configure systems after provisioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The right tool depends on your cloud provider, existing technology stack, and infrastructure requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure as Code Is Not Without Challenges
&lt;/h2&gt;

&lt;p&gt;IaC does not automatically eliminate infrastructure problems.&lt;/p&gt;

&lt;p&gt;Poorly managed configurations can still cause outages, security vulnerabilities, and unexpected costs.&lt;/p&gt;

&lt;p&gt;A few practices make IaC safer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Review infrastructure changes before applying them.&lt;/li&gt;
&lt;li&gt;Protect state files and avoid committing secrets.&lt;/li&gt;
&lt;li&gt;Use reusable modules to reduce duplication.&lt;/li&gt;
&lt;li&gt;Restrict deployment permissions using least privilege.&lt;/li&gt;
&lt;li&gt;Detect configuration drift and test changes before production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infrastructure automation is powerful, but it still requires proper engineering practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure should be treated with the same discipline as application code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It should be version-controlled, reviewed, tested, and deployed through repeatable processes.&lt;/p&gt;

&lt;p&gt;Infrastructure as Code is not simply about automating cloud resource creation.&lt;/p&gt;

&lt;p&gt;It's about making infrastructure &lt;strong&gt;consistent, reproducible, auditable, and easier to manage at scale.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your application deployment is automated but your infrastructure is still configured manually, you've only automated half the process.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Unit Tests vs Integration Tests: What's the Difference, and Why Do You Need Both?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Thu, 15 Oct 2026 09:22:14 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/unit-tests-vs-integration-tests-whats-the-difference-and-why-do-you-need-both-2beb</link>
      <guid>https://dev.to/omeiza_ahmed/unit-tests-vs-integration-tests-whats-the-difference-and-why-do-you-need-both-2beb</guid>
      <description>&lt;p&gt;Your code passes every unit test. Everything looks perfect.&lt;/p&gt;

&lt;p&gt;Then you deploy, and suddenly your application starts failing.&lt;/p&gt;

&lt;p&gt;The database connection isn't working. An API returns unexpected data. Two components that work perfectly on their own fail when communicating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is why passing unit tests doesn't guarantee a working application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's understand the difference between Unit Tests and Integration Tests, and when to use each.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What Are Unit Tests?
&lt;/h2&gt;

&lt;p&gt;Unit tests verify that individual pieces of code work correctly in isolation.&lt;/p&gt;

&lt;p&gt;A unit could be a method, function, or class.&lt;/p&gt;

&lt;p&gt;The goal is simple: &lt;strong&gt;Does this specific piece of code behave as expected?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, imagine you're building a banking application with a method that calculates transaction fees.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalculateFee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.01m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A unit test using xUnit might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CalculateFee_ShouldReturnOnePercent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TransactionService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fee&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CalculateFee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test checks one thing: whether the calculation produces the expected result.&lt;/p&gt;

&lt;p&gt;It doesn't need a database, external API, or running server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of Unit Tests:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast to execute&lt;/li&gt;
&lt;li&gt;Easy to debug&lt;/li&gt;
&lt;li&gt;Help catch logic errors early&lt;/li&gt;
&lt;li&gt;Provide quick feedback during development&lt;/li&gt;
&lt;li&gt;Encourage modular, maintainable code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; Unit tests cannot guarantee that independently tested components will work correctly together.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What Are Integration Tests?
&lt;/h2&gt;

&lt;p&gt;Integration tests verify that multiple components work correctly when connected.&lt;/p&gt;

&lt;p&gt;Instead of testing a single method, you're testing how different parts of your application interact.&lt;/p&gt;

&lt;p&gt;For example, consider a banking API that processes transfers.&lt;/p&gt;

&lt;p&gt;A transfer might involve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receiving an HTTP request.&lt;/li&gt;
&lt;li&gt;Validating the transaction.&lt;/li&gt;
&lt;li&gt;Checking the account balance.&lt;/li&gt;
&lt;li&gt;Updating the database.&lt;/li&gt;
&lt;li&gt;Returning a response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each component might pass its unit tests, but what happens when they work together?&lt;/p&gt;

&lt;p&gt;That's what integration tests help verify.&lt;/p&gt;

&lt;p&gt;Here's a simplified ASP.NET Core integration test using xUnit and &lt;code&gt;WebApplicationFactory&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TransferTests&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;IClassFixture&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WebApplicationFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Program&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;TransferTests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;WebApplicationFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Program&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Transfer_ShouldRejectInvalidAmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PostAsJsonAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"/api/transfers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test sends an HTTP request through the application's test host and checks whether the API rejects an invalid amount.&lt;/p&gt;

&lt;p&gt;It verifies more than a single method, including HTTP routing, model binding, and relevant request-processing components.&lt;/p&gt;

&lt;p&gt;A broader integration test could also verify database persistence using an isolated test database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of Integration Tests:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect communication problems between components&lt;/li&gt;
&lt;li&gt;Verify API and database interactions&lt;/li&gt;
&lt;li&gt;Catch configuration and dependency-injection issues&lt;/li&gt;
&lt;li&gt;Provide confidence that connected components behave correctly&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Generally slower than unit tests&lt;/li&gt;
&lt;li&gt;Require more setup&lt;/li&gt;
&lt;li&gt;Failures can be harder to diagnose&lt;/li&gt;
&lt;li&gt;May depend on infrastructure such as databases or message brokers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Unit Tests vs Integration Tests: Key Differences
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Unit Tests&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus:&lt;/strong&gt; Individual methods, functions, or classes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope:&lt;/strong&gt; Small and isolated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; Usually very fast&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies:&lt;/strong&gt; Typically replaced with mocks or fakes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging:&lt;/strong&gt; Easier to pinpoint failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; Checking whether a transaction fee is calculated correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration Tests&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus:&lt;/strong&gt; Interactions between components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope:&lt;/strong&gt; Multiple connected components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; Generally slower&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies:&lt;/strong&gt; Often use real components or test infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging:&lt;/strong&gt; May require investigating several layers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; Verifying that a transfer API correctly updates account balances in a database&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. When Should You Use Each?
&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;Unit Tests&lt;/strong&gt; when testing business rules, calculations, validation logic, or methods that can be isolated from external dependencies.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;Integration Tests&lt;/strong&gt; when testing database operations, API endpoints, service communication, authentication pipelines, or messaging infrastructure.&lt;/p&gt;

&lt;p&gt;For example, in a financial application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit test that a transfer cannot exceed the available balance.&lt;/li&gt;
&lt;li&gt;Integration test that a successful transfer correctly updates both accounts in the database.&lt;/li&gt;
&lt;li&gt;Unit test that a transaction fee is calculated correctly.&lt;/li&gt;
&lt;li&gt;Integration test that the API returns the correct response when a transfer is rejected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither type of test replaces the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Why You Need Both
&lt;/h2&gt;

&lt;p&gt;Imagine building an application using only unit tests.&lt;/p&gt;

&lt;p&gt;Your business logic might be perfectly tested, but you could still have broken database queries, incorrect API configurations, or failed service integrations.&lt;/p&gt;

&lt;p&gt;Now imagine relying only on integration tests.&lt;/p&gt;

&lt;p&gt;You might catch those problems, but your tests could become slower and make simple logic bugs harder to identify.&lt;/p&gt;

&lt;p&gt;A practical testing strategy combines both:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit Tests → Integration Tests → End-to-End Tests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unit tests provide fast feedback on individual components.&lt;/p&gt;

&lt;p&gt;Integration tests verify that components work together.&lt;/p&gt;

&lt;p&gt;End-to-end tests validate complete user workflows across the system.&lt;/p&gt;

&lt;p&gt;The goal isn't to write the largest number of tests. It's to build confidence that your application behaves correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Unit tests verify that individual components work correctly. Integration tests verify that those components work correctly together.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Good software needs both.&lt;/p&gt;

&lt;p&gt;Because working code is important, but working systems are what users actually depend on.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>Profiling a Slow Application: Stop Guessing, Start Measuring</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Wed, 14 Oct 2026 08:25:03 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/profiling-a-slow-application-stop-guessing-start-measuring-b6j</link>
      <guid>https://dev.to/omeiza_ahmed/profiling-a-slow-application-stop-guessing-start-measuring-b6j</guid>
      <description>&lt;p&gt;Your application is slow. Users are complaining. API requests are taking too long, and pages are struggling to load.&lt;/p&gt;

&lt;p&gt;Your first instinct might be to optimize the database, add caching, or rewrite some code.&lt;/p&gt;

&lt;p&gt;But what if none of those is the actual problem?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fastest way to fix a slow application is to stop guessing and start profiling.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Application Profiling?
&lt;/h2&gt;

&lt;p&gt;Application profiling is the process of measuring how an application uses resources such as CPU, memory, and execution time.&lt;/p&gt;

&lt;p&gt;Instead of assuming where the performance problem exists, profiling helps you identify the actual bottleneck.&lt;/p&gt;

&lt;p&gt;For example, imagine an API endpoint takes &lt;strong&gt;3 seconds&lt;/strong&gt; to respond.&lt;/p&gt;

&lt;p&gt;A profiler might reveal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database queries: 2,200ms&lt;/li&gt;
&lt;li&gt;Business logic: 300ms&lt;/li&gt;
&lt;li&gt;External API calls: 400ms&lt;/li&gt;
&lt;li&gt;Other processing: 100ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you know where to focus.&lt;/p&gt;

&lt;p&gt;Optimizing business logic won't make much difference when database queries consume most of the response time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Profile a Slow Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Reproduce the Performance Problem
&lt;/h3&gt;

&lt;p&gt;Before optimizing anything, reproduce the slowness under measurable conditions.&lt;/p&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which endpoint or operation is slow?&lt;/li&gt;
&lt;li&gt;Does it happen under heavy traffic?&lt;/li&gt;
&lt;li&gt;Is the problem consistent or occasional?&lt;/li&gt;
&lt;li&gt;How long does the operation actually take?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use tools like Chrome DevTools, Postman, or k6 to measure response times and reproduce performance issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You cannot reliably improve what you haven't measured.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Identify the Bottleneck
&lt;/h3&gt;

&lt;p&gt;Once you can reproduce the problem, investigate where execution time is being spent.&lt;/p&gt;

&lt;p&gt;Common bottlenecks include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CPU bottlenecks:&lt;/strong&gt; Expensive calculations, inefficient algorithms, or unnecessary processing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory bottlenecks:&lt;/strong&gt; Excessive allocations, memory leaks, or frequent garbage collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database bottlenecks:&lt;/strong&gt; Slow queries, missing indexes, or repeated database calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network bottlenecks:&lt;/strong&gt; Slow external APIs, excessive requests, or large payloads.&lt;/p&gt;

&lt;p&gt;Useful profiling tools include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chrome DevTools:&lt;/strong&gt; Frontend performance and JavaScript execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python cProfile:&lt;/strong&gt; Function-level execution profiling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js Inspector:&lt;/strong&gt; CPU profiling and memory analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pyroscope:&lt;/strong&gt; Continuous application profiling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenTelemetry:&lt;/strong&gt; Distributed tracing to identify latency across services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tracing and profiling complement each other: tracing shows where a request spends time across components, while profiling reveals what the code is doing within a process.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Optimize the Actual Problem
&lt;/h3&gt;

&lt;p&gt;Imagine your application retrieves 100 products from a database.&lt;/p&gt;

&lt;p&gt;For each product, it executes another query to fetch its category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_products&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates the classic &lt;strong&gt;N+1 query problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of executing one query, your application executes 101 queries.&lt;/p&gt;

&lt;p&gt;A better approach is to fetch the required data in fewer queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_products_with_categories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on your database and ORM, this might use a JOIN or eager loading.&lt;/p&gt;

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

&lt;p&gt;Fewer database round trips and potentially much faster response times.&lt;/p&gt;

&lt;p&gt;The important point is that profiling helped you identify the problem before making changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Measure Again
&lt;/h3&gt;

&lt;p&gt;Optimization isn't complete when your code looks cleaner.&lt;/p&gt;

&lt;p&gt;It's complete when measurements show meaningful improvement.&lt;/p&gt;

&lt;p&gt;Suppose your endpoint originally took 3 seconds.&lt;/p&gt;

&lt;p&gt;After optimizing the database queries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: 3,000ms&lt;/li&gt;
&lt;li&gt;After: 450ms&lt;/li&gt;
&lt;li&gt;Improvement: 85% reduction in response time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's a measurable performance improvement.&lt;/p&gt;

&lt;p&gt;However, don't stop at average response time. Check p95 and p99 latency, CPU usage, memory consumption, and error rates under comparable workloads.&lt;/p&gt;

&lt;p&gt;An optimization that improves one metric but introduces instability isn't necessarily a win.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Common Mistake Developers Make
&lt;/h2&gt;

&lt;p&gt;Many developers optimize code that looks inefficient without confirming whether it affects application performance.&lt;/p&gt;

&lt;p&gt;They rewrite loops, introduce caching, or change frameworks.&lt;/p&gt;

&lt;p&gt;Sometimes these changes help.&lt;/p&gt;

&lt;p&gt;Other times, they add complexity without solving anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Profiling changes the question from "What code looks slow?" to "What is actually consuming time and resources?"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;Performance optimization should follow a simple cycle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measure → Profile → Identify → Optimize → Measure Again&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't optimize based on assumptions.&lt;/p&gt;

&lt;p&gt;Find the bottleneck, fix it, and verify the improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best performance optimization isn't always the most complicated one. It's the one that fixes the actual problem.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>debugging</category>
      <category>performance</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Chaos Engineering: Why Breaking Your System Makes It More Reliable</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Wed, 14 Oct 2026 08:19:02 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/chaos-engineering-why-breaking-your-system-makes-it-more-reliable-186j</link>
      <guid>https://dev.to/omeiza_ahmed/chaos-engineering-why-breaking-your-system-makes-it-more-reliable-186j</guid>
      <description>&lt;p&gt;&lt;strong&gt;Your application works perfectly. Until something fails in production.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A database becomes unavailable. A network request times out. A server crashes unexpectedly.&lt;/p&gt;

&lt;p&gt;Suddenly, an application that passed every test starts falling apart.&lt;/p&gt;

&lt;p&gt;The problem isn't necessarily that your code is broken. It's that your system was never tested under failure conditions.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Chaos Engineering&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Chaos Engineering?
&lt;/h2&gt;

&lt;p&gt;Chaos Engineering is the practice of deliberately introducing controlled failures into a system to understand how it behaves under unexpected conditions.&lt;/p&gt;

&lt;p&gt;Instead of waiting for something to break in production, you simulate failures to discover weaknesses before they cause major outages.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't just test whether your system works. Test whether it can survive when things go wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Chaos Engineering Work?
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application with three services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order Service:&lt;/strong&gt; Handles customer orders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment Service:&lt;/strong&gt; Processes transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notification Service:&lt;/strong&gt; Sends order confirmations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under normal conditions, everything works perfectly.&lt;/p&gt;

&lt;p&gt;But what happens if the Payment Service suddenly becomes unavailable?&lt;/p&gt;

&lt;p&gt;Does the Order Service crash?&lt;/p&gt;

&lt;p&gt;Does the customer get charged twice when the request is retried?&lt;/p&gt;

&lt;p&gt;Does the application return a meaningful error?&lt;/p&gt;

&lt;p&gt;These are the questions Chaos Engineering helps answer.&lt;/p&gt;

&lt;p&gt;A typical experiment follows five steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Define normal behavior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Establish how the system should behave.&lt;/p&gt;

&lt;p&gt;For example, 99% of payment requests should complete successfully within two seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Form a hypothesis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Predict what should happen during a failure.&lt;/p&gt;

&lt;p&gt;For example, if the Payment Service becomes unavailable, the Order Service should return a controlled error without crashing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Introduce a controlled failure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simulate conditions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server shutdowns&lt;/li&gt;
&lt;li&gt;Network latency&lt;/li&gt;
&lt;li&gt;Database connection failures&lt;/li&gt;
&lt;li&gt;CPU or memory pressure&lt;/li&gt;
&lt;li&gt;Service unavailability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Observe the system&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Monitor error rates, response times, logs, and service health to understand how the application responds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Analyze and improve&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the system behaves unexpectedly, identify the weakness, implement a fix, and repeat the experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Example: Simulating Network Failure
&lt;/h2&gt;

&lt;p&gt;Let's say your application depends on an external payment API.&lt;/p&gt;

&lt;p&gt;Under normal conditions, the API responds in 200 milliseconds.&lt;/p&gt;

&lt;p&gt;But what happens when the response takes 10 seconds?&lt;/p&gt;

&lt;p&gt;Without proper timeout handling, requests may pile up and exhaust available resources.&lt;/p&gt;

&lt;p&gt;Chaos Engineering helps you discover this problem before real customers experience it.&lt;/p&gt;

&lt;p&gt;For example, using &lt;strong&gt;Toxiproxy&lt;/strong&gt;, you can simulate network latency between your application and a dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;toxiproxy-cli toxic add payment_api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt; latency &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attribute&lt;/span&gt; &lt;span class="nv"&gt;latency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming &lt;code&gt;payment_api&lt;/code&gt; is a configured Toxiproxy proxy, this introduces 5 seconds of latency.&lt;/p&gt;

&lt;p&gt;Now you can observe whether your application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Times out appropriately.&lt;/li&gt;
&lt;li&gt;Returns a meaningful error.&lt;/li&gt;
&lt;li&gt;Prevents uncontrolled retries.&lt;/li&gt;
&lt;li&gt;Recovers when the dependency becomes healthy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal isn't simply to make the application fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's to understand whether failure is handled gracefully.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chaos Engineering vs Traditional Testing
&lt;/h2&gt;

&lt;p&gt;Traditional testing primarily verifies whether an application behaves correctly under expected conditions.&lt;/p&gt;

&lt;p&gt;Chaos Engineering explores how the system behaves when infrastructure or dependencies fail.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional testing:&lt;/strong&gt;&lt;br&gt;
Does the checkout endpoint successfully process an order?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chaos Engineering:&lt;/strong&gt;&lt;br&gt;
What happens to checkout when the database becomes temporarily unavailable?&lt;/p&gt;

&lt;p&gt;Both approaches are important.&lt;/p&gt;

&lt;p&gt;Traditional testing helps establish correctness. Chaos Engineering helps validate resilience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Popular Chaos Engineering Tools
&lt;/h2&gt;

&lt;p&gt;Several tools can help automate failure experiments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Monkey:&lt;/strong&gt; Terminates compute instances to test fault tolerance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LitmusChaos:&lt;/strong&gt; Provides chaos experiments for Kubernetes environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Mesh:&lt;/strong&gt; Simulates network, infrastructure, and resource failures in Kubernetes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toxiproxy:&lt;/strong&gt; Simulates network issues between applications and dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The right tool depends on your architecture and the failures you want to investigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Run Chaos Experiments in Production?
&lt;/h2&gt;

&lt;p&gt;Chaos Engineering can be performed in production, but it should never mean introducing uncontrolled failures.&lt;/p&gt;

&lt;p&gt;Start in a staging environment where possible.&lt;/p&gt;

&lt;p&gt;Define a hypothesis, monitor the relevant metrics, limit the experiment's impact, and establish clear conditions for stopping it.&lt;/p&gt;

&lt;p&gt;Once you understand your system's behavior and have appropriate safeguards, you can consider carefully scoped production experiments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The objective is to build confidence, not create unnecessary outages.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;A reliable system isn't one that never experiences failure.&lt;/p&gt;

&lt;p&gt;It's one that can handle failure without causing unnecessary disruption.&lt;/p&gt;

&lt;p&gt;Chaos Engineering shifts your mindset from asking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Will this system fail?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To asking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"When something fails, will the system recover gracefully?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because in distributed systems, failures aren't exceptions.&lt;/p&gt;

&lt;p&gt;They're part of normal operation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't wait for production to expose your system's weaknesses. Discover them through controlled experiments.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>testing</category>
    </item>
    <item>
      <title>CI vs CD: Passing Tests Is Only Part of Shipping Software</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Mon, 12 Oct 2026 07:27:18 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/ci-vs-cd-passing-tests-is-only-part-of-shipping-software-24g7</link>
      <guid>https://dev.to/omeiza_ahmed/ci-vs-cd-passing-tests-is-only-part-of-shipping-software-24g7</guid>
      <description>&lt;p&gt;Your code builds. The tests pass. But releasing it still involves copying files, changing settings, and hoping you remembered every step.&lt;/p&gt;

&lt;p&gt;That gap is what CI and CD help address.&lt;/p&gt;

&lt;p&gt;They work together, but they handle different parts of getting code into users’ hands.&lt;/p&gt;

&lt;h2&gt;
  
  
  CI: Integrate Changes and Catch Problems Early
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Continuous Integration (CI)&lt;/strong&gt; means developers frequently merge small changes into a shared codebase, with automated checks validating those changes.&lt;/p&gt;

&lt;p&gt;A typical CI pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Builds the application.&lt;/li&gt;
&lt;li&gt;Runs automated tests.&lt;/li&gt;
&lt;li&gt;Checks code quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine two developers working on an ASP.NET application. One changes an API response; the other updates code that depends on it.&lt;/p&gt;

&lt;p&gt;Their changes may work separately but fail when combined. CI helps catch that conflict early, while the changes are still small enough to investigate easily.&lt;/p&gt;

&lt;p&gt;CI gives feedback about whether changes work together. Its confidence depends on the quality of the checks—you can still ship bugs with a green pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  CD: Make Releases Repeatable
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CD can mean Continuous Delivery or Continuous Deployment.&lt;/strong&gt; This distinction matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous Delivery
&lt;/h3&gt;

&lt;p&gt;Changes that pass the pipeline are kept ready for release. The pipeline automates the steps needed to prepare and validate a release, but production deployment still requires a deliberate approval or action.&lt;/p&gt;

&lt;p&gt;For example, a release is deployed to staging automatically. After reviewing it, someone approves deployment to production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous Deployment
&lt;/h3&gt;

&lt;p&gt;Every change that passes the required checks is automatically deployed to production.&lt;/p&gt;

&lt;p&gt;There is no routine manual approval between successful validation and deployment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Practice&lt;/th&gt;
&lt;th&gt;Main purpose&lt;/th&gt;
&lt;th&gt;Production deployment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Continuous Integration&lt;/td&gt;
&lt;td&gt;Validate frequently integrated changes&lt;/td&gt;
&lt;td&gt;Not required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuous Delivery&lt;/td&gt;
&lt;td&gt;Keep validated changes ready for release&lt;/td&gt;
&lt;td&gt;Requires a deliberate decision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuous Deployment&lt;/td&gt;
&lt;td&gt;Release validated changes automatically&lt;/td&gt;
&lt;td&gt;Happens automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  A Practical Example
&lt;/h2&gt;

&lt;p&gt;Suppose you add pagination to an ASP.NET API.&lt;/p&gt;

&lt;p&gt;Your pipeline builds the application, runs tests, packages it, and deploys it to staging.&lt;/p&gt;

&lt;p&gt;The build and integration checks support &lt;strong&gt;CI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the validated release waits for production approval, you have &lt;strong&gt;Continuous Delivery&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If it automatically goes to production after passing all required checks, you have &lt;strong&gt;Continuous Deployment&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The difference is the release decision, not whether you use GitHub Actions, Jenkins, or another tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Approach Should You Use?
&lt;/h2&gt;

&lt;p&gt;Start with reliable CI checks and a repeatable deployment process.&lt;/p&gt;

&lt;p&gt;Choose Continuous Delivery when releases need deliberate approval, coordination, or scheduled timing.&lt;/p&gt;

&lt;p&gt;Choose Continuous Deployment when your testing, monitoring, and recovery processes support automatically releasing small changes.&lt;/p&gt;

&lt;p&gt;Automation increases release speed, but weak checks can also let mistakes reach production faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CI validates integrated changes. Continuous Delivery keeps them ready to release. Continuous Deployment releases them automatically.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build confidence in your checks before removing the final approval step.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>cicd</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>Principle of Least Privilege: Does Your App Really Need Admin Access?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Sun, 11 Oct 2026 08:53:29 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/principle-of-least-privilege-does-your-app-really-need-admin-access-456n</link>
      <guid>https://dev.to/omeiza_ahmed/principle-of-least-privilege-does-your-app-really-need-admin-access-456n</guid>
      <description>&lt;p&gt;Your reporting service only reads sales data. So why does its database account also have permission to delete customers?&lt;/p&gt;

&lt;p&gt;Extra permissions are easy to grant during development—and easy to forget afterward. The principle of least privilege helps prevent that convenience from becoming a security problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does least privilege mean?
&lt;/h2&gt;

&lt;p&gt;Give every user, application, and service only the permissions it needs to perform its job.&lt;/p&gt;

&lt;p&gt;A service that reads reports needs access to the relevant data. It does not automatically need permission to update records, manage accounts, or change database tables. This matches NIST’s definition of granting only the minimum resources and authorizations required for a task.&lt;/p&gt;

&lt;p&gt;The question is simple: &lt;strong&gt;What does this identity actually need to do?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical example: a reporting service
&lt;/h2&gt;

&lt;p&gt;Imagine an e-commerce application with a service that generates daily sales reports.&lt;/p&gt;

&lt;p&gt;Its database access could look like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Required?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read approved sales data&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update order statuses&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete customers&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create or drop tables&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Give the service a dedicated database account with access to the required tables, columns, or reporting views.&lt;/p&gt;

&lt;p&gt;If someone steals its credentials, those credentials should not authorize destructive operations. However, the attacker could still read the data the account can access. Restricting which data it can read matters too.&lt;/p&gt;

&lt;p&gt;Least privilege limits the damage a compromised identity can cause. It does not make compromise harmless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply it to users and resources
&lt;/h2&gt;

&lt;p&gt;Permissions also need boundaries inside your application.&lt;/p&gt;

&lt;p&gt;A customer may be allowed to view orders, but only their own orders. Checking that they are logged in is insufficient; the API must check whether they can access the specific order requested.&lt;/p&gt;

&lt;p&gt;OWASP recommends denying access by default and validating permissions on every request. Hiding a button in the frontend does not enforce that rule—the backend must reject unauthorized actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid “give it admin so it works”
&lt;/h2&gt;

&lt;p&gt;When an operation fails, granting administrator access can make the error disappear without explaining which permission was missing.&lt;/p&gt;

&lt;p&gt;Instead, identify the operation, grant the specific permission it requires, and verify that unrelated operations remain blocked.&lt;/p&gt;

&lt;p&gt;Use separate identities for separate responsibilities. A deployment process that changes the database schema has different needs from the application serving normal requests.&lt;/p&gt;

&lt;p&gt;There is a tradeoff: narrower permissions require more planning and maintenance. Review them as responsibilities change, so old access does not accumulate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaway
&lt;/h2&gt;

&lt;p&gt;Treat permissions as part of your application’s design. Give each identity the access its current responsibilities require, and verify that everything outside those boundaries is denied.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>security</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>JSON Web Tokens: What Your API Should Actually Trust</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Sat, 10 Oct 2026 10:10:27 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/json-web-tokens-what-your-api-should-actually-trust-5ggl</link>
      <guid>https://dev.to/omeiza_ahmed/json-web-tokens-what-your-api-should-actually-trust-5ggl</guid>
      <description>&lt;p&gt;A user logs in, receives a token, and sends it with every request.&lt;/p&gt;

&lt;p&gt;Simple enough. But decoding that token doesn’t prove it’s trustworthy.&lt;/p&gt;

&lt;p&gt;That distinction is central to understanding JSON Web Tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a JWT?
&lt;/h3&gt;

&lt;p&gt;A JSON Web Token, or JWT, is a compact format for carrying &lt;strong&gt;claims&lt;/strong&gt; between systems. Claims are statements such as who the user is, who issued the token, and when it expires.&lt;/p&gt;

&lt;p&gt;JWTs can be signed, encrypted, or both. The signed version commonly used in APIs has three parts:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;header.payload.signature&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header:&lt;/strong&gt; Identifies the signing algorithm and token type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload:&lt;/strong&gt; Contains the claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature:&lt;/strong&gt; Lets the recipient verify integrity using the appropriate key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The header and payload are Base64url-encoded. &lt;strong&gt;Encoding does not hide their contents.&lt;/strong&gt; A signed JWT’s payload is readable by anyone holding it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work in an API?
&lt;/h3&gt;

&lt;p&gt;Consider an order management application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user submits their login credentials.&lt;/li&gt;
&lt;li&gt;The authentication service verifies them and issues a signed JWT.&lt;/li&gt;
&lt;li&gt;The client sends the token with subsequent requests.&lt;/li&gt;
&lt;li&gt;The API validates the token before applying its access rules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A typical request includes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The token might identify the user as &lt;code&gt;user-42&lt;/code&gt;. The API can then use that identity when checking whether they may view a particular order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoding is not validation
&lt;/h3&gt;

&lt;p&gt;Decoding a JWT only reveals its contents. Anyone can construct a payload claiming to be an administrator.&lt;/p&gt;

&lt;p&gt;Before trusting a token, the API must verify its cryptographic protection, restrict accepted algorithms, and check relevant claims—including the expected issuer, intended audience, and expiration.&lt;/p&gt;

&lt;p&gt;Use a maintained validation library with explicit configuration. Don’t let an incoming token decide which algorithms your API trusts.&lt;/p&gt;

&lt;h3&gt;
  
  
  A valid token still needs permission checks
&lt;/h3&gt;

&lt;p&gt;Imagine a valid token belongs to &lt;code&gt;user-42&lt;/code&gt;, but the requested order belongs to &lt;code&gt;user-99&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The token establishes an identity. Your application still needs to check ownership or other authorization rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“This token is valid” does not mean “this request is allowed.”&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What about logout?
&lt;/h3&gt;

&lt;p&gt;Deleting the token from the client stops that client from sending it. It does not invalidate a copy held elsewhere.&lt;/p&gt;

&lt;p&gt;If an API relies only on token validation, a copied token can remain usable until expiration. Immediate revocation requires an additional mechanism, such as a server-side revocation check.&lt;/p&gt;

&lt;p&gt;This is a practical tradeoff to consider when designing your authentication flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key takeaway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;JWTs carry claims; validation establishes whether to trust them; authorization determines what the request may do.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep those responsibilities clear, and your authentication flow becomes easier to understand and secure.&lt;/p&gt;

</description>
      <category>api</category>
      <category>authentication</category>
      <category>backend</category>
      <category>security</category>
    </item>
    <item>
      <title>Pub/Sub Messaging: Let One Event Trigger Many Actions</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Fri, 09 Oct 2026 07:04:41 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/pubsub-messaging-let-one-event-trigger-many-actions-390f</link>
      <guid>https://dev.to/omeiza_ahmed/pubsub-messaging-let-one-event-trigger-many-actions-390f</guid>
      <description>&lt;p&gt;An order is placed. You need to send a confirmation email, update inventory, and notify the warehouse.&lt;/p&gt;

&lt;p&gt;You could make the order service call every system directly. But each new integration adds another dependency—and another way for order processing to fail.&lt;/p&gt;

&lt;p&gt;Pub/Sub offers a different approach: publish what happened and let interested systems react.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Pub/Sub?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pub/Sub stands for publish/subscribe.&lt;/strong&gt; It is a messaging pattern with three main parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Publisher:&lt;/strong&gt; Produces a message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Topic:&lt;/strong&gt; A named channel through which a broker routes messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriber:&lt;/strong&gt; Receives messages through a subscription to that topic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The publisher does not need to know which systems consume its messages.&lt;/p&gt;

&lt;p&gt;For example, an order service publishes this message to an &lt;code&gt;orders&lt;/code&gt; topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"eventId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"evt_123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"order.created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ord_456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cus_789"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The email, inventory, and warehouse services each have their own subscription. Each can react to the same event independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Helps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add features without changing the publisher
&lt;/h3&gt;

&lt;p&gt;Suppose you introduce an analytics service.&lt;/p&gt;

&lt;p&gt;With direct calls, you may need to update the order service to call it. With Pub/Sub, you can add a subscription that receives relevant order events.&lt;/p&gt;

&lt;p&gt;The publisher still needs to maintain a stable message contract, but it does not need to manage every consumer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handle work independently
&lt;/h3&gt;

&lt;p&gt;An email service can process messages at a different pace from the inventory service.&lt;/p&gt;

&lt;p&gt;With durable subscriptions and suitable retention settings, a temporarily unavailable subscriber can catch up later. That behavior depends on the messaging system and its configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep slow work out of the request
&lt;/h3&gt;

&lt;p&gt;The order service can publish an event without waiting for every downstream action to finish.&lt;/p&gt;

&lt;p&gt;That makes processing asynchronous: an accepted order does not necessarily mean its confirmation email has already been sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pub/Sub vs a Work Queue
&lt;/h2&gt;

&lt;p&gt;The key difference is &lt;strong&gt;who should receive the message&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A work queue typically distributes each message to one worker in a group. Pub/Sub routes a message to each interested subscription.&lt;/p&gt;

&lt;p&gt;For an &lt;code&gt;order.created&lt;/code&gt; event:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Email and inventory need separate subscriptions because both must react.&lt;/li&gt;
&lt;li&gt;Multiple email workers can share one subscription to divide the email workload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pub/Sub enables fan-out across subscriptions while allowing workers within a subscription to share the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Catch: Delivery Needs Care
&lt;/h2&gt;

&lt;p&gt;Pub/Sub reduces direct dependencies, but it introduces delivery concerns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duplicate messages:&lt;/strong&gt; Many systems offer at-least-once delivery. A subscriber should safely handle the same event more than once—for example, by recording processed event IDs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failed processing:&lt;/strong&gt; Use controlled retries and a dead-letter destination for messages that repeatedly fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ordering:&lt;/strong&gt; Do not assume global message order. Check the broker’s guarantees and configure ordering where your workflow requires it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Saving an order and publishing its event are separate operations. An outbox pattern can help prevent an order from being saved without its event eventually being published.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pub/Sub lets one event reach multiple independent consumers without making the publisher coordinate them all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use it when several systems need to react to the same event. Design for duplicates, failures, and delayed processing from the start.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>microservices</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>BFS vs DFS: Explore Nearby or Go Deeper?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Thu, 08 Oct 2026 09:21:19 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/bfs-vs-dfs-explore-nearby-or-go-deeper-367e</link>
      <guid>https://dev.to/omeiza_ahmed/bfs-vs-dfs-explore-nearby-or-go-deeper-367e</guid>
      <description>&lt;p&gt;Imagine searching for a file in a folder full of subfolders.&lt;/p&gt;

&lt;p&gt;You could check every folder at the current level before going deeper. Or you could follow one folder path all the way down, then return to explore the others.&lt;/p&gt;

&lt;p&gt;That is the core difference between &lt;strong&gt;Breadth-First Search (BFS)&lt;/strong&gt; and &lt;strong&gt;Depth-First Search (DFS)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Both traverse trees and graphs. What changes is the order they explore—and the problems they solve best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breadth-First Search: Explore Level by Level
&lt;/h2&gt;

&lt;p&gt;BFS visits the starting node, then its immediate neighbors, then their neighbors.&lt;/p&gt;

&lt;p&gt;It typically uses a &lt;strong&gt;queue&lt;/strong&gt;: the first node added is the first node processed.&lt;/p&gt;

&lt;p&gt;Consider this tree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A has children B and C.&lt;/li&gt;
&lt;li&gt;B has children D and E.&lt;/li&gt;
&lt;li&gt;C has children F and G.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Starting at A and visiting children from left to right, BFS produces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A → B → C → D → E → F → G&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It finishes one level before moving to the next.&lt;/p&gt;

&lt;h3&gt;
  
  
  When is BFS useful?
&lt;/h3&gt;

&lt;p&gt;BFS is useful when you need the &lt;strong&gt;shortest path by number of edges in an unweighted graph&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, if each connection between two people counts as one step, BFS can find the fewest connections between you and another person.&lt;/p&gt;

&lt;p&gt;This works because BFS explores all nodes one step away before exploring nodes two steps away.&lt;/p&gt;

&lt;p&gt;If edges have different costs, ordinary BFS does not guarantee the cheapest path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Depth-First Search: Follow One Branch
&lt;/h2&gt;

&lt;p&gt;DFS follows a branch as far as possible, then backtracks to explore another branch.&lt;/p&gt;

&lt;p&gt;It typically uses a &lt;strong&gt;stack&lt;/strong&gt;, either explicitly or through recursive function calls.&lt;/p&gt;

&lt;p&gt;Using the same tree and visiting children from left to right, DFS produces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A → B → D → E → C → F → G&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It explores B’s entire branch before moving to C.&lt;/p&gt;

&lt;h3&gt;
  
  
  When is DFS useful?
&lt;/h3&gt;

&lt;p&gt;DFS is useful for problems that involve exploring possibilities or relationships deeply, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detecting cycles.&lt;/li&gt;
&lt;li&gt;Finding connected components.&lt;/li&gt;
&lt;li&gt;Topological sorting in a directed acyclic graph.&lt;/li&gt;
&lt;li&gt;Backtracking through puzzles and possible solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DFS can find a path between nodes, but the first path it finds may not be the shortest.&lt;/p&gt;

&lt;h2&gt;
  
  
  BFS vs DFS at a Glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;BFS&lt;/th&gt;
&lt;th&gt;DFS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Exploration order&lt;/td&gt;
&lt;td&gt;Level by level&lt;/td&gt;
&lt;td&gt;Branch by branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main structure&lt;/td&gt;
&lt;td&gt;Queue&lt;/td&gt;
&lt;td&gt;Stack or recursion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shortest path in an unweighted graph&lt;/td&gt;
&lt;td&gt;Guaranteed&lt;/td&gt;
&lt;td&gt;Not guaranteed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use&lt;/td&gt;
&lt;td&gt;Fewest-step paths&lt;/td&gt;
&lt;td&gt;Deep exploration and backtracking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a full traversal using an adjacency list, both take &lt;strong&gt;O(V + E)&lt;/strong&gt; time, where V is the number of vertices and E is the number of edges.&lt;/p&gt;

&lt;p&gt;Memory depends on the graph’s shape. BFS can hold a large frontier in a wide graph. Recursive DFS can build a large call stack in a deep graph. Both can require &lt;strong&gt;O(V)&lt;/strong&gt; auxiliary space.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Important Detail: Track Visited Nodes
&lt;/h2&gt;

&lt;p&gt;Graphs can contain cycles.&lt;/p&gt;

&lt;p&gt;Without tracking visited nodes, your traversal may keep returning to the same nodes indefinitely.&lt;/p&gt;

&lt;p&gt;For BFS, mark a node as visited when you enqueue it. For DFS, mark it when you first enter it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use BFS when you need the fewest steps in an unweighted graph. Use DFS when you need to explore branches, dependencies, or possible solutions deeply.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The right choice comes from the problem you need to solve.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>coding</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Authentication vs Authorization: Who Are You, and What Are You Allowed to Do?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Wed, 07 Oct 2026 08:56:08 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/authentication-vs-authorization-who-are-you-and-what-are-you-allowed-to-do-5bl2</link>
      <guid>https://dev.to/omeiza_ahmed/authentication-vs-authorization-who-are-you-and-what-are-you-allowed-to-do-5bl2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Authentication answers “Who are you?” Authorization answers “What are you allowed to do?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These two concepts are often mentioned together, but they solve completely different problems.&lt;/p&gt;

&lt;p&gt;Understanding the difference is essential when building APIs, web applications, and secure systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication: Who Are You?
&lt;/h2&gt;

&lt;p&gt;Authentication is the process of &lt;strong&gt;verifying a user's identity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you log into an application with an email and password, the system checks whether those credentials belong to you.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Email: omeiza@example.com
Password: ********
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the credentials are valid, the application knows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“This user is Omeiza.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Other common authentication methods include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passwords&lt;/li&gt;
&lt;li&gt;JWT tokens&lt;/li&gt;
&lt;li&gt;Session cookies&lt;/li&gt;
&lt;li&gt;OAuth&lt;/li&gt;
&lt;li&gt;Multi-factor authentication&lt;/li&gt;
&lt;li&gt;Biometric authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Authentication happens &lt;strong&gt;before&lt;/strong&gt; the system can make meaningful authorization decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization: What Can You Do?
&lt;/h2&gt;

&lt;p&gt;Once the system knows who you are, it needs to determine what you're allowed to access.&lt;/p&gt;

&lt;p&gt;That's authorization.&lt;/p&gt;

&lt;p&gt;Imagine you're logged into an admin dashboard.&lt;/p&gt;

&lt;p&gt;The system knows you're Omeiza, but that doesn't automatically mean you're allowed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete users&lt;/li&gt;
&lt;li&gt;Access financial reports&lt;/li&gt;
&lt;li&gt;Change system settings&lt;/li&gt;
&lt;li&gt;Promote another user to admin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Authorization determines whether you have permission to perform those actions.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: Omeiza
Role: Admin

Action: Delete User
Result: Allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: John
Role: Customer

Action: Delete User
Result: Forbidden
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Difference in One Example
&lt;/h2&gt;

&lt;p&gt;Think about entering an office building.&lt;/p&gt;

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

&lt;p&gt;The security guard checks your ID and confirms:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Yes, this is Omeiza.”&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;The guard then checks your access level:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Omeiza can enter the office, but not the server room.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Authentication establishes &lt;strong&gt;identity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Authorization determines &lt;strong&gt;permissions&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How They Work Together
&lt;/h2&gt;

&lt;p&gt;A typical API request might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  ↓
Login
  ↓
Authentication
  ↓
JWT Token
  ↓
API Request
  ↓
Authorization
  ↓
Access Granted / Denied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, a user logs in and receives a JWT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API validates the token to authenticate the user.&lt;/p&gt;

&lt;p&gt;Then it checks the user's role or permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is the user authenticated?
        ↓
       Yes
        ↓
Does the user have permission?
        ↓
       Yes
        ↓
   Execute request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user isn't authenticated, the API typically returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;401 Unauthorized
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user is authenticated but doesn't have permission, the API typically returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;403 Forbidden
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction is important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;401:&lt;/strong&gt; “I don't know who you are.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;403:&lt;/strong&gt; “I know who you are, but you're not allowed to do this.”&lt;/p&gt;

&lt;h2&gt;
  
  
  A Common Mistake
&lt;/h2&gt;

&lt;p&gt;A common security mistake is assuming that authentication is enough.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Authorize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;DeleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Delete user&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may ensure that the user is logged in, but it doesn't necessarily mean every authenticated user should be able to delete users.&lt;/p&gt;

&lt;p&gt;You might instead require a specific role or permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Roles&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Admin"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;DeleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Delete user&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now authentication answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this user logged in?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Authorization answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this user an admin?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Authentication identifies the user. Authorization controls what that user can do.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A secure application needs both.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Authentication = Who are you?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Authorization = What are you allowed to do?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you understand that distinction, many security concepts in APIs and web applications become much easier to reason about.&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>backend</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Partitioning vs Sharding: What’s the Difference?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Tue, 06 Oct 2026 10:13:44 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/partitioning-vs-sharding-whats-the-difference-54fe</link>
      <guid>https://dev.to/omeiza_ahmed/partitioning-vs-sharding-whats-the-difference-54fe</guid>
      <description>&lt;p&gt;Your database is getting bigger. Queries are getting slower. Your server is starting to struggle.&lt;/p&gt;

&lt;p&gt;You hear two solutions: &lt;strong&gt;partitioning&lt;/strong&gt; and &lt;strong&gt;sharding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They sound similar because both split data into smaller pieces. But they solve the problem at &lt;strong&gt;different levels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Database Partitioning?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Partitioning&lt;/strong&gt; splits a large table into smaller logical pieces called &lt;strong&gt;partitions&lt;/strong&gt;, while keeping them within the same database system.&lt;/p&gt;

&lt;p&gt;For example, imagine an &lt;code&gt;Orders&lt;/code&gt; table with 100 million records.&lt;/p&gt;

&lt;p&gt;Instead of keeping everything in one huge table, you could partition it by year:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Orders
├── 2024
├── 2025
├── 2026
└── 2027
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A query such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Orders&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;OrderDate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-01'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can potentially access only the relevant partition instead of scanning the entire table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Partitioning Strategies
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Range partitioning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Split data based on ranges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2024 orders → Partition 1
2025 orders → Partition 2
2026 orders → Partition 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;List partitioning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Split data based on specific values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nigeria → Partition 1
Ghana   → Partition 2
Kenya   → Partition 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hash partitioning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use a hash function to distribute rows across partitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hash(CustomerId) → Partition 1, 2, 3...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing is that the partitions are still managed as part of the &lt;strong&gt;same database environment&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Sharding?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Sharding&lt;/strong&gt; takes the idea further.&lt;/p&gt;

&lt;p&gt;Instead of splitting a table inside one database, you distribute the data across &lt;strong&gt;multiple independent database instances or servers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shard 1 → Customers 1–1,000,000
Shard 2 → Customers 1,000,001–2,000,000
Shard 3 → Customers 2,000,001–3,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each shard can have its own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database&lt;/li&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Connections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows the workload to be distributed across multiple machines.&lt;/p&gt;

&lt;p&gt;For example, a large application might route customers based on &lt;code&gt;CustomerId&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CustomerId → Shard
     101   → Shard 1
  1500000  → Shard 2
  2500000  → Shard 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Partitioning vs Sharding
&lt;/h2&gt;

&lt;p&gt;The easiest way to remember the difference:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Partitioning&lt;/th&gt;
&lt;th&gt;Sharding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Splits data&lt;/td&gt;
&lt;td&gt;Inside a database&lt;/td&gt;
&lt;td&gt;Across databases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure&lt;/td&gt;
&lt;td&gt;Usually one database system&lt;/td&gt;
&lt;td&gt;Multiple database instances/servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main goal&lt;/td&gt;
&lt;td&gt;Manage large tables efficiently&lt;/td&gt;
&lt;td&gt;Scale database workloads horizontally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complexity&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application involvement&lt;/td&gt;
&lt;td&gt;Usually minimal&lt;/td&gt;
&lt;td&gt;Often significant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

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

&lt;blockquote&gt;
&lt;p&gt;"Let's organize this huge table into smaller pieces."&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"This database is too much for one machine, so let's distribute the data across multiple machines."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Can You Use Both?
&lt;/h2&gt;

&lt;p&gt;Absolutely.&lt;/p&gt;

&lt;p&gt;A large-scale system might use &lt;strong&gt;sharding and partitioning together&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Database Cluster
                       │
          ┌────────────┼────────────┐
          │            │            │
       Shard 1      Shard 2      Shard 3
          │            │            │
       ┌──┴──┐       ┌──┴──┐       ┌──┴──┐
       2025  2026    2025  2026    2025  2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each shard could contain partitioned tables.&lt;/p&gt;

&lt;p&gt;This is useful when an application has both &lt;strong&gt;very large datasets&lt;/strong&gt; and &lt;strong&gt;high traffic&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Which One Should You Use?
&lt;/h2&gt;

&lt;p&gt;Don't jump straight to sharding because it sounds more scalable.&lt;/p&gt;

&lt;p&gt;Partitioning is often the simpler solution when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your tables are becoming very large.&lt;/li&gt;
&lt;li&gt;Queries frequently filter by a predictable column such as date.&lt;/li&gt;
&lt;li&gt;You want easier data management.&lt;/li&gt;
&lt;li&gt;A single database server can still handle your workload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sharding becomes more attractive when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single database server is reaching its limits.&lt;/li&gt;
&lt;li&gt;You need to scale horizontally.&lt;/li&gt;
&lt;li&gt;Your dataset is extremely large.&lt;/li&gt;
&lt;li&gt;Database traffic needs to be distributed across multiple machines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sharding also introduces significant complexity around routing, joins, transactions, backups, and operational management.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Partitioning divides data within a database. Sharding distributes data across databases.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Partitioning is primarily about &lt;strong&gt;organizing and managing large datasets efficiently&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sharding is primarily about &lt;strong&gt;scaling database capacity across multiple machines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So before reaching for sharding, ask a simpler question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Is my database too big, or is one database server no longer enough?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That distinction can determine which solution you actually need.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>database</category>
      <category>performance</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>CAP Theorem: The Trade-Off Behind Distributed Systems</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Mon, 05 Oct 2026 07:12:10 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/cap-theorem-the-trade-off-behind-distributed-systems-18ie</link>
      <guid>https://dev.to/omeiza_ahmed/cap-theorem-the-trade-off-behind-distributed-systems-18ie</guid>
      <description>&lt;p&gt;What if your database has multiple servers, and they suddenly can’t communicate with each other?&lt;/p&gt;

&lt;p&gt;Should the system keep accepting requests, even if some servers might have outdated data?&lt;/p&gt;

&lt;p&gt;Or should it reject requests until everything is synchronized?&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;CAP Theorem&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is CAP Theorem?
&lt;/h2&gt;

&lt;p&gt;CAP states that a distributed system can guarantee at most &lt;strong&gt;two out of three properties&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Availability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partition Tolerance&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's break them down.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Consistency
&lt;/h3&gt;

&lt;p&gt;Every read gets the &lt;strong&gt;most recent write&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine you update your bank balance from ₦50,000 to ₦40,000.&lt;/p&gt;

&lt;p&gt;With strong consistency, every server should immediately return:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;₦40,000&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No server should return the old ₦50,000.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Availability
&lt;/h3&gt;

&lt;p&gt;Every request receives a response, even when some parts of the system are failing.&lt;/p&gt;

&lt;p&gt;If one server goes down, another server should still be able to respond.&lt;/p&gt;

&lt;p&gt;The system prioritizes staying operational.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Partition Tolerance
&lt;/h3&gt;

&lt;p&gt;The system continues working even when communication between servers is interrupted.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server A  X  Server B
          ↑
   Network failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server A and Server B are still running, but they can't communicate.&lt;/p&gt;

&lt;p&gt;That's a &lt;strong&gt;network partition&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Important Part: You Can't Ignore Partitions
&lt;/h2&gt;

&lt;p&gt;Here's the part that is often misunderstood.&lt;/p&gt;

&lt;p&gt;CAP doesn't simply mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Pick any two of the three."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a distributed system, &lt;strong&gt;network partitions can happen&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a partition occurs, you have to choose between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency (C)&lt;/strong&gt;&lt;br&gt;
or&lt;br&gt;
&lt;strong&gt;Availability (A)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You still need &lt;strong&gt;Partition Tolerance (P)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So during a network failure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C + P → Prefer correct, consistent data
A + P → Prefer staying available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Simple Example
&lt;/h2&gt;

&lt;p&gt;Imagine an e-commerce system with two servers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        Database
       /        \
   Server A    Server B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A network failure occurs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Server A  X  Server B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A customer buys the last available product through Server A.&lt;/p&gt;

&lt;p&gt;Server B doesn't know about the purchase because the servers can't communicate.&lt;/p&gt;

&lt;p&gt;Now another customer requests the same product through Server B.&lt;/p&gt;

&lt;p&gt;What should happen?&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose Consistency
&lt;/h3&gt;

&lt;p&gt;Server B could reject the request because it cannot guarantee that its data is current.&lt;/p&gt;

&lt;p&gt;You sacrifice &lt;strong&gt;availability&lt;/strong&gt; to protect &lt;strong&gt;consistency&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose Availability
&lt;/h3&gt;

&lt;p&gt;Server B could continue accepting requests using its local data.&lt;/p&gt;

&lt;p&gt;The system remains available, but users might temporarily see inconsistent information.&lt;/p&gt;

&lt;p&gt;You sacrifice &lt;strong&gt;consistency&lt;/strong&gt; to protect &lt;strong&gt;availability&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  CAP Isn't About "Fast vs Slow"
&lt;/h2&gt;

&lt;p&gt;CAP is specifically about &lt;strong&gt;distributed systems experiencing network partitions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's not a general rule that says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You can only have two of the three properties."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In normal operation, a system can provide both strong consistency and high availability.&lt;/p&gt;

&lt;p&gt;The trade-off becomes important &lt;strong&gt;when a network partition occurs&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why CAP Matters
&lt;/h2&gt;

&lt;p&gt;CAP helps engineers understand why distributed databases make different design decisions.&lt;/p&gt;

&lt;p&gt;Some systems prioritize:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Useful when incorrect or stale data is unacceptable.&lt;/p&gt;

&lt;p&gt;Others prioritize:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Availability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Useful when keeping the system operational is more important than immediately having perfectly synchronized data.&lt;/p&gt;

&lt;p&gt;Neither choice is automatically better.&lt;/p&gt;

&lt;p&gt;It depends on the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;CAP Theorem is really about what happens when distributed systems &lt;strong&gt;can't communicate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a network partition occurs, you generally have to choose:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency or Availability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Understanding that trade-off helps you make better decisions when designing distributed systems, databases, and highly available applications.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>database</category>
      <category>distributedsystems</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
