<?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>CORS Explained: Why Your Browser Blocks Your API</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Fri, 25 Sep 2026 12:17:44 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/cors-explained-why-your-browser-blocks-your-api-43fk</link>
      <guid>https://dev.to/omeiza_ahmed/cors-explained-why-your-browser-blocks-your-api-43fk</guid>
      <description>&lt;p&gt;You build an API.&lt;/p&gt;

&lt;p&gt;Your frontend sends a request.&lt;/p&gt;

&lt;p&gt;The API responds successfully.&lt;/p&gt;

&lt;p&gt;And somehow, the browser still says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Blocked by CORS policy.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What just happened?&lt;/p&gt;

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

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

&lt;p&gt;&lt;strong&gt;CORS (Cross-Origin Resource Sharing)&lt;/strong&gt; is a browser security mechanism that controls whether a web page can make requests to a different &lt;strong&gt;origin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An origin is made up of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol&lt;/li&gt;
&lt;li&gt;Domain&lt;/li&gt;
&lt;li&gt;Port&lt;/li&gt;
&lt;/ul&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;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are different origins because their ports are different.&lt;/p&gt;

&lt;p&gt;So if your React application runs on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and your ASP.NET API runs on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the browser treats the request as cross-origin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does CORS Exist?
&lt;/h2&gt;

&lt;p&gt;Imagine a user is logged into their banking website.&lt;/p&gt;

&lt;p&gt;Now imagine another website could freely make requests to that banking API using the user's browser.&lt;/p&gt;

&lt;p&gt;That could create serious security problems.&lt;/p&gt;

&lt;p&gt;The browser therefore follows the &lt;strong&gt;same-origin policy&lt;/strong&gt; by default.&lt;/p&gt;

&lt;p&gt;CORS provides a controlled way for servers to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Requests from this particular origin are allowed."&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Suppose your frontend does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your frontend is running on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser sees two different origins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend:
https://app.example.com

API:
https://api.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API needs to explicitly allow the frontend's origin.&lt;/p&gt;

&lt;p&gt;A server might respond with:&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;Access-Control-Allow-Origin: https://app.example.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser sees this header and knows that the frontend is allowed to access the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  CORS in ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;In ASP.NET Core, you can configure CORS using a policy.&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="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FrontendPolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;policy&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://app.example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyMethod&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;Then apply the policy:&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FrontendPolicy"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the API allows requests from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What About &lt;code&gt;AllowAnyOrigin()&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;You might see 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="n"&gt;policy&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyOrigin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyMethod&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means requests from any origin can access the API's CORS-enabled responses.&lt;/p&gt;

&lt;p&gt;It's convenient during development, but you should be deliberate about using it in production.&lt;/p&gt;

&lt;p&gt;If your application only needs to communicate with one frontend, explicitly specify that origin:&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;WithOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://app.example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Is a Preflight Request?
&lt;/h2&gt;

&lt;p&gt;Sometimes the browser sends an &lt;strong&gt;OPTIONS&lt;/strong&gt; request before the actual request.&lt;/p&gt;

&lt;p&gt;This is called a &lt;strong&gt;preflight request&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, your frontend wants to send:&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;POST /api/users
Authorization: Bearer ...
Content-Type: application/json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser may first ask the server:&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;OPTIONS /api/users
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with headers describing the intended request.&lt;/p&gt;

&lt;p&gt;The server responds with something like:&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;Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the browser is satisfied with the response, it sends the actual &lt;code&gt;POST&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;So when debugging CORS, don't only look at the request you expected. Check whether an &lt;strong&gt;OPTIONS&lt;/strong&gt; request is failing first.&lt;/p&gt;

&lt;h2&gt;
  
  
  CORS Is a Browser Restriction
&lt;/h2&gt;

&lt;p&gt;This is one of the most important things to understand.&lt;/p&gt;

&lt;p&gt;CORS is primarily enforced by browsers.&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;React → Browser → API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser checks the CORS rules.&lt;/p&gt;

&lt;p&gt;But if you make the same request using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Postman → API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you may not see the same CORS error.&lt;/p&gt;

&lt;p&gt;That's because Postman isn't enforcing browser CORS rules in the same way.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"It works in Postman but not in my frontend"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;is often a strong clue that you're dealing with CORS.&lt;/p&gt;

&lt;h2&gt;
  
  
  CORS ≠ Authentication
&lt;/h2&gt;

&lt;p&gt;CORS doesn't determine whether a user is authenticated.&lt;/p&gt;

&lt;p&gt;These are different concerns.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Who are you?&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Are you allowed to access this resource?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;CORS&lt;/strong&gt; asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this browser-based origin allowed to access the response?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, your API can correctly validate a JWT and still reject the browser's access because the CORS configuration doesn't allow the frontend's origin.&lt;/p&gt;

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

&lt;p&gt;Developers sometimes see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CORS error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and immediately add:&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;AllowAnyOrigin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may hide the immediate problem, but it doesn't necessarily explain what caused it.&lt;/p&gt;

&lt;p&gt;Instead, check:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is the frontend origin correct?&lt;/li&gt;
&lt;li&gt;Is the API returning the correct CORS headers?&lt;/li&gt;
&lt;li&gt;Is the OPTIONS preflight succeeding?&lt;/li&gt;
&lt;li&gt;Are the required headers allowed?&lt;/li&gt;
&lt;li&gt;Are the required HTTP methods allowed?&lt;/li&gt;
&lt;li&gt;Is middleware configured in the correct order?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Understanding the request flow is much more useful than simply disabling the restriction.&lt;/p&gt;

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

&lt;p&gt;CORS isn't your API randomly refusing requests.&lt;/p&gt;

&lt;p&gt;It's the browser enforcing a security boundary between different origins.&lt;/p&gt;

&lt;p&gt;Once you understand &lt;strong&gt;origin, same-origin policy, preflight requests, and CORS response headers&lt;/strong&gt;, those confusing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blocked by CORS policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;errors become much easier to debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't just add &lt;code&gt;AllowAnyOrigin()&lt;/code&gt; because the error disappeared. Understand why the browser rejected the request in the first place.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>frontend</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Webhooks vs Polling: How Should Your Systems Communicate?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Thu, 24 Sep 2026 09:43:04 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/webhooks-vs-polling-how-should-your-systems-communicate-gl7</link>
      <guid>https://dev.to/omeiza_ahmed/webhooks-vs-polling-how-should-your-systems-communicate-gl7</guid>
      <description>&lt;p&gt;Your application needs to know when something happens.&lt;/p&gt;

&lt;p&gt;A payment succeeds.&lt;br&gt;
An order is shipped.&lt;br&gt;
A GitHub issue is created.&lt;/p&gt;

&lt;p&gt;The question is: &lt;strong&gt;should your application keep asking for updates, or should the other system notify you when something happens?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s the difference between &lt;strong&gt;polling and webhooks&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Polling: “Has anything happened yet?”
&lt;/h2&gt;

&lt;p&gt;With polling, your application repeatedly asks another system for updates.&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 http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/payment/123
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your application might make this request every 5 seconds:&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 payment complete?
    ↓
    No
    ↓
Wait 5 seconds
    ↓
Is the payment complete?
    ↓
    No
    ↓
Wait 5 seconds
    ↓
Is the payment complete?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eventually, the payment changes to &lt;code&gt;successful&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;Most of those requests may return the same answer.&lt;/p&gt;

&lt;p&gt;If you have thousands of users doing this, you're generating a lot of unnecessary requests.&lt;/p&gt;

&lt;p&gt;Polling is simple, but it can be wasteful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Webhooks: “I’ll tell you when it happens.”
&lt;/h2&gt;

&lt;p&gt;With a webhook, the receiving application provides an endpoint that another system can call when an event occurs.&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 http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /webhooks/payment
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the payment succeeds, the payment provider sends:&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;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment.success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"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;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50000&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;Instead of asking repeatedly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Did the payment succeed?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your application gets notified:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The payment succeeded.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is an &lt;strong&gt;event-driven approach&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Webhooks vs Polling
&lt;/h2&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;Polling&lt;/th&gt;
&lt;th&gt;Webhooks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Communication&lt;/td&gt;
&lt;td&gt;Client asks repeatedly&lt;/td&gt;
&lt;td&gt;Server sends event&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timing&lt;/td&gt;
&lt;td&gt;Based on polling interval&lt;/td&gt;
&lt;td&gt;Usually near real-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;Can generate many unnecessary requests&lt;/td&gt;
&lt;td&gt;Only sends when an event occurs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complexity&lt;/td&gt;
&lt;td&gt;Simpler to implement&lt;/td&gt;
&lt;td&gt;Requires webhook endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;Easy to retry requests&lt;/td&gt;
&lt;td&gt;Requires handling retries/duplicates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Periodic checks&lt;/td&gt;
&lt;td&gt;Event-driven updates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  When should you use polling?
&lt;/h2&gt;

&lt;p&gt;Polling makes sense when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The external system doesn't support webhooks.&lt;/li&gt;
&lt;li&gt;You need to periodically synchronize data.&lt;/li&gt;
&lt;li&gt;You don't need real-time updates.&lt;/li&gt;
&lt;li&gt;You want a simple implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, your application might check an external API every 10 minutes for new records.&lt;/p&gt;




&lt;h2&gt;
  
  
  When should you use webhooks?
&lt;/h2&gt;

&lt;p&gt;Webhooks are useful when you need to react to events quickly.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Payment notifications&lt;/li&gt;
&lt;li&gt;Order status changes&lt;/li&gt;
&lt;li&gt;GitHub events&lt;/li&gt;
&lt;li&gt;Email delivery events&lt;/li&gt;
&lt;li&gt;Subscription changes&lt;/li&gt;
&lt;li&gt;CI/CD events&lt;/li&gt;
&lt;/ul&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;Customer pays
     ↓
Payment provider
     ↓
Webhook
     ↓
Your API
     ↓
Update order
     ↓
Send confirmation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No constant checking required.&lt;/p&gt;




&lt;h2&gt;
  
  
  One important webhook problem
&lt;/h2&gt;

&lt;p&gt;Webhooks aren't automatically reliable just because they're event-driven.&lt;/p&gt;

&lt;p&gt;The sender might retry an event if your server doesn't respond successfully.&lt;/p&gt;

&lt;p&gt;That means you could receive the same webhook more than once.&lt;/p&gt;

&lt;p&gt;Your application should therefore handle &lt;strong&gt;idempotency&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;payment.success
payment.success
payment.success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your system should still process the payment only once.&lt;/p&gt;

&lt;p&gt;A common approach is to store the webhook's unique event ID and ignore events that have already been processed.&lt;/p&gt;

&lt;p&gt;You should also verify webhook signatures so that arbitrary clients can't impersonate the service sending your events.&lt;/p&gt;




&lt;h2&gt;
  
  
  The key takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Polling asks, “Has anything changed?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhooks say, “Something changed.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need periodic synchronization or the external service doesn't provide events, polling can be perfectly reasonable.&lt;/p&gt;

&lt;p&gt;But when you're reacting to well-defined events, webhooks can reduce unnecessary requests and provide a much more responsive architecture.&lt;/p&gt;

&lt;p&gt;Choose based on the communication pattern your system actually needs—not simply because one approach sounds more modern.&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cursor Pagination vs Offset Pagination: Which One Should You Use?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Wed, 23 Sep 2026 13:40:48 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/cursor-pagination-vs-offset-pagination-which-one-should-you-use-4c36</link>
      <guid>https://dev.to/omeiza_ahmed/cursor-pagination-vs-offset-pagination-which-one-should-you-use-4c36</guid>
      <description>&lt;p&gt;Pagination looks simple until your dataset gets large.&lt;/p&gt;

&lt;p&gt;At first, &lt;code&gt;page=2&amp;amp;limit=20&lt;/code&gt; seems perfectly fine. But as your application grows, pagination strategy can start affecting &lt;strong&gt;query performance, consistency, and user experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Two common approaches are &lt;strong&gt;offset pagination&lt;/strong&gt; and &lt;strong&gt;cursor pagination&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s break down how they work and when to use each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Offset Pagination
&lt;/h2&gt;

&lt;p&gt;Offset pagination works by telling the database:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Skip these records and give me the next batch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&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;GET /api/products?page=3&amp;amp;limit=20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database might translate this into:&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;Products&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;
&lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="k"&gt;ROWS&lt;/span&gt;
&lt;span class="k"&gt;FETCH&lt;/span&gt; &lt;span class="k"&gt;NEXT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="k"&gt;ROWS&lt;/span&gt; &lt;span class="k"&gt;ONLY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first page skips &lt;code&gt;0&lt;/code&gt; records, the second skips &lt;code&gt;20&lt;/code&gt;, and the third skips &lt;code&gt;40&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem with large offsets
&lt;/h3&gt;

&lt;p&gt;As the offset gets larger, the database may have to scan and skip a lot of rows before returning the records you actually want.&lt;/p&gt;

&lt;p&gt;Imagine requesting:&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;GET /api/products?page=50000&amp;amp;limit=20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database potentially has to work through a huge number of records before returning just 20.&lt;/p&gt;

&lt;p&gt;This can become expensive with large datasets.&lt;/p&gt;

&lt;p&gt;There is another problem: &lt;strong&gt;changing data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine you're viewing page 2 while new records are inserted at the beginning of the dataset.&lt;/p&gt;

&lt;p&gt;Records can shift between pages, meaning you might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See the same record twice&lt;/li&gt;
&lt;li&gt;Miss a record&lt;/li&gt;
&lt;li&gt;Get inconsistent results between requests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cursor Pagination
&lt;/h2&gt;

&lt;p&gt;Cursor pagination takes a different approach.&lt;/p&gt;

&lt;p&gt;Instead of saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Skip 40 records.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me the records after this specific position.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&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;GET /api/products?limit=20&amp;amp;cursor=eyJpZCI6NDA...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cursor represents a position in the dataset.&lt;/p&gt;

&lt;p&gt;A simplified query could look like:&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;Products&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response might contain:&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;"data"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;products&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;span class="nl"&gt;"nextCursor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJpZCI6NjA..."&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 client uses &lt;code&gt;nextCursor&lt;/code&gt; to request the next batch.&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;GET /api/products?limit=20&amp;amp;cursor=eyJpZCI6NjA...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database can efficiently find records after the cursor, especially when the ordering column is properly indexed.&lt;/p&gt;




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

&lt;p&gt;The simplest way to remember it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offset pagination asks:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How many records should I skip?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Cursor pagination asks:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where should I continue from?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference becomes important as your dataset grows.&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;Offset&lt;/th&gt;
&lt;th&gt;Cursor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple to implement&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jump directly to page 50&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good for large datasets&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handles changing datasets well&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works well for infinite scrolling&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires a stable ordering&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy page numbers&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  When Should You Use Offset Pagination?
&lt;/h2&gt;

&lt;p&gt;Offset pagination is often a good choice for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin dashboards&lt;/li&gt;
&lt;li&gt;Search results&lt;/li&gt;
&lt;li&gt;Small-to-medium datasets&lt;/li&gt;
&lt;li&gt;Interfaces where users need page numbers&lt;/li&gt;
&lt;li&gt;Applications where jumping to a specific page matters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&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;GET /api/users?page=5&amp;amp;limit=25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's simple, familiar, and often perfectly adequate.&lt;/p&gt;

&lt;p&gt;Don't introduce cursor pagination just because your application uses a database.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Use Cursor Pagination?
&lt;/h2&gt;

&lt;p&gt;Cursor pagination becomes more useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your dataset is large&lt;/li&gt;
&lt;li&gt;Data changes frequently&lt;/li&gt;
&lt;li&gt;You're building infinite scrolling&lt;/li&gt;
&lt;li&gt;You're building feeds or timelines&lt;/li&gt;
&lt;li&gt;Consistent traversal matters&lt;/li&gt;
&lt;li&gt;You need efficient pagination deep into a dataset&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, social media feeds are a natural fit.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Give me page 50.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Give me the next 20 posts after this cursor.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  One Important Detail: Your Cursor Needs an Order
&lt;/h2&gt;

&lt;p&gt;Cursor pagination isn't simply:&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;WHERE&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;cursor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you're done.&lt;/p&gt;

&lt;p&gt;Your ordering needs to be &lt;strong&gt;stable and deterministic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you're ordering by:&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="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;multiple records could have the same timestamp.&lt;/p&gt;

&lt;p&gt;A common solution is using a combination 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;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cursor can then contain both values:&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;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-23T12:30:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4821&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;This gives the database an unambiguous position to continue from.&lt;/p&gt;

&lt;p&gt;In production systems, cursors are also commonly encoded or signed so clients don't have to manipulate internal pagination values directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  So Which Should You Choose?
&lt;/h2&gt;

&lt;p&gt;Don't choose based on which one sounds more advanced.&lt;/p&gt;

&lt;p&gt;Choose based on the requirements of your application.&lt;/p&gt;

&lt;p&gt;If you need &lt;strong&gt;simple page navigation&lt;/strong&gt;, offset pagination may be enough.&lt;/p&gt;

&lt;p&gt;If you need &lt;strong&gt;efficient traversal through a large, frequently changing dataset&lt;/strong&gt;, cursor pagination is often a better fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Offset pagination is about pages. Cursor pagination is about position.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Offset pagination is simpler and gives you familiar page-based navigation.&lt;/p&gt;

&lt;p&gt;Cursor pagination requires more thought, but it can provide more consistent and efficient traversal as your dataset grows.&lt;/p&gt;

&lt;p&gt;The best pagination strategy isn't the most sophisticated one.&lt;/p&gt;

&lt;p&gt;It's the one that fits the way your users actually consume your data.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>database</category>
      <category>performance</category>
      <category>sql</category>
    </item>
    <item>
      <title>HTTP/1.1 vs HTTP/2 vs HTTP/3: What Actually Changed?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Tue, 22 Sep 2026 13:11:19 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/http11-vs-http2-vs-http3-what-actually-changed-18c1</link>
      <guid>https://dev.to/omeiza_ahmed/http11-vs-http2-vs-http3-what-actually-changed-18c1</guid>
      <description>&lt;p&gt;HTTP started simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Client sends a request. Server sends a response.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But modern applications don't make just one request.&lt;/p&gt;

&lt;p&gt;A typical web page might load dozens or hundreds of resources — APIs, images, JavaScript, CSS, fonts, and more.&lt;/p&gt;

&lt;p&gt;That is where HTTP/1.1 started showing its age.&lt;/p&gt;

&lt;p&gt;HTTP/2 improved things significantly. HTTP/3 changed the underlying transport completely.&lt;/p&gt;

&lt;p&gt;Let's break down what actually changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP/1.1: Simple, But Sequential
&lt;/h2&gt;

&lt;p&gt;HTTP/1.1 uses TCP and traditionally processes requests in a way that can cause &lt;strong&gt;head-of-line blocking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1 ────────&amp;gt; Response 1
Request 2 ────────────────&amp;gt; Response 2
Request 3 ─────────────────────&amp;gt; Response 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Request 1 is delayed, other requests can be affected.&lt;/p&gt;

&lt;p&gt;Browsers worked around this by opening multiple TCP connections, but that came with additional overhead.&lt;/p&gt;

&lt;p&gt;HTTP/1.1 also introduced useful features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent connections&lt;/li&gt;
&lt;li&gt;Chunked transfer encoding&lt;/li&gt;
&lt;li&gt;Better caching mechanisms&lt;/li&gt;
&lt;li&gt;Pipelining support, although it was rarely used effectively&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It worked — but the web had become much more demanding.&lt;/p&gt;




&lt;h2&gt;
  
  
  HTTP/2: Multiple Requests Over One Connection
&lt;/h2&gt;

&lt;p&gt;HTTP/2 kept TCP but changed how HTTP messages are transferred.&lt;/p&gt;

&lt;p&gt;The biggest improvement?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiplexing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of waiting for one request to finish before processing another, multiple streams can share the same TCP connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             ┌── Request 1
             ├── Request 2
TCP ─────────┼── Request 3
             ├── Request 4
             └── Request 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces the need for multiple connections and makes it much more efficient to load many resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Binary Instead of Text
&lt;/h3&gt;

&lt;p&gt;HTTP/1.1 messages are text-based.&lt;/p&gt;

&lt;p&gt;HTTP/2 uses a &lt;strong&gt;binary framing layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That allows the protocol to break requests and responses into smaller frames and efficiently interleave them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Header Compression
&lt;/h3&gt;

&lt;p&gt;HTTP/2 introduced &lt;strong&gt;HPACK&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of repeatedly sending the same HTTP headers, connections can compress and reuse header information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Push
&lt;/h3&gt;

&lt;p&gt;HTTP/2 also introduced server push, allowing servers to send resources before the client explicitly requested them.&lt;/p&gt;

&lt;p&gt;However, browser support and real-world usefulness were limited, and server push has since been removed from modern browser implementations.&lt;/p&gt;




&lt;h2&gt;
  
  
  HTTP/3: HTTP Over QUIC
&lt;/h2&gt;

&lt;p&gt;HTTP/3 makes the biggest architectural change.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP → TCP → IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTTP/3 uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/3 → QUIC → UDP → IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't let the use of UDP fool you.&lt;/p&gt;

&lt;p&gt;QUIC provides the reliability, ordering, congestion control, and security mechanisms needed for HTTP traffic.&lt;/p&gt;

&lt;p&gt;And it does this at the transport layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Big Difference: Head-of-Line Blocking
&lt;/h2&gt;

&lt;p&gt;Here's where HTTP/3 becomes particularly interesting.&lt;/p&gt;

&lt;p&gt;With HTTP/2, multiple streams share one TCP connection.&lt;/p&gt;

&lt;p&gt;If a TCP packet is lost, TCP needs to retransmit it before the affected data can be delivered.&lt;/p&gt;

&lt;p&gt;That can cause &lt;strong&gt;transport-level head-of-line blocking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;HTTP/3's QUIC uses independent streams.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/2

TCP Connection
├── Stream 1 ── X
├── Stream 2 ── X
└── Stream 3 ── X

Packet loss can affect the connection's delivery.

HTTP/3

QUIC Connection
├── Stream 1 ── X
├── Stream 2 ── ✓
└── Stream 3 ── ✓

Other streams can continue progressing.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's especially useful on networks where packet loss is common.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connection Establishment
&lt;/h2&gt;

&lt;p&gt;HTTP/3 also improves connection setup.&lt;/p&gt;

&lt;p&gt;QUIC integrates TLS 1.3 into the protocol.&lt;/p&gt;

&lt;p&gt;This reduces the number of round trips required to establish a secure connection compared with traditional TCP + TLS setup.&lt;/p&gt;

&lt;p&gt;QUIC also supports &lt;strong&gt;connection migration&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, if your device moves from Wi-Fi to mobile data, a QUIC connection can potentially continue without establishing an entirely new connection.&lt;/p&gt;




&lt;h2&gt;
  
  
  HTTP/1.1 vs HTTP/2 vs HTTP/3
&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;HTTP/1.1&lt;/th&gt;
&lt;th&gt;HTTP/2&lt;/th&gt;
&lt;th&gt;HTTP/3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Transport&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;QUIC over UDP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiplexing&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary framing&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Header compression&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;HPACK&lt;/td&gt;
&lt;td&gt;QPACK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transport HOL blocking&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS&lt;/td&gt;
&lt;td&gt;Separate&lt;/td&gt;
&lt;td&gt;Separate&lt;/td&gt;
&lt;td&gt;Built into QUIC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection migration&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important thing isn't memorizing the table.&lt;/p&gt;

&lt;p&gt;It's understanding the progression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1
   ↓
Multiple connections

HTTP/2
   ↓
Multiplexing over TCP

HTTP/3
   ↓
Multiplexing over QUIC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Should Developers Care About?
&lt;/h2&gt;

&lt;p&gt;You usually don't implement HTTP/2 or HTTP/3 yourself.&lt;/p&gt;

&lt;p&gt;Your web server, reverse proxy, CDN, browser, and networking stack handle most of the protocol details.&lt;/p&gt;

&lt;p&gt;As a backend developer, what's important is understanding the implications.&lt;/p&gt;

&lt;p&gt;For example, if you're building an API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   ↓
HTTP/3
   ↓
CDN / Reverse Proxy
   ↓
ASP.NET Core API
   ↓
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your application code can remain largely the same while the underlying HTTP protocol changes how efficiently requests travel across the network.&lt;/p&gt;




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

&lt;p&gt;HTTP/1.1 made the modern web possible.&lt;/p&gt;

&lt;p&gt;HTTP/2 made multiple requests much more efficient through multiplexing.&lt;/p&gt;

&lt;p&gt;HTTP/3 takes that further by moving HTTP onto QUIC, reducing the impact of packet loss and improving connection establishment and migration.&lt;/p&gt;

&lt;p&gt;So don't think of HTTP/3 as simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"HTTP/2 but faster."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's a fundamental change in how HTTP communicates over the network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/1.1 optimized connections.&lt;br&gt;
HTTP/2 optimized streams.&lt;br&gt;
HTTP/3 optimized the transport underneath them.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>OpenTelemetry in .NET: Stop Guessing What Your Application Is Doing</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Mon, 21 Sep 2026 15:13:25 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/opentelemetry-in-net-stop-guessing-what-your-application-is-doing-3dp5</link>
      <guid>https://dev.to/omeiza_ahmed/opentelemetry-in-net-stop-guessing-what-your-application-is-doing-3dp5</guid>
      <description>&lt;p&gt;Your API is slow.&lt;/p&gt;

&lt;p&gt;But why?&lt;/p&gt;

&lt;p&gt;Is the database taking too long?&lt;br&gt;
Is another service failing?&lt;br&gt;
Is an external API responding slowly?&lt;/p&gt;

&lt;p&gt;Logs can give you clues, but when you're dealing with a distributed application, logs alone can make debugging painful.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;OpenTelemetry&lt;/strong&gt; comes in.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is OpenTelemetry?
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry (OTel) is an open-source observability framework for collecting telemetry data from your applications.&lt;/p&gt;

&lt;p&gt;It focuses mainly on three types of data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traces&lt;/strong&gt; — What happened during a request?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt; — How is the application performing?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt; — What events are happening?&lt;/li&gt;
&lt;/ul&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Understand what your application is doing without guessing.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Why Does This Matter in .NET?
&lt;/h2&gt;

&lt;p&gt;Imagine a request going through your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  ↓
ASP.NET Core API
  ↓
Order Service
  ↓
Payment Service
  ↓
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user only sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request took 3.2 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But where did those 3.2 seconds go?&lt;/p&gt;

&lt;p&gt;OpenTelemetry can give you a trace like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP Request          3.2s
 ├── Order Service    1.1s
 ├── Payment API      1.7s
 └── Database         0.4s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have something useful.&lt;/p&gt;

&lt;p&gt;Instead of saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The API is slow."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Payment API is responsible for most of the request latency."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the difference between logging events and understanding system behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  Traces: Following a Request
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;trace&lt;/strong&gt; represents the journey of a request through your system.&lt;/p&gt;

&lt;p&gt;Each operation within that journey is represented as a &lt;strong&gt;span&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;Trace
│
├── HTTP GET /orders
│
├── SQL Query
│
└── HTTP POST /payments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each span can contain information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duration&lt;/li&gt;
&lt;li&gt;Operation name&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Attributes&lt;/li&gt;
&lt;li&gt;Errors&lt;/li&gt;
&lt;li&gt;Relationships to other spans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is that these spans can be connected together into one trace.&lt;/p&gt;




&lt;h2&gt;
  
  
  Metrics: Measuring Performance
&lt;/h2&gt;

&lt;p&gt;Metrics give you numbers about your application.&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;HTTP Requests:       15,420
Request Errors:          73
Average Duration:      180ms
Active Requests:          12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Metrics are useful when you want to answer questions like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Are errors increasing?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Has API latency gotten worse?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Logs: Understanding Events
&lt;/h2&gt;

&lt;p&gt;Logs record events happening inside your application.&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;Order 4821 created
Payment request started
Payment failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenTelemetry can also help correlate logs with traces.&lt;/p&gt;

&lt;p&gt;That means you can go from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trace → Span → Log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and understand what happened during a specific request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up OpenTelemetry in ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
dotnet add package OpenTelemetry.Instrumentation.Runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure OpenTelemetry in &lt;code&gt;Program.cs&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="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTracing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracing&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tracing&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAspNetCoreInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHttpClientInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOtlpExporter&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="nf"&gt;WithMetrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAspNetCoreInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRuntimeInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOtlpExporter&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;Now your application can automatically collect telemetry from common ASP.NET Core and HTTP operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Does the Data Go?
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry doesn't try to be your dashboard.&lt;/p&gt;

&lt;p&gt;Instead, it collects and exports telemetry to an observability backend.&lt;/p&gt;

&lt;p&gt;A common architecture looks 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;.NET Application
       │
       ▼
 OpenTelemetry
       │
       ▼
   OTLP Exporter
       │
       ▼
Observability Backend
       │
       ▼
    Dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use tools such as Grafana, Jaeger, Zipkin, or other systems that support OpenTelemetry.&lt;/p&gt;

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

&lt;p&gt;Your application produces telemetry.&lt;/p&gt;

&lt;p&gt;Your observability platform stores, analyzes, and visualizes it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automatic vs Manual Instrumentation
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry can automatically instrument many common operations.&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="nf"&gt;AddAspNetCoreInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHttpClientInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can give you useful telemetry without manually creating spans for every request.&lt;/p&gt;

&lt;p&gt;But sometimes you want to track your own business operations.&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="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ProcessOrder"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"order.id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customer.id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a custom span representing your business operation.&lt;/p&gt;

&lt;p&gt;This becomes useful when infrastructure-level telemetry isn't enough to understand your application's behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  OpenTelemetry Is Not Just Logging
&lt;/h2&gt;

&lt;p&gt;This is one of the most important distinctions.&lt;/p&gt;

&lt;p&gt;Traditional logging might tell you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment failed for order 4821
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A trace can tell you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
  ↓
Create Order
  ↓
Database Query       120ms
  ↓
Payment API          1.8s
  ↓
Payment Failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second gives you &lt;strong&gt;context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's why observability becomes increasingly important as applications become distributed.&lt;/p&gt;




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

&lt;p&gt;OpenTelemetry gives your .NET applications a standardized way to collect &lt;strong&gt;traces, metrics, and logs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why is this request slow?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;you can investigate the actual path the request took.&lt;/p&gt;

&lt;p&gt;For a small application, you might get away with logs.&lt;/p&gt;

&lt;p&gt;For a system with multiple services, databases, queues, and external APIs, observability becomes much harder to ignore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't just collect logs. Understand the journey of your requests.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>dotnet</category>
      <category>monitoring</category>
      <category>performance</category>
    </item>
    <item>
      <title>Rate Limiting: The Traffic Cop Your API Needs</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Sun, 20 Sep 2026 12:51:44 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/rate-limiting-the-traffic-cop-your-api-needs-3b1l</link>
      <guid>https://dev.to/omeiza_ahmed/rate-limiting-the-traffic-cop-your-api-needs-3b1l</guid>
      <description>&lt;p&gt;Your API can be perfectly designed and still fail when too many requests hit it at once.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;rate limiting&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;Rate limiting controls how many requests a client can make to your API within a specific period.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;A user can make &lt;strong&gt;100 requests per minute&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Request #101? They have to wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do We Need Rate Limiting?
&lt;/h2&gt;

&lt;p&gt;Without rate limiting, a single client could send thousands of requests to your API and consume resources that should be available to everyone else.&lt;/p&gt;

&lt;p&gt;Rate limiting helps protect against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Abuse and spam&lt;/li&gt;
&lt;li&gt;Brute-force attacks&lt;/li&gt;
&lt;li&gt;Accidental request floods&lt;/li&gt;
&lt;li&gt;Resource exhaustion&lt;/li&gt;
&lt;li&gt;Excessive API usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also helps keep your API predictable under heavy traffic.&lt;/p&gt;

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

&lt;p&gt;Imagine you have:&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;GET /api/products
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You configure a limit of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100 requests / minute / client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A client makes 100 requests within the minute.&lt;/p&gt;

&lt;p&gt;The next request could receive:&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;429 Too Many Requests
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API is basically saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Slow down. You've reached your limit."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Does Rate Limiting Know Who to Limit?
&lt;/h2&gt;

&lt;p&gt;The limit can be applied based on different identifiers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IP address&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.20 → 100 requests/minute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for controlling anonymous traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 123 → 1,000 requests/hour
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful when users are authenticated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API key&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_KEY_ABC → 10,000 requests/day
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common for public APIs and third-party integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Rate-Limiting Algorithms
&lt;/h2&gt;

&lt;p&gt;There are several ways to implement rate limiting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixed Window
&lt;/h3&gt;

&lt;p&gt;Requests are counted within fixed time periods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;12:00 - 12:01 → 100 requests
12:01 - 12:02 → 100 requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, but traffic can spike around the boundary between windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sliding Window
&lt;/h3&gt;

&lt;p&gt;Instead of using fixed time blocks, the system looks at a continuously moving time window.&lt;/p&gt;

&lt;p&gt;This provides more accurate control over request bursts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Bucket
&lt;/h3&gt;

&lt;p&gt;The system maintains a bucket of tokens.&lt;/p&gt;

&lt;p&gt;Each request consumes a token.&lt;/p&gt;

&lt;p&gt;Tokens are continuously added back at a fixed rate.&lt;/p&gt;

&lt;p&gt;This allows controlled bursts while still enforcing an average request rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rate Limiting in ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;ASP.NET Core provides built-in rate-limiting middleware.&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="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRateLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFixedWindowLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limiterOptions&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;limiterOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PermitLimit&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="n"&gt;limiterOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&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;Then enable it in the request pipeline:&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseRateLimiter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also apply a policy to specific endpoints instead of limiting your entire API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rate Limiting vs Authentication
&lt;/h2&gt;

&lt;p&gt;These solve different problems.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Who are you?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting asks:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How many requests are you allowed to make?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An authenticated user can still abuse an API, so authentication does not replace rate limiting.&lt;/p&gt;

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

&lt;p&gt;Rate limiting isn't just about blocking excessive requests.&lt;/p&gt;

&lt;p&gt;It's about &lt;strong&gt;protecting your API, controlling resource usage, and making sure one client doesn't negatively affect everyone else.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your API is exposed to the internet, don't just ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can users access this endpoint?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How often should they be allowed to access it?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>performance</category>
      <category>security</category>
    </item>
    <item>
      <title>Process vs Thread: What’s Really Running Your Application?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Sat, 19 Sep 2026 07:24:26 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/process-vs-thread-whats-really-running-your-application-185h</link>
      <guid>https://dev.to/omeiza_ahmed/process-vs-thread-whats-really-running-your-application-185h</guid>
      <description>&lt;p&gt;When your application is running, it isn’t just “executing code.”&lt;/p&gt;

&lt;p&gt;The operating system is managing &lt;strong&gt;processes&lt;/strong&gt; and &lt;strong&gt;threads&lt;/strong&gt; behind the scenes.&lt;/p&gt;

&lt;p&gt;Understanding the difference matters because it affects performance, memory usage, concurrency, and how applications communicate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Process?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;process&lt;/strong&gt; is a running instance of a program.&lt;/p&gt;

&lt;p&gt;For example, when you open Chrome, your operating system creates one or more processes to run it.&lt;/p&gt;

&lt;p&gt;A process has its own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory space&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;li&gt;File handles&lt;/li&gt;
&lt;li&gt;Security context&lt;/li&gt;
&lt;li&gt;Threads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of a process as a &lt;strong&gt;house&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The house has its own resources and is separated from other houses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Process A
├── Memory
├── Resources
└── Threads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Process A crashes, Process B generally isn't directly affected because they have separate memory spaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Thread?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;thread&lt;/strong&gt; is an execution path inside a process.&lt;/p&gt;

&lt;p&gt;A process can contain multiple threads that execute work concurrently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Process
├── Thread 1
├── Thread 2
└── Thread 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the house analogy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A process is the house.&lt;br&gt;
Threads are the people working inside it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They share the house's resources, but each person can work on a different task.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Biggest Difference
&lt;/h2&gt;

&lt;p&gt;The most important difference is &lt;strong&gt;memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Processes have separate memory spaces.&lt;/p&gt;

&lt;p&gt;Threads within the same process share memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Process A                 Process B
┌───────────────┐         ┌───────────────┐
│ Shared by     │         │ Shared by     │
│ its threads   │         │ its threads   │
│               │         │               │
│ Thread 1      │         │ Thread 1      │
│ Thread 2      │         │ Thread 2      │
└───────────────┘         └───────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Threads in Process A cannot simply access Process B's memory.&lt;/p&gt;

&lt;p&gt;But Thread 1 and Thread 2 inside Process A can access the same process memory.&lt;/p&gt;

&lt;p&gt;That's useful for communication, but it also introduces problems such as &lt;strong&gt;race conditions&lt;/strong&gt; and the need for synchronization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process vs Thread
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Process&lt;/th&gt;
&lt;th&gt;Thread&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Independent running program&lt;/td&gt;
&lt;td&gt;Execution unit inside a process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Has its own memory space&lt;/td&gt;
&lt;td&gt;Shares process memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;More expensive to create&lt;/td&gt;
&lt;td&gt;Cheaper to create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Communication is more involved&lt;/td&gt;
&lt;td&gt;Communication is easier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Better isolation&lt;/td&gt;
&lt;td&gt;Less isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can contain multiple threads&lt;/td&gt;
&lt;td&gt;Belongs to a process&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;Imagine a web server receiving requests.&lt;/p&gt;

&lt;p&gt;Instead of processing everything sequentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1 → Process
Request 2 → Process
Request 3 → Process
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A process can use multiple threads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Web Server Process
├── Thread 1 → Request 1
├── Thread 2 → Request 2
└── Thread 3 → Request 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now multiple pieces of work can be handled concurrently.&lt;/p&gt;

&lt;p&gt;Modern applications often go further and use &lt;strong&gt;thread pools&lt;/strong&gt;, asynchronous programming, processes, or a combination of these rather than manually creating a new thread for every request.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens When a Thread Crashes?
&lt;/h2&gt;

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

&lt;p&gt;A problem in one thread can potentially affect the entire process because threads share the process's resources.&lt;/p&gt;

&lt;p&gt;A process provides stronger isolation.&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;Process A              Process B
   │                      │
 Thread 1              Thread 1
 Thread 2              Thread 2
   │
   X Crash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A failure in Process A doesn't automatically mean Process B crashes.&lt;/p&gt;

&lt;p&gt;That's one reason operating systems use processes as an important isolation boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You Think About Processes vs Threads?
&lt;/h2&gt;

&lt;p&gt;Think about &lt;strong&gt;processes&lt;/strong&gt; when isolation and independent resources matter.&lt;/p&gt;

&lt;p&gt;Think about &lt;strong&gt;threads&lt;/strong&gt; when multiple tasks need to execute within the same application and share data efficiently.&lt;/p&gt;

&lt;p&gt;But in modern development, you usually won't manually choose between them for every task.&lt;/p&gt;

&lt;p&gt;Frameworks and runtimes such as .NET provide abstractions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Task&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;async/await&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ThreadPool&lt;/li&gt;
&lt;li&gt;Background services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These allow you to handle concurrent work without manually managing every operating-system thread.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;process is an isolated running program with its own memory space.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;thread is an execution unit inside a process that shares the process's memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simplest way to remember it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Process = container. Thread = worker inside the container.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you understand that relationship, concepts like concurrency, parallelism, thread safety, synchronization, and async programming become much easier to reason about.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>YAML vs JSON: Same Data, Different Trade-offs</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Fri, 18 Sep 2026 10:28:35 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/yaml-vs-json-same-data-different-trade-offs-4lla</link>
      <guid>https://dev.to/omeiza_ahmed/yaml-vs-json-same-data-different-trade-offs-4lla</guid>
      <description>&lt;p&gt;&lt;strong&gt;Your application doesn't care whether the configuration is YAML or JSON. But you might.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both YAML and JSON are popular formats for representing structured data. You'll see them everywhere in modern development — from API responses and configuration files to Docker and CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;So, what's the actual difference?&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON: Simple and Strict
&lt;/h2&gt;

&lt;p&gt;JSON stands for &lt;strong&gt;JavaScript Object Notation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It uses a strict syntax based on objects, arrays, keys, and values.&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Omeiza"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Backend Developer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ASP.NET Core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MySQL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Redis"&lt;/span&gt;&lt;span class="p"&gt;]&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;JSON is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strictly structured&lt;/li&gt;
&lt;li&gt;Easy for machines to parse&lt;/li&gt;
&lt;li&gt;Widely supported across programming languages&lt;/li&gt;
&lt;li&gt;Commonly used for APIs and data exchange&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;JSON can become difficult to read when the structure gets large.&lt;/p&gt;




&lt;h2&gt;
  
  
  YAML: Designed for Humans
&lt;/h2&gt;

&lt;p&gt;YAML stands for &lt;strong&gt;YAML Ain't Markup Language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It represents the same kind of structured data but uses indentation instead of brackets and braces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Omeiza&lt;/span&gt;
&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Backend Developer&lt;/span&gt;
&lt;span class="na"&gt;skills&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ASP.NET Core&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MySQL&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Redis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how much cleaner it looks.&lt;/p&gt;

&lt;p&gt;YAML is especially popular for &lt;strong&gt;configuration files&lt;/strong&gt;, where developers frequently need to read and modify the data manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  YAML vs JSON
&lt;/h2&gt;

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

&lt;p&gt;&lt;strong&gt;YAML&lt;/strong&gt; → Easier for humans to read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON&lt;/strong&gt; → More verbose because of &lt;code&gt;{}&lt;/code&gt;, &lt;code&gt;[]&lt;/code&gt;, commas, and quotes.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;YAML&lt;/strong&gt; → Uses indentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JSON&lt;/strong&gt; → Uses braces and brackets.&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;"server"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&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;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;YAML looks cleaner, but its indentation-based syntax also means formatting mistakes can cause problems.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. APIs and Data Exchange
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;JSON&lt;/strong&gt; is generally the natural choice for APIs.&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 http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/users/1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Omeiza"&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;It's widely supported and predictable, making it a strong fit for communication between applications.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;YAML&lt;/strong&gt; is frequently used for configuration.&lt;/p&gt;

&lt;p&gt;You'll commonly encounter it in tools such as Kubernetes and CI/CD systems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hierarchical structure makes configuration easier to scan and edit.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Strictness
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;JSON&lt;/strong&gt; is stricter.&lt;/p&gt;

&lt;p&gt;That can be a good thing because invalid syntax is usually easier to identify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAML&lt;/strong&gt; is more flexible, but that flexibility can introduce subtle issues around indentation, data types, and special characters.&lt;/p&gt;




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

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

&lt;p&gt;&lt;strong&gt;Use JSON when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're building APIs.&lt;/li&gt;
&lt;li&gt;You're exchanging data between applications.&lt;/li&gt;
&lt;li&gt;You want strict, predictable syntax.&lt;/li&gt;
&lt;li&gt;Your tooling already expects JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use YAML when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're writing configuration files.&lt;/li&gt;
&lt;li&gt;Humans will frequently edit the file.&lt;/li&gt;
&lt;li&gt;You're working with Kubernetes or CI/CD configuration.&lt;/li&gt;
&lt;li&gt;Readability is a major concern.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Important Lesson
&lt;/h2&gt;

&lt;p&gt;YAML and JSON aren't really competing to replace each other.&lt;/p&gt;

&lt;p&gt;They solve similar problems but excel in different situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON prioritizes strict structure and interoperability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAML prioritizes human readability and configuration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The best choice isn't about which format is "better."&lt;/p&gt;

&lt;p&gt;It's about &lt;strong&gt;who is consuming the data and what the data is being used for.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Monolith vs Microservices: When Should You Split Your Application?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Thu, 17 Sep 2026 07:14:58 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/monolith-vs-microservices-when-should-you-split-your-application-39o6</link>
      <guid>https://dev.to/omeiza_ahmed/monolith-vs-microservices-when-should-you-split-your-application-39o6</guid>
      <description>&lt;p&gt;&lt;strong&gt;Not every application needs microservices. Sometimes, a well-built monolith is exactly what you need.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Microservices have become a popular architecture choice, especially in discussions about scalability and distributed systems.&lt;/p&gt;

&lt;p&gt;But there's a common misconception:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Microservices are not automatically better than a monolith.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The right choice depends on the complexity, team, scale, and requirements of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Monolith?
&lt;/h2&gt;

&lt;p&gt;A monolithic application is built and deployed as a single unit.&lt;/p&gt;

&lt;p&gt;For example, imagine an e-commerce application with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Orders&lt;/li&gt;
&lt;li&gt;Payments&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a monolith, all of these might exist inside the same application and typically share the same deployment and infrastructure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                E-Commerce App
                     |
        -----------------------------
        |       |       |      |     |
      Users  Products Orders Payments Notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This doesn't mean the code has to be messy.&lt;/p&gt;

&lt;p&gt;A monolith can still use clean architecture, separation of concerns, dependency injection, modules, and well-defined boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Start With a Monolith?
&lt;/h3&gt;

&lt;p&gt;It's simpler.&lt;/p&gt;

&lt;p&gt;You have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One application to deploy&lt;/li&gt;
&lt;li&gt;One codebase to manage&lt;/li&gt;
&lt;li&gt;Easier local development&lt;/li&gt;
&lt;li&gt;Simpler debugging&lt;/li&gt;
&lt;li&gt;Simpler communication between components&lt;/li&gt;
&lt;li&gt;Usually less infrastructure overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a small team building an early-stage product, this simplicity can be extremely valuable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Microservices?
&lt;/h2&gt;

&lt;p&gt;Microservices split an application into smaller, independently deployable services.&lt;/p&gt;

&lt;p&gt;Using the same e-commerce example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             API Gateway
                  |
      -------------------------
      |        |       |      |
    Users   Orders  Payments Products
      |        |       |      |
     DB       DB      DB      DB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each service is responsible for a specific business capability.&lt;/p&gt;

&lt;p&gt;The Order Service handles orders.&lt;/p&gt;

&lt;p&gt;The Payment Service handles payments.&lt;/p&gt;

&lt;p&gt;The Product Service handles products.&lt;/p&gt;

&lt;p&gt;They communicate over the network, commonly through HTTP APIs or messaging systems.&lt;/p&gt;

&lt;p&gt;The important part is &lt;strong&gt;independent ownership and deployment&lt;/strong&gt;, not simply having many projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Difference
&lt;/h2&gt;

&lt;p&gt;The biggest difference isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"One has many services and the other has one."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's about &lt;strong&gt;boundaries and deployment&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With a monolith:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code → Build → Deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With microservices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Service   → Build → Deploy
Order Service  → Build → Deploy
Payment Service → Build → Deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A change to the Order Service doesn't necessarily require deploying the Payment Service.&lt;/p&gt;

&lt;p&gt;That independence is one of the major benefits of microservices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Monolith vs Microservices
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monolith&lt;/th&gt;
&lt;th&gt;Microservices&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single deployable application&lt;/td&gt;
&lt;td&gt;Multiple independently deployable services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simpler infrastructure&lt;/td&gt;
&lt;td&gt;More infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easier to develop initially&lt;/td&gt;
&lt;td&gt;More operational complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easier debugging&lt;/td&gt;
&lt;td&gt;Distributed debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usually simpler communication&lt;/td&gt;
&lt;td&gt;Network communication between services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling is often application-wide&lt;/td&gt;
&lt;td&gt;Services can scale independently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simpler deployment&lt;/td&gt;
&lt;td&gt;More complex deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good for smaller systems/teams&lt;/td&gt;
&lt;td&gt;Useful for larger, complex systems&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither architecture is universally better.&lt;/p&gt;

&lt;p&gt;They solve different problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hidden Cost of Microservices
&lt;/h2&gt;

&lt;p&gt;Here's something developers sometimes underestimate:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microservices move complexity; they don't remove it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of dealing with complexity inside one application, you now have to deal with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network failures&lt;/li&gt;
&lt;li&gt;Service discovery&lt;/li&gt;
&lt;li&gt;Distributed logging&lt;/li&gt;
&lt;li&gt;Message queues&lt;/li&gt;
&lt;li&gt;Authentication between services&lt;/li&gt;
&lt;li&gt;Monitoring and tracing&lt;/li&gt;
&lt;li&gt;Data consistency&lt;/li&gt;
&lt;li&gt;Deployment orchestration&lt;/li&gt;
&lt;li&gt;API versioning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, in a monolith:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order → Payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;might simply be a method call.&lt;/p&gt;

&lt;p&gt;In microservices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Service
      |
      | HTTP / Message
      ↓
Payment Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the network can fail.&lt;/p&gt;

&lt;p&gt;The Payment Service can be unavailable.&lt;/p&gt;

&lt;p&gt;The request can timeout.&lt;/p&gt;

&lt;p&gt;You may need retries, idempotency, circuit breakers, distributed tracing, and better observability.&lt;/p&gt;

&lt;p&gt;That's a very different level of complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Does Microservices Make Sense?
&lt;/h2&gt;

&lt;p&gt;Microservices become more attractive when your system and organization have real reasons to need them.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Independent scaling
&lt;/h3&gt;

&lt;p&gt;Suppose your product service receives 10x more traffic than your notification service.&lt;/p&gt;

&lt;p&gt;With microservices, you can scale the Product Service independently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Independent deployments
&lt;/h3&gt;

&lt;p&gt;If the payment team needs to release a change, they don't necessarily need to deploy the entire application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large teams
&lt;/h3&gt;

&lt;p&gt;Different teams can own different services with clear boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different technology requirements
&lt;/h3&gt;

&lt;p&gt;One service might benefit from .NET while another uses Python or Go.&lt;/p&gt;

&lt;p&gt;Microservices can accommodate this when there's a genuine reason for doing so.&lt;/p&gt;




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

&lt;p&gt;Imagine you're building a URL shortener.&lt;/p&gt;

&lt;p&gt;You could start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UrlShortener
├── Authentication
├── Short URLs
├── Redirects
├── Analytics
└── Admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's perfectly reasonable as a monolith.&lt;/p&gt;

&lt;p&gt;As the system grows, you might eventually separate responsibilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                API Gateway
                     |
       ------------------------------
       |             |              |
   Auth Service   URL Service   Analytics Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But don't split everything on day one just because microservices are popular.&lt;/p&gt;

&lt;p&gt;Start with clear boundaries inside your application.&lt;/p&gt;

&lt;p&gt;If you later need to extract a service, those boundaries make the transition much easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Monolith Can Still Be Well Architected
&lt;/h2&gt;

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

&lt;p&gt;&lt;strong&gt;Monolith does not mean bad architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can build a modular monolith where different business domains are separated internally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
├── Identity
├── Orders
├── Payments
├── Products
└── Notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each module has clear responsibilities and dependencies.&lt;/p&gt;

&lt;p&gt;This gives you many benefits of good separation without immediately introducing distributed-system complexity.&lt;/p&gt;

&lt;p&gt;And if one module eventually needs to become its own service, you already have a logical boundary to work with.&lt;/p&gt;




&lt;h2&gt;
  
  
  So Which Should You Choose?
&lt;/h2&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Should I use microservices?"&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"What problem am I trying to solve?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your application is small and your team is small, a monolith may provide the simplicity you need.&lt;/p&gt;

&lt;p&gt;If your system has genuinely independent domains, large teams, independent scaling requirements, or deployment needs, microservices may make sense.&lt;/p&gt;

&lt;p&gt;Architecture should respond to &lt;strong&gt;real problems&lt;/strong&gt;, not trends.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Start simple.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A monolith is not a failure to use microservices.&lt;/p&gt;

&lt;p&gt;Microservices are not a sign that an application has matured.&lt;/p&gt;

&lt;p&gt;Build clear boundaries, keep your architecture modular, and introduce distributed services when the complexity and requirements of the system actually justify them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't choose microservices because they sound advanced. Choose them because your system has a problem that microservices solve.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Memoization: Stop Doing the Same Work Twice</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Wed, 16 Sep 2026 11:28:08 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/memoization-stop-doing-the-same-work-twice-3pjc</link>
      <guid>https://dev.to/omeiza_ahmed/memoization-stop-doing-the-same-work-twice-3pjc</guid>
      <description>&lt;p&gt;Imagine calling a function with the exact same input 100 times.&lt;/p&gt;

&lt;p&gt;If that function performs an expensive calculation, why should your application calculate the same result 100 times?&lt;/p&gt;

&lt;p&gt;It shouldn't.&lt;/p&gt;

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

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

&lt;p&gt;Memoization is an optimization technique where you &lt;strong&gt;store the result of an expensive function call and reuse it when the same input appears again.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of it like a notebook.&lt;/p&gt;

&lt;p&gt;The first time you solve a problem, you write down the answer. Next time you encounter the exact same problem, you look at your notes instead of solving it again.&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Square&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;number&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;number&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;number&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;Without memoization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Square(10) → calculate → 100
Square(10) → calculate → 100
Square(10) → calculate → 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With memoization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Square(10) → calculate → 100 → store

Square(10) → return stored 100
Square(10) → return stored 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second and third calls don't need to perform the calculation again.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does It Work?
&lt;/h2&gt;

&lt;p&gt;Memoization usually involves a &lt;strong&gt;cache&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The basic flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Function called
      ↓
Have we seen this input before?
      ↓
   Yes ─────→ Return cached result
      │
      No
      ↓
Calculate result
      ↓
Store result
      ↓
Return result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a simple C# 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="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cache&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Square&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;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&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;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&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;result&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;Now, once &lt;code&gt;Square(10)&lt;/code&gt; has been calculated, the result is stored.&lt;/p&gt;

&lt;p&gt;Future calls can retrieve it directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memoization vs Caching
&lt;/h2&gt;

&lt;p&gt;These concepts are closely related, but they're not exactly the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt; is the broader concept of storing data so it can be retrieved faster later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memoization&lt;/strong&gt; specifically refers to caching the &lt;strong&gt;result of a function based on its inputs&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;Caching:
Database query → store result → reuse result

Memoization:
calculate(10) → store result for input 10 → reuse result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can think of memoization as a specific form of caching.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Classic Example: Fibonacci
&lt;/h2&gt;

&lt;p&gt;Memoization becomes much more useful when a function repeatedly calculates the same values.&lt;/p&gt;

&lt;p&gt;Consider Fibonacci:&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Fibonacci&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;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;1&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;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;Fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;2&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;For something like:&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="nf"&gt;Fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the function calculates some values multiple times.&lt;/p&gt;

&lt;p&gt;For larger values, the number of repeated calculations grows rapidly.&lt;/p&gt;

&lt;p&gt;With memoization:&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="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cache&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="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Fibonacci&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;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;1&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;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&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;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;Fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&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;result&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;Now, once &lt;code&gt;Fibonacci(3)&lt;/code&gt; has been calculated, we don't calculate it from scratch every time we need it.&lt;/p&gt;

&lt;p&gt;We simply reuse the stored result.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Use Memoization?
&lt;/h2&gt;

&lt;p&gt;Memoization is useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A function is expensive to execute.&lt;/li&gt;
&lt;li&gt;The same inputs occur repeatedly.&lt;/li&gt;
&lt;li&gt;The function is deterministic.&lt;/li&gt;
&lt;li&gt;The result doesn't change for the same input.&lt;/li&gt;
&lt;/ul&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;Input: 5
Output: 120
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;5&lt;/code&gt; will always produce &lt;code&gt;120&lt;/code&gt;, storing that result makes sense.&lt;/p&gt;

&lt;p&gt;Memoization is especially common in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recursive algorithms&lt;/li&gt;
&lt;li&gt;Dynamic programming&lt;/li&gt;
&lt;li&gt;Mathematical calculations&lt;/li&gt;
&lt;li&gt;Parsing and processing&lt;/li&gt;
&lt;li&gt;Expensive transformations&lt;/li&gt;
&lt;li&gt;Applications with repeated computations&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When Memoization Can Be a Bad Idea
&lt;/h2&gt;

&lt;p&gt;Memoization isn't free.&lt;/p&gt;

&lt;p&gt;You're trading &lt;strong&gt;memory for speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every cached result takes memory, and if the inputs are constantly changing, the cache may provide very little benefit.&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;calculate(1)
calculate(2)
calculate(3)
calculate(4)
calculate(5)
...
calculate(1,000,000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If every input is unique, you're storing lots of results without getting many cache hits.&lt;/p&gt;

&lt;p&gt;You also need to think about &lt;strong&gt;stale data&lt;/strong&gt; if the underlying result can change.&lt;/p&gt;




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

&lt;p&gt;Memoization is a simple idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you've already done the work for the same input, don't do it again.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Store the result.&lt;/p&gt;

&lt;p&gt;Reuse it.&lt;/p&gt;

&lt;p&gt;Save computation.&lt;/p&gt;

&lt;p&gt;But remember the trade-off:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memoization improves performance by spending memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The real skill isn't just knowing how to memoize.&lt;/p&gt;

&lt;p&gt;It's knowing &lt;strong&gt;when repeated computation is expensive enough to justify caching the result.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>performance</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Deadlocks: When Your Threads Are Waiting Forever</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Tue, 15 Sep 2026 06:42:34 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/deadlocks-when-your-threads-are-waiting-forever-2dcd</link>
      <guid>https://dev.to/omeiza_ahmed/deadlocks-when-your-threads-are-waiting-forever-2dcd</guid>
      <description>&lt;p&gt;Your application is running. No exception. No crash.&lt;/p&gt;

&lt;p&gt;But two requests are stuck indefinitely.&lt;/p&gt;

&lt;p&gt;Welcome to a &lt;strong&gt;deadlock&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A deadlock happens when two or more threads are waiting for resources held by each other, so none of them can continue.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Deadlock?
&lt;/h2&gt;

&lt;p&gt;Imagine two developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developer A has &lt;strong&gt;Resource 1&lt;/strong&gt; and needs &lt;strong&gt;Resource 2&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Developer B has &lt;strong&gt;Resource 2&lt;/strong&gt; and needs &lt;strong&gt;Resource 1&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are waiting.&lt;/p&gt;

&lt;p&gt;Neither can move forward.&lt;/p&gt;

&lt;p&gt;That's essentially what happens with threads and locks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread A → holds Lock 1 → waiting for Lock 2
Thread B → holds Lock 2 → waiting for Lock 1

Result: DEADLOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is that &lt;strong&gt;both threads are waiting for each other&lt;/strong&gt;.&lt;/p&gt;




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

&lt;p&gt;Consider 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="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;lockA&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="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;lockB&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="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MethodA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&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="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Method A"&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MethodB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&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="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Method B"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If two threads execute these methods at the same time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread 1:
Locks A
↓
Waits for B

Thread 2:
Locks B
↓
Waits for A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neither thread can acquire the lock it needs.&lt;/p&gt;

&lt;p&gt;The application can remain stuck indefinitely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Do Deadlocks Happen?
&lt;/h2&gt;

&lt;p&gt;Deadlocks usually involve a combination of these conditions:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Mutual Exclusion
&lt;/h3&gt;

&lt;p&gt;A resource can only be used by one thread at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread A → owns Resource X
Thread B → must wait
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Hold and Wait
&lt;/h3&gt;

&lt;p&gt;A thread holds one resource while waiting for another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread A:
Holding X
Waiting for Y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. No Preemption
&lt;/h3&gt;

&lt;p&gt;A resource cannot simply be taken away from the thread holding it.&lt;/p&gt;

&lt;p&gt;The thread must release it.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Circular Wait
&lt;/h3&gt;

&lt;p&gt;Thread A waits for Thread B, while Thread B waits for Thread A.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A → waiting for B
B → waiting for A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This circular dependency is what ultimately creates the deadlock.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Do You Prevent Deadlocks?
&lt;/h2&gt;

&lt;p&gt;One of the simplest strategies is to &lt;strong&gt;always acquire locks in the same order&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of:&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="c1"&gt;// Method A&lt;/span&gt;
&lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockB&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;and:&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="c1"&gt;// Method B&lt;/span&gt;
&lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockA&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;Make both follow the same order:&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;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Work&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;Now both threads agree:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;There is no circular waiting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Other Ways to Reduce the Risk
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Keep Lock Scope Small
&lt;/h3&gt;

&lt;p&gt;Don't hold a lock longer than necessary.&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;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Only critical work&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid performing slow operations such as network calls or database requests while holding a lock.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid Unnecessary Multiple Locks
&lt;/h3&gt;

&lt;p&gt;The more locks you need to coordinate, the more opportunities you create for circular dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Async Carefully
&lt;/h3&gt;

&lt;p&gt;Async code can introduce its own synchronization problems.&lt;/p&gt;

&lt;p&gt;Avoid blocking asynchronous operations with:&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;Result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&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;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer:&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;await&lt;/span&gt; &lt;span class="nf"&gt;SomeOperationAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This doesn't automatically eliminate every deadlock, but it avoids an important class of blocking problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deadlock vs Race Condition
&lt;/h2&gt;

&lt;p&gt;These problems are often confused.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;race condition&lt;/strong&gt; happens when multiple threads access shared data and the result depends on the timing of their execution.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;deadlock&lt;/strong&gt; happens when threads are stuck waiting for each other.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Race condition:&lt;/strong&gt;&lt;br&gt;
"Who gets there first?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deadlock:&lt;/strong&gt;&lt;br&gt;
"Nobody can move."&lt;/p&gt;




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

&lt;p&gt;A deadlock isn't necessarily caused by a bug that crashes your application.&lt;/p&gt;

&lt;p&gt;Sometimes the more dangerous bug is the one that makes your application &lt;strong&gt;wait forever&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When working with multiple locks, remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Acquire locks consistently, keep lock scope small, and avoid unnecessary blocking.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good concurrency isn't just about making multiple things run at once. It's also about making sure they can actually &lt;strong&gt;finish&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Middleware vs Filter in ASP.NET Core: What’s the Difference?</title>
      <dc:creator>Ahmed Omeiza</dc:creator>
      <pubDate>Mon, 14 Sep 2026 13:00:53 +0000</pubDate>
      <link>https://dev.to/omeiza_ahmed/middleware-vs-filter-in-aspnet-core-whats-the-difference-flp</link>
      <guid>https://dev.to/omeiza_ahmed/middleware-vs-filter-in-aspnet-core-whats-the-difference-flp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Middleware and filters can both run before or after your request logic, but they operate at different levels of the ASP.NET Core pipeline.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Understanding that difference helps you put code in the right place instead of turning your application into a collection of random checks.&lt;/p&gt;

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

&lt;p&gt;Middleware is part of the &lt;strong&gt;HTTP request pipeline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It can inspect, modify, or short-circuit an HTTP request before it reaches your endpoint. It can also process the response on the way back.&lt;/p&gt;

&lt;p&gt;A simple middleware might log every incoming request:&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;InvokeAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Request: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Response: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&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="s"&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;Middleware is useful for concerns that apply broadly across your application.&lt;/p&gt;

&lt;p&gt;Common examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Exception handling&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;CORS&lt;/li&gt;
&lt;li&gt;Request/response manipulation&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of middleware as a &lt;strong&gt;checkpoint for the entire HTTP pipeline&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Filter?
&lt;/h2&gt;

&lt;p&gt;Filters are part of the &lt;strong&gt;ASP.NET Core MVC/controller pipeline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They run at specific stages around controller actions.&lt;/p&gt;

&lt;p&gt;For example, an authorization filter can check whether a user is allowed to execute an action before the controller action runs.&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;AdminOnlyFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IAuthorizationFilter&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;OnAuthorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthorizationFilterContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsInRole&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="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&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;ForbidResult&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filters are useful when the behavior is specifically related to MVC/controller actions.&lt;/p&gt;

&lt;p&gt;Common filter types include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization filters&lt;/li&gt;
&lt;li&gt;Resource filters&lt;/li&gt;
&lt;li&gt;Action filters&lt;/li&gt;
&lt;li&gt;Exception filters&lt;/li&gt;
&lt;li&gt;Result filters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of a filter as a &lt;strong&gt;checkpoint specifically around controller execution&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Middleware vs Filter
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Middleware&lt;/th&gt;
&lt;th&gt;Filter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Works at the HTTP pipeline level&lt;/td&gt;
&lt;td&gt;Works inside the MVC/controller pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can apply to almost every request&lt;/td&gt;
&lt;td&gt;Mainly applies to MVC/controller endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runs before routing or at specific middleware positions&lt;/td&gt;
&lt;td&gt;Runs around controller/action execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good for global concerns&lt;/td&gt;
&lt;td&gt;Good for controller/action-specific concerns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uses &lt;code&gt;HttpContext&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Has access to MVC-specific context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The biggest difference is &lt;strong&gt;scope&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Middleware doesn't need to care whether the request eventually reaches a controller, Razor Page, or another endpoint.&lt;/p&gt;

&lt;p&gt;A filter is more closely connected to the MVC execution process.&lt;/p&gt;




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

&lt;p&gt;Imagine you want to log every request entering your API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Middleware&lt;/strong&gt; is a good choice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
   ↓
Logging Middleware
   ↓
Authentication
   ↓
Authorization
   ↓
Controller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But suppose you want to run some logic only before a specific controller action.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;filter&lt;/strong&gt; makes more sense:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
   ↓
Middleware
   ↓
Controller
   ↓
Action Filter
   ↓
Controller Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The decision comes down to &lt;strong&gt;where the behavior belongs in the pipeline&lt;/strong&gt;.&lt;/p&gt;




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

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

&lt;p&gt;A typical ASP.NET Core application might use middleware for global concerns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP Request
     ↓
Exception Middleware
     ↓
Logging Middleware
     ↓
Authentication Middleware
     ↓
Authorization Middleware
     ↓
MVC Pipeline
     ↓
Action Filter
     ↓
Controller Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They aren't competing technologies.&lt;/p&gt;

&lt;p&gt;They solve problems at different levels.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Use middleware when the concern belongs to the HTTP request pipeline. Use filters when the concern is specifically tied to MVC/controller execution.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A simple rule to remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Middleware is broader. Filters are more specific.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knowing where your logic belongs makes your ASP.NET Core applications cleaner, easier to maintain, and easier to reason about.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
