<?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: Mehrad Sadeghi</title>
    <description>The latest articles on DEV Community by Mehrad Sadeghi (@mehradsadeghi).</description>
    <link>https://dev.to/mehradsadeghi</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%2F262659%2F811ae57e-fdb3-43b9-9acd-78203e43c8b8.png</url>
      <title>DEV Community: Mehrad Sadeghi</title>
      <link>https://dev.to/mehradsadeghi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mehradsadeghi"/>
    <language>en</language>
    <item>
      <title>Automated Testing in Backend Development: A Complete Guide from Unit Tests to Fuzz Testing</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Sun, 27 Sep 2026 13:42:38 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/automated-testing-in-backend-development-a-complete-guide-from-unit-tests-to-fuzz-testing-2l5k</link>
      <guid>https://dev.to/mehradsadeghi/automated-testing-in-backend-development-a-complete-guide-from-unit-tests-to-fuzz-testing-2l5k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0hkr7ao33jjog11aew22.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0hkr7ao33jjog11aew22.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you had to change one of your critical services right now, how confident are you that the change wouldn't silently break something else in your codebase ?&lt;/p&gt;

&lt;p&gt;And harder still — if the only way to be sure was to manually test the entire system by hand, what would you do ?&lt;/p&gt;

&lt;p&gt;This is exactly where &lt;strong&gt;automated tests&lt;/strong&gt; earn their keep.&lt;/p&gt;

&lt;p&gt;Automated tests aren't just a tool for catching bugs. In any serious project, they're a core part of keeping the system safe to change. Tests are what let you refactor code, swap out dependencies, optimize a database, or even redesign a service's architecture — without manually re-verifying the entire system from scratch every single time.&lt;/p&gt;

&lt;p&gt;But here's the catch: &lt;strong&gt;not all tests are equal.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are many kinds of tests — Unit, Integration, Feature, Contract, Fuzz, End-to-End, and more — and each one solves a different problem. A test that's extremely valuable in one project might just be maintenance overhead in another.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Automated Testing, and Why Does It Matter in Backend Development ?
&lt;/h2&gt;

&lt;p&gt;In simple terms, an &lt;strong&gt;automated test&lt;/strong&gt; is a program that runs part of your software, compares the actual result to the expected one, and fails the test if there's a mismatch.&lt;/p&gt;

&lt;p&gt;For example, imagine a service that calculates the final price of an order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;subtotal = 1,000,000
discount = 10%
shipping = 50,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we expect the final price to equal 950,000, we can turn that expectation into a test. From then on, every time the pricing logic changes, the test automatically verifies whether the expected behavior still holds.&lt;/p&gt;

&lt;p&gt;Automated tests are extremely useful for catching &lt;a href="https://en.wikipedia.org/wiki/Regression_testing" rel="noopener noreferrer"&gt;regressions&lt;/a&gt;, documenting system behavior, and building confidence when changing code. They can also be plugged directly into CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;The goal isn't to test every single line of code — it's to cover the system's most important risks at a reasonable cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Tests in Backend Development
&lt;/h2&gt;

&lt;p&gt;To really understand test types, you first need to define their &lt;strong&gt;scope&lt;/strong&gt; — which specific part of the system a given test touches. That gives us:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit Test&lt;/li&gt;
&lt;li&gt;Integration Test&lt;/li&gt;
&lt;li&gt;Feature / Functional Test&lt;/li&gt;
&lt;li&gt;Contract Test&lt;/li&gt;
&lt;li&gt;End-to-End Test&lt;/li&gt;
&lt;li&gt;Characterization Test&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alongside these, there are techniques focused more on &lt;em&gt;how inputs are generated&lt;/em&gt; or &lt;em&gt;how strong your test suite is&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Property-Based Test&lt;/li&gt;
&lt;li&gt;Fuzz Testing&lt;/li&gt;
&lt;li&gt;Mutation Testing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And finally, tests that check the system's performance and quality:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performance / Load / Stress Test&lt;/li&gt;
&lt;li&gt;Smoke Test&lt;/li&gt;
&lt;li&gt;Regression Test&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These categories aren't fully independent of each other. A Feature Test can also be an Integration Test at the same time, and fuzzing can be applied to a single Unit Test.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So what matters more than a test's &lt;em&gt;name&lt;/em&gt; is understanding exactly what risk it covers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Is a Unit Test ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Unit_testing" rel="noopener noreferrer"&gt;Unit testing&lt;/a&gt; is the smallest and fastest level of testing. In a unit test, you typically isolate a specific unit of behavior and verify that, given a specific input, it produces the expected result.&lt;/p&gt;

&lt;p&gt;That "unit" can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A function&lt;/li&gt;
&lt;li&gt;A method&lt;/li&gt;
&lt;li&gt;A class&lt;/li&gt;
&lt;li&gt;Or a small piece of domain logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, take:&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;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could write tests like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer = Regular
Price = 1,000,000
Expected Discount = 0
&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;Customer = Premium
Price = 1,000,000
Expected Discount = 100,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a unit test, external dependencies like the database, file system, or network are never brought in directly — instead they're replaced with test doubles such as mocks, stubs, or fakes (we'll cover each of these later in the article).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests" rel="noopener noreferrer"&gt;Microsoft's definition of a unit test&lt;/a&gt; treats it as a test of a specific component or method, and explicitly places infrastructure pieces — database, file system, network — outside the normal scope of a unit test.&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages of Unit Tests
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Very fast&lt;/li&gt;
&lt;li&gt;Low execution cost&lt;/li&gt;
&lt;li&gt;CI-friendly&lt;/li&gt;
&lt;li&gt;Pinpoints the exact location of a bug&lt;/li&gt;
&lt;li&gt;Great for refactoring&lt;/li&gt;
&lt;li&gt;Lets you have a large number of tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The Downside of Unit Tests
&lt;/h4&gt;

&lt;p&gt;Every component might work correctly in isolation, but still break when combined.&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;OrderService
      ↓
Repository
      ↓
PostgreSQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt;'s logic might be completely correct, but the query it sends could still be wrong. A unit test alone won't catch that.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What Is an Integration Test ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Integration_testing" rel="noopener noreferrer"&gt;Integration testing&lt;/a&gt; checks whether two or more parts of your application — or one part and an external dependency — can actually work together. Common examples in backend systems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application + PostgreSQL&lt;/li&gt;
&lt;li&gt;Application + Redis&lt;/li&gt;
&lt;li&gt;Application + Message Broker&lt;/li&gt;
&lt;li&gt;Application + File System&lt;/li&gt;
&lt;li&gt;Application + External API&lt;/li&gt;
&lt;li&gt;Repository + Database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Say your repository does something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateOrder(order)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a unit test, you'd probably mock the database.&lt;/p&gt;

&lt;p&gt;But an integration test can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spin up a real PostgreSQL instance&lt;/li&gt;
&lt;li&gt;Connect the application to it&lt;/li&gt;
&lt;li&gt;Save an order&lt;/li&gt;
&lt;li&gt;Read it back&lt;/li&gt;
&lt;li&gt;Verify the result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, you're no longer just testing your code's logic — you're verifying how components actually interact. Integration tests generally have a larger scope than unit tests and can pull in real infrastructure.&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages of Integration Tests
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Tests more realistic behavior&lt;/li&gt;
&lt;li&gt;Catches database-related issues&lt;/li&gt;
&lt;li&gt;Catches serialization issues&lt;/li&gt;
&lt;li&gt;Verifies configuration&lt;/li&gt;
&lt;li&gt;Gives more confidence than unit tests alone&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Disadvantages of Integration Tests
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Slower&lt;/li&gt;
&lt;li&gt;More complex setup&lt;/li&gt;
&lt;li&gt;(Probably) requires real infrastructure&lt;/li&gt;
&lt;li&gt;Harder to debug&lt;/li&gt;
&lt;li&gt;Failures can have many possible causes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So it doesn't make sense to write an integration test for every single piece of business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Feature Test (or Functional Test) ?
&lt;/h2&gt;

&lt;p&gt;A Feature Test checks a more complete capability of the system, from the perspective of its expected behavior. In a backend, this test can start from the API itself. For example, a feature around placing an order:&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 /orders
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Input:&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;"productId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&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;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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;And we expect the response:&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="mi"&gt;201&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Created&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;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"created"&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;At this point, it no longer matters how many classes exist inside &lt;code&gt;OrderService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We're testing the feature's behavior: &lt;em&gt;"Can a user create a valid order ?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's exactly why a Feature Test differs from a Unit Test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Unit Test asks:&lt;/strong&gt; does this class or function work correctly ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Feature Test asks:&lt;/strong&gt; does this specific feature of the system behave as expected ?&lt;/p&gt;

&lt;p&gt;That's why Feature Tests are so valuable in API development.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Is a Feature Test Different from an Integration Test ?
&lt;/h2&gt;

&lt;p&gt;These two concepts can overlap. For instance, a single API test might flow through:&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
   ↓
Controller
   ↓
Service
   ↓
Repository
   ↓
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that case, you've tested both the feature &lt;em&gt;and&lt;/em&gt; the integration between its components.&lt;/p&gt;

&lt;p&gt;So these aren't necessarily two fully separate layers. A practical way to decide is to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What risk does this test actually cover ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the goal is to verify that a feature works correctly from the API's point of view, call it a Feature/Functional Test. If the goal is to verify the repository's connection to PostgreSQL, call it an Integration Test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Contract Test ?
&lt;/h2&gt;

&lt;p&gt;Imagine the Order service sends a request to the Payment service:&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 /payments
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and expects the response to look like:&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;"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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"paid"&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;Now imagine the Payment team changes that response without telling you:&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;"id"&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;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&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;Your unit tests might still be green. But the integration between the two services is broken.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Contract Testing&lt;/strong&gt; becomes valuable.&lt;/p&gt;

&lt;p&gt;A Contract Test verifies that both sides of an integration agree on a specific contract. For HTTP communication, that contract can define the expected request and response shapes — and the same idea applies to message-based integrations too.&lt;/p&gt;

&lt;p&gt;One well-known approach is &lt;strong&gt;Consumer-Driven Contract Testing&lt;/strong&gt;. In this model, the consumer defines its expected needs and interactions as a contract, and the provider verifies that contract.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Benefit of Contract Testing
&lt;/h4&gt;

&lt;p&gt;A Contract Test can reduce a chunk of integration risk between services without running the entire system.&lt;/p&gt;

&lt;p&gt;This is especially useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different teams work on different services&lt;/li&gt;
&lt;li&gt;Services are deployed independently&lt;/li&gt;
&lt;li&gt;APIs change frequently&lt;/li&gt;
&lt;li&gt;You have a microservices architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's important to note that Contract Testing doesn't fully replace other test types. Instead, it's designed for one specific problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do the two services still agree on the expected interface ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Is an End-to-End (E2E) Test ?
&lt;/h2&gt;

&lt;p&gt;An End-to-End Test, or E2E, checks a scenario's entire path from start to finish.&lt;/p&gt;

&lt;p&gt;For example, in an online store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Login
 ↓
Add Product
 ↓
Create Order
 ↓
Payment
 ↓
Order Confirmation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E2E tests run this entire path. In backend development, even without a UI, we can run this kind of scenario purely through the API:&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 /login
POST /cart
POST /orders
POST /payments
GET /orders/{id}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally verify:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  The Benefit of E2E Tests
&lt;/h4&gt;

&lt;p&gt;They most closely resemble the system's real-world behavior. That's why, for critical business scenarios, they can create a very high level of confidence.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Main Challenge with E2E Tests
&lt;/h4&gt;

&lt;p&gt;They're expensive.&lt;/p&gt;

&lt;p&gt;E2E tests are usually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slower&lt;/li&gt;
&lt;li&gt;Harder to debug when they fail, with more complex failure modes&lt;/li&gt;
&lt;li&gt;Dependent on a broader environment&lt;/li&gt;
&lt;li&gt;More demanding to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's why it doesn't make sense to test every system state end-to-end.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Characterization Test ?
&lt;/h2&gt;

&lt;p&gt;Here we get to one of the most important techniques for legacy projects. Imagine you inherit a project that's been in production for 10 years, but the project 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;Test Coverage = Low
Documentation = Incomplete
Code = Complex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project manager says: "Just make one small change here."&lt;/p&gt;

&lt;p&gt;The problem ? You don't actually know what the existing code does.&lt;/p&gt;

&lt;p&gt;Something that looks like a bug to you might actually be behavior the system has relied on for years — behavior clients now depend on.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Characterization Tests&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;A Characterization Test isn't meant to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This behavior is correct."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is the system's current behavior."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This approach matters a lot when working with &lt;strong&gt;legacy code&lt;/strong&gt;, and alongside techniques like introducing a seam, it makes it possible to change old systems gradually and safely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A seam is a point in the code where you can change or substitute a dependency in order to test or alter behavior. For example, if a service depends directly on a database, inserting an interface between them creates a seam — one that lets you swap the real database for a mock or fake during testing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  An Example of a Characterization Test
&lt;/h4&gt;

&lt;p&gt;Say you have an old function:&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;calculateShipping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and there's no existing test for it. You don't know what result this input produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order = 1,000,000
City = Tehran
Weight = 3kg
Customer = VIP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of guessing what the result "should" be, you run the function and observe the actual output. Say the output is 120,000. Now you turn that exact behavior into a test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calculateShipping(order)
Expected = 120,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this point on, if a refactor changes the result to 150,000, the test fails. In other words: before you fully understand the code, you've already captured its existing behavior.&lt;/p&gt;

&lt;h4&gt;
  
  
  When Is a Characterization Test Valuable ?
&lt;/h4&gt;

&lt;p&gt;Specifically when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The project is legacy&lt;/li&gt;
&lt;li&gt;Test coverage is low&lt;/li&gt;
&lt;li&gt;Documentation is incomplete&lt;/li&gt;
&lt;li&gt;A major refactor is coming up&lt;/li&gt;
&lt;li&gt;An old system is about to be migrated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important note:&lt;/strong&gt; a Characterization Test doesn't necessarily claim the current behavior is &lt;em&gt;correct&lt;/em&gt;. You might later discover that the captured behavior is actually a bug. At that point, you can follow this path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current Behavior
      ↓
Characterization Test
      ↓
Understanding
      ↓
Specification
      ↓
     Fix
      ↓
Normal Test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So a Characterization Test is really more of a safety net for changing an unfamiliar system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Property-Based Testing ?
&lt;/h2&gt;

&lt;p&gt;Up to this point, most of the tests we've discussed followed this shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input → Expected Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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: 10
Expected: 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are &lt;strong&gt;example-based&lt;/strong&gt; tests — we manually specify the inputs ourselves. But sometimes, instead of checking specific examples, we can define a &lt;strong&gt;property&lt;/strong&gt; of the system instead. Say we have this function:&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;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sort([3,1,2]) == [1,2,3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can say: the output must be sorted, and it must contain the same number of elements as the input.&lt;/p&gt;

&lt;p&gt;Now a property-based testing framework can generate a large number of inputs and check the property against all of them. Libraries like &lt;a href="https://hypothesis.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Hypothesis&lt;/a&gt; and &lt;a href="https://fast-check.dev/docs/introduction/" rel="noopener noreferrer"&gt;fast-check&lt;/a&gt; are built for exactly this kind of scenario.&lt;/p&gt;

&lt;p&gt;For example, it might generate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[]
[1]
[3,1]
[10,5,8,2]
[random data...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and check, for all of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;isSorted(result) == true
length(result) == length(input)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  When Is Property-Based Testing Useful ?
&lt;/h4&gt;

&lt;p&gt;When:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The number of possible input states is large&lt;/li&gt;
&lt;li&gt;Edge cases are hard to find manually&lt;/li&gt;
&lt;li&gt;You have a clear invariant or property&lt;/li&gt;
&lt;li&gt;The algorithm or domain rule is complex&lt;/li&gt;
&lt;li&gt;You want to check more examples at a lower cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, in financial systems, you might have a property like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The sum of all transactions must preserve the balance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in serialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decode(encode(x)) == x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These kinds of properties can check a huge range of inputs at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Fuzz Testing ?
&lt;/h2&gt;

&lt;p&gt;Fuzz Testing (or fuzzing) is a testing technique where you run a program against unexpected, malformed, unusual, or automatically generated inputs, in order to find bugs, crashes, vulnerabilities, or unexpected behavior. OWASP also describes fuzzing as a technique for finding bugs, vulnerabilities, and unexpected behavior through unexpected or corrupted input.&lt;/p&gt;

&lt;p&gt;Say we have this API:&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 /users
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we expect it to work correctly with input like:&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;"Ali"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ali@example.com"&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;In a normal test, we might send inputs like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;age = 30
age = 0
age = -1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But fuzzing can generate far more varied inputs, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;age = -999999
age = 999999999
name = ""
name = an extremely long string
email = ""
email = malformed
unusual Unicode
truncated JSON
oversized JSON
null
nested objects
unexpected arrays
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal isn't to prove exactly what the output should be — it's to verify that the system behaves safely and predictably in the face of unexpected input.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the Difference Between Fuzz Testing and Property-Based Testing ?
&lt;/h2&gt;

&lt;p&gt;These two concepts are closely related, and some tools even combine them — but it's better not to treat them as identical.&lt;/p&gt;

&lt;p&gt;In Property-Based Testing, the main question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does a specific property hold across a large number of inputs ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, &lt;code&gt;sort(list)&lt;/code&gt; should always return a sorted list for any valid list.&lt;/p&gt;

&lt;p&gt;In Fuzz Testing, the question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If we feed the system a large number of unexpected or malformed inputs, does it crash, expose a security issue, or behave unexpectedly ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Put simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property-Based Testing
        ↓
Generate Inputs
        ↓
Check Properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fuzz Testing
        ↓
Generate Unexpected Inputs
        ↓
Look for Failures / Crashes / Vulnerabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That said, the line between the two isn't perfectly sharp. Some property-based testing tools use fuzzing techniques, and some fuzzers also work on structured inputs with defined properties. Even Hypothesis's own documentation notes the close relationship between the two.&lt;/p&gt;

&lt;h4&gt;
  
  
  Where Is Fuzz Testing Useful in Backend Development ?
&lt;/h4&gt;

&lt;p&gt;Fuzzing can be very effective on things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API input:

JSON
Query parameters
Path parameters
Headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parsers:

JSON parser
XML parser
CSV parser
Custom protocols
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication and authorization:

Unexpected input for sessions, tokens, or headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File uploads:

Empty file
Huge file
Malformed file
Unexpected format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Search and filtering:

Very long strings
Special characters
Unicode
Unexpected combinations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Serialization / deserialization:

Input designed to trigger exceptions, incorrect
behavior, or abnormal resource consumption
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Trade-offs of Fuzz Testing
&lt;/h4&gt;

&lt;p&gt;Its advantages include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finding unexpected edge cases&lt;/li&gt;
&lt;li&gt;Discovering crashes&lt;/li&gt;
&lt;li&gt;Uncovering unknown behaviors&lt;/li&gt;
&lt;li&gt;Great for complex inputs&lt;/li&gt;
&lt;li&gt;Can run long-term in CI or dedicated fuzzing environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And its drawbacks include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designing a good fuzzer can be time-consuming&lt;/li&gt;
&lt;li&gt;Not all random inputs are equally valuable&lt;/li&gt;
&lt;li&gt;Analyzing failures can be difficult&lt;/li&gt;
&lt;li&gt;For some domains, it's hard to define a clearly "correct" output&lt;/li&gt;
&lt;li&gt;Running fuzzing at scale can consume significant resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So fuzzing is usually not a replacement for unit or integration tests — it's a complementary layer for catching a different class of problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Mutation Testing ?
&lt;/h2&gt;

&lt;p&gt;If all of your tests are green, how do you actually know your tests are capable of catching bugs ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mutation Testing&lt;/strong&gt; exists to answer exactly that question.&lt;/p&gt;

&lt;p&gt;In mutation testing, a tool deliberately introduces small changes into your production code to see whether your tests can detect them. For example, it might change:&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="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into:&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="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Then your test suite runs.&lt;/p&gt;

&lt;p&gt;If the tests fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mutation = Killed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means the tests successfully caught the change.&lt;/p&gt;

&lt;p&gt;If the tests still pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mutation = Survived
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can be a sign of a weakness in your test suite.&lt;/p&gt;

&lt;p&gt;So Mutation Testing is less a type of test &lt;em&gt;for&lt;/em&gt; your production code, and more a method for evaluating how strong your test suite actually is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Testing, Load Testing, and Stress Testing
&lt;/h2&gt;

&lt;p&gt;Sometimes the question is: does the system stay stable at 10,000 requests per second ?&lt;/p&gt;

&lt;p&gt;This is where we enter the world of &lt;strong&gt;Performance Testing&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Load Testing
&lt;/h4&gt;

&lt;p&gt;Checks how the system performs under a specific, expected load. 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;1,000 concurrent users
100 requests/sec
Response Time &amp;lt; 300ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal of a Load Test is to check system behavior under expected load. Microsoft also defines Load Testing as checking a system's ability to handle a specific load — such as a given number of concurrent users and how the system responds to them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stress Testing
&lt;/h4&gt;

&lt;p&gt;Here you push the load beyond expected capacity to see how the system behaves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100 req/s
200 req/s
500 req/s
1000 req/s
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At what point does the system degrade ?&lt;/li&gt;
&lt;li&gt;Does it crash ?&lt;/li&gt;
&lt;li&gt;Does it recover ?&lt;/li&gt;
&lt;li&gt;Does the queue grow unbounded ?&lt;/li&gt;
&lt;li&gt;Does the error rate increase ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tests matter a lot for high-traffic backends.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Smoke Test ?
&lt;/h2&gt;

&lt;p&gt;A Smoke Test is a quick, high-level test that checks whether the system starts up correctly and its core capabilities work.&lt;/p&gt;

&lt;p&gt;For example, right after a deploy:&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 /health
&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 http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /login
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If these basic paths fail, there's usually no point running more complex tests.&lt;/p&gt;

&lt;p&gt;Smoke tests are typically short and fast, and can run right after deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Regression Test ?
&lt;/h2&gt;

&lt;p&gt;A Regression Test means re-running previous tests after a change, to make sure existing capabilities still work correctly. When you find a bug, you can write a test that reproduces that exact bug.&lt;/p&gt;

&lt;p&gt;For example, say this bug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order with quantity = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;used to result in the order being created successfully.&lt;/p&gt;

&lt;p&gt;After the fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity = 0 → 400 Bad Request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You write a test for this behavior. From then on, if someone reintroduces the same bug through a different change, the test will fail.&lt;/p&gt;

&lt;p&gt;The difference between Regression Testing and other test types is that it isn't defined independently by scope — its focus is more about &lt;em&gt;purpose&lt;/em&gt; and &lt;em&gt;when&lt;/em&gt; it's run. For example, say you've already tested the &lt;code&gt;CreateOrder&lt;/code&gt; capability and everything worked. Now you make a new change — say, updating the discount logic. If you re-run the &lt;code&gt;CreateOrder&lt;/code&gt; test to confirm that this new change hasn't broken previous behavior, that's a Regression Test.&lt;/p&gt;

&lt;p&gt;The key point is that a single test can serve multiple purposes at once. A unit test can also be a regression test, if it's kept around specifically to prevent an old bug from resurfacing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Test Pyramid
&lt;/h2&gt;

&lt;p&gt;A simple way to think about a project's tests is the &lt;strong&gt;Test Pyramid&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The core idea is to have tests at several levels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit Test → small, fast tests
Integration/Feature Test → testing multiple parts together
E2E Test → testing the whole system end-to-end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The usual recommendation is to have many small, fast tests, and fewer large ones. That's because a unit test might run in a few milliseconds, while an E2E test has to exercise multiple parts of the system and usually costs more in time and resources.&lt;/p&gt;

&lt;p&gt;But that doesn't mean, say, 70% of a project's tests must be unit tests. The right proportion of each test type depends on the project itself and its specific risks.&lt;/p&gt;

&lt;p&gt;So instead of asking, &lt;em&gt;"What percentage of tests should be unit tests ?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's better to ask: &lt;em&gt;"What's the simplest, fastest test that can give us confidence this part works correctly ?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For example, if you have a simple calculation, a unit test is probably enough. But if you need to confirm that the API, database, and several services work correctly together, you need an integration or E2E test.&lt;/p&gt;

&lt;p&gt;So the Test Pyramid isn't a fixed rule — it's just a simple guide for choosing and balancing your tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing Different Test Types
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F285stpe275svjmao14vo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F285stpe275svjmao14vo.png" alt=" " width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important distinction between test types is the question each one is really asking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit:&lt;/strong&gt; Is this logic correct ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integration:&lt;/strong&gt; Do these two components work correctly together ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; Does this capability work as expected ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contract:&lt;/strong&gt; Do the two services still honor their shared agreement ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E2E:&lt;/strong&gt; Does the entire real-world scenario work correctly from start to finish ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Characterization:&lt;/strong&gt; What does the current system actually do ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property-Based:&lt;/strong&gt; Does a rule hold across a wide range of inputs ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuzz Testing:&lt;/strong&gt; Can unexpected input push the system into problematic behavior ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mutation:&lt;/strong&gt; Can my tests actually detect incorrect changes ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load Test:&lt;/strong&gt; How does the system behave under load ?&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real-World Scenario: From Bug to Test
&lt;/h2&gt;

&lt;p&gt;Imagine that, in an online store, users can occasionally place an order with a negative quantity:&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;"productId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-2&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;and the system creates the order anyway.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Reproduce the Bug
&lt;/h4&gt;

&lt;p&gt;First, we write a test that defines the expected behavior:&lt;br&gt;
&lt;/p&gt;

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

Expected: 400 Bad Request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test fails initially. That's a good thing — it means we've captured the bug as a reproducible test.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Find the Bug's Location
&lt;/h4&gt;

&lt;p&gt;We trace this path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API
 ↓
Controller
 ↓
OrderService
 ↓
Validator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out the validator isn't checking the &lt;code&gt;quantity&lt;/code&gt; value at all.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Add a Unit Test
&lt;/h4&gt;

&lt;p&gt;We write a small test for this rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity = -2
Expected = Validation Error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this test captures the failure more precisely, at the business-rule level.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Write a Feature Test
&lt;/h4&gt;

&lt;p&gt;Next, we write a Feature Test:&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 /orders
quantity = -2

Expected: 400
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test confirms the rule is properly enforced along the real API path as well.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5: Fix
&lt;/h4&gt;

&lt;p&gt;We fix the validator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity &amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6: Run the Test Suite
&lt;/h4&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit Tests ✓
Feature Tests ✓
Integration ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything's green, we have much more confidence that both the rule and the API path are correctly fixed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 7: Prevent Regression
&lt;/h4&gt;

&lt;p&gt;From now on, any change to order validation that reintroduces &lt;code&gt;quantity = -2&lt;/code&gt; will make the test fail.&lt;/p&gt;

&lt;p&gt;This is exactly where automated testing shows its real value:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The test didn't just find the current bug — it also reduced the cost of that same bug happening again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Happens If We Fuzz This Same API ?
&lt;/h2&gt;

&lt;p&gt;Let's take it one step further. We found the &lt;code&gt;quantity = -2&lt;/code&gt; bug using a specific test.&lt;/p&gt;

&lt;p&gt;But is that the only problematic case ?&lt;/p&gt;

&lt;p&gt;These might also produce interesting behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity = -999999999
quantity = 0
quantity = 2147483647
quantity = null
quantity = "2"
quantity = []
quantity = {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a fuzz test, we don't have to manually define every possible input case — tools can generate a wide variety of unexpected inputs to check that the system behaves correctly across all of them. 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;For every generated request:

System must not crash
AND
invalid quantity must not create an order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if the fuzzer finds a specific input that triggers an exception or unexpected behavior, that exact input can be turned into a fixed, reproducible test.&lt;/p&gt;

&lt;p&gt;This is a very practical workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fuzzing
   ↓
Unexpected Input
   ↓
Bug Found
   ↓
Minimize / Reproduce
   ↓
Regression Test
   ↓
Permanent Safety Net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Property-Based Testing, when a specific input causes a test to fail, property-based frameworks can shrink that input down to the smallest example that still triggers the failure. This is called &lt;strong&gt;shrinking&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Write Tests That You Won't Hate Them ?
&lt;/h2&gt;

&lt;p&gt;Writing a test is easy. Writing a &lt;em&gt;maintainable&lt;/em&gt; test is harder.&lt;/p&gt;

&lt;p&gt;A few key principles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Test behavior, not implementation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of a test depending on this kind of internal structure:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;it's better to check observable behavior as much as possible. If you refactor the implementation, tests shouldn't break for no reason. Microsoft's own unit testing guidance also emphasizes readability and resilience against unnecessary changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Tests should be readable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have to read a test's implementation just to understand what the test does, the test is probably too complicated. A name like:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;is usually more meaningful than something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ShouldCallValidatorThenRepositoryAnd...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A test's name should describe the scenario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Take edge cases seriously&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A test that only checks the happy path isn't enough. For instance, testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is fine — but what happens with these ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity = 0
quantity = -1
quantity = MAX_INT
quantity = null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edge cases are exactly where bugs hide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does 100% Code Coverage Mean the System Is Fully Tested ?
&lt;/h2&gt;

&lt;p&gt;This is one of the most common misconceptions in automated testing. Say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code Coverage = 100%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Does that mean the system is bug-free ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; Coverage only tells you how much of your code ran while your tests were executing — not whether the important behaviors were actually tested correctly. For example, a test might simply do 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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculatePrice&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;and just call the function without asserting anything meaningful about the result. In that case, coverage looks high, but confidence in correct behavior stays low. So it's better to treat coverage as a &lt;em&gt;signal&lt;/em&gt;, not a final goal.&lt;/p&gt;

&lt;p&gt;The more important question is whether the system's core business rules and failure modes have actually been tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Test Double ?
&lt;/h2&gt;

&lt;p&gt;A Test Double means using a temporary stand-in for a real dependency, used specifically during testing.&lt;/p&gt;

&lt;p&gt;The common types are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Stub:&lt;/strong&gt; returns a specific piece of fixed data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getUser() → returns User(id=10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A stub is essentially data a test can't run correctly without.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Mock:&lt;/strong&gt; used to verify invocations. 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;PaymentService.charge()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;must be called &lt;strong&gt;exactly once&lt;/strong&gt;, or the test fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Fake:&lt;/strong&gt; a simpler but still realistic implementation of a dependency. 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;InMemoryUserRepository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;used in place of a real database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Spy:&lt;/strong&gt; records information about a dependency's real behavior during a test run. For instance, letting &lt;code&gt;EmailService&lt;/code&gt; run as normal during a test, then checking how many times &lt;code&gt;sendEmail&lt;/code&gt; was called and with what parameters.&lt;/p&gt;

&lt;p&gt;Worth noting: these terms don't always mean exactly the same thing across different frameworks and sources. So what matters more than the label is understanding what role a given test double actually plays in your tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Test Should You Write, and Where ?
&lt;/h2&gt;

&lt;p&gt;For quick decision-making, you can use this rule of thumb:&lt;/p&gt;

&lt;p&gt;If you have simple business logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit Test:

Discount calculation
Tax calculation
Permission rules
Validation rules
Pricing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're interacting with a database or infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Integration Test:

Repository
Database
Redis
Message broker
File system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to verify an API capability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature / Functional Test:

POST /orders
POST /login
GET /profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If two microservices communicate with each other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Contract Test:

Order Service ↔ Payment Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the whole business flow matters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;E2E Test:

Login → Order → Payment → Confirmation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're dealing with untested legacy code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Characterization Test:

Current Behavior → Capture → Refactor Safely
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the input space is very large:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property-Based Test:

Generate Many Inputs
        ↓
Check Invariant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If unexpected or malformed inputs matter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fuzz Testing:

Generate Unexpected Inputs
        ↓
Execute System
        ↓
Find Crash / Failure / Unexpected Behavior
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to know the system's capacity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Load / Performance Test:

100 → 500 → 1000 req/s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Does a Professional Test Suite Look Like ?
&lt;/h2&gt;

&lt;p&gt;A professional backend probably has something structured 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;tests/
│
├── unit/
│   ├── pricing/
│   ├── validation/
│   └── authorization/
│
├── integration/
│   ├── database/
│   ├── redis/
│   └── messaging/
│
├── feature/
│   ├── orders/
│   ├── users/
│   └── payments/
│
├── contract/
│   └── payment-service/
│
├── e2e/
│   └── checkout/
│
├── characterization/
│   └── legacy-order/
│
├── property/
│   └── pricing/
│
└── fuzz/
    ├── api/
    └── parsers/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure is just one example — you don't need to implement it exactly this way. What matters is that the team knows exactly what risk each test exists to cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback Loop Matters More Than Test Count
&lt;/h2&gt;

&lt;p&gt;One common mistake is measuring a test suite's success by the number of tests it has. For example, 5,000 tests sounds impressive. But if running them takes 45 minutes, developers probably won't run them constantly. On the other hand, 1,500 tests that run in 30 seconds might deliver far more value throughout the development cycle. That's exactly why one of the most important traits of a professional test suite is &lt;strong&gt;fast feedback&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The lower the scope at which you can write an appropriate test, the faster your feedback tends to be, and the easier failures are to diagnose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Arrange/Act/Assert Pattern
&lt;/h2&gt;

&lt;p&gt;A very common structure for writing tests is the &lt;strong&gt;Arrange/Act/Assert&lt;/strong&gt; pattern. This structure improves readability in small tests and even in higher-level ones. It works like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arrange:&lt;/strong&gt; set up the data and dependencies&lt;br&gt;
&lt;strong&gt;Act:&lt;/strong&gt; run the code you want to test&lt;br&gt;
&lt;strong&gt;Assert:&lt;/strong&gt; verify the result&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;Arrange:

price = 1,000,000
customer = Premium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Act:

result = calculateDiscount(price, customer)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Assert:

result == 100,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Choose Tests Based on Risk, Not Habit
&lt;/h2&gt;

&lt;p&gt;The most important thing to take away from this article isn't that unit tests are good or E2E tests are bad — that view is overly simplistic. The right question isn't which type of test is "the best." It's: for a specific risk, which test gives you enough confidence at the lowest cost ?&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Automated Testing isn't just about writing a handful of unit tests to boost code coverage. A professional test suite should be a balanced collection of tests, each covering a different kind of risk.&lt;/p&gt;

&lt;p&gt;Unit Tests are for small, fast logic. Integration Tests are for the connections between units. Feature Tests are for the system's capabilities. Contract Tests are for the boundaries between microservices. E2E Tests are for critical real-world scenarios. And Characterization Tests are for understanding and safely working with legacy code.&lt;/p&gt;

&lt;p&gt;Alongside these, Property-Based Testing and Fuzz Testing offer different ways to uncover edge cases and unexpected behavior, and Mutation Testing helps you understand just how good your test suite actually is at catching incorrect changes.&lt;/p&gt;

&lt;p&gt;A good test isn't one that runs the most code — it's one that covers the most important risk at the lowest possible cost.&lt;/p&gt;

&lt;p&gt;Once this mindset becomes part of how you design a test suite, tests stop being a side cost and become part of your architecture and development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Final Question
&lt;/h2&gt;

&lt;p&gt;If tomorrow you had to refactor a legacy service that has almost no tests, what's the very first test you'd write ? What has your experience been like on real-world projects ?&lt;/p&gt;




&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/bliki/TestPyramid.html" rel="noopener noreferrer"&gt;Martin Fowler — Test Pyramid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;Martin Fowler — The Practical Test Pyramid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/2021-test-shapes.html" rel="noopener noreferrer"&gt;Martin Fowler — On the Diverse And Fantastical Shapes of Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/testing/" rel="noopener noreferrer"&gt;Microsoft Learn — Testing in .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices" rel="noopener noreferrer"&gt;Microsoft Learn — Unit Testing Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests" rel="noopener noreferrer"&gt;Microsoft Learn — Integration Tests in ASP.NET Core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.pact.io/" rel="noopener noreferrer"&gt;Pact — Contract Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.owasp.org/Fuzzing" rel="noopener noreferrer"&gt;OWASP — Fuzzing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hypothesis.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Hypothesis — Property-Based Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fast-check.dev/docs/introduction/" rel="noopener noreferrer"&gt;fast-check — Property-Based Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/bliki/LegacySeam.html" rel="noopener noreferrer"&gt;Martin Fowler — Legacy Seam&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>backend</category>
      <category>softwareengineering</category>
      <category>programming</category>
      <category>unittest</category>
    </item>
    <item>
      <title>The Outbox Pattern Explained: A Complete Guide to Reliable Messaging in Distributed Systems</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Tue, 22 Sep 2026 05:54:39 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/the-outbox-pattern-explained-a-complete-guide-to-reliable-messaging-in-distributed-systems-d99</link>
      <guid>https://dev.to/mehradsadeghi/the-outbox-pattern-explained-a-complete-guide-to-reliable-messaging-in-distributed-systems-d99</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgacoxztcmr9s7r41zywf.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgacoxztcmr9s7r41zywf.webp" alt=" " width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;small&gt;Image by Abhinav Thakur&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;What happens if your database successfully commits a transaction, but your &lt;a href="https://en.wikipedia.org/wiki/Message_broker" rel="noopener noreferrer"&gt;Message Broker&lt;/a&gt; becomes unavailable at exactly the same moment ?&lt;/p&gt;

&lt;p&gt;Imagine a user places an order in an online store, and the order is successfully stored in the database:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;A few milliseconds later, your service tries to send an &lt;code&gt;OrderCreated&lt;/code&gt; event to &lt;a href="https://en.wikipedia.org/wiki/Apache_Kafka" rel="noopener noreferrer"&gt;Kafka&lt;/a&gt; or &lt;a href="https://www.rabbitmq.com/" rel="noopener noreferrer"&gt;RabbitMQ&lt;/a&gt;, and suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The network goes down.&lt;/li&gt;
&lt;li&gt;The Broker becomes unavailable.&lt;/li&gt;
&lt;li&gt;The application crashes.&lt;/li&gt;
&lt;li&gt;A timeout occurs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what happens ?&lt;/p&gt;

&lt;p&gt;The database says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The order has been created.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the other services say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We have no idea about this order!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is one of the classic problems in distributed systems and &lt;a href="https://en.wikipedia.org/wiki/Microservices" rel="noopener noreferrer"&gt;Microservices&lt;/a&gt; architecture: the &lt;strong&gt;Dual Write Problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is where the &lt;a href="https://microservices.io/patterns/data/transactional-outbox.html" rel="noopener noreferrer"&gt;Outbox Pattern&lt;/a&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Idea Behind the Outbox Pattern
&lt;/h2&gt;

&lt;p&gt;The idea behind the Outbox Pattern is surprisingly simple.&lt;/p&gt;

&lt;p&gt;Instead of writing to the database and Message Broker at the same time, we store the &lt;strong&gt;business data change&lt;/strong&gt; and the corresponding &lt;strong&gt;message/event&lt;/strong&gt; in the same &lt;a href="https://dev.to/mehradsadeghi/two-transactions-one-row-what-does-mysql-actually-let-you-see--52ga"&gt;database transaction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We then delegate message publishing to a separate process.&lt;/p&gt;

&lt;p&gt;This small change in architecture can make a significant difference to system &lt;a href="https://iamkanikamodi.medium.com/reliability-v-s-resiliency-design-strategies-for-microservices-8d15729da081" rel="noopener noreferrer"&gt;reliability&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the Outbox Pattern ?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Outbox Pattern&lt;/strong&gt;, or more precisely the &lt;strong&gt;Transactional Outbox Pattern&lt;/strong&gt;, is a design pattern for reliably sending messages and events in distributed systems.&lt;/p&gt;

&lt;p&gt;Instead of having the application directly publish an event to a Message Broker after modifying the database, the application first stores the event in an &lt;strong&gt;Outbox Table&lt;/strong&gt; in the same database.&lt;/p&gt;

&lt;p&gt;The most important point is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The business data change and the event stored in the Outbox must happen within the same database transaction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A separate process then reads events from the Outbox and sends them to the Message Broker.&lt;/p&gt;

&lt;p&gt;At a high level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
      │
      │ Transaction
      ▼
┌───────────────────────┐
│       Database        │
│                       │
│  Orders               │
│  Outbox Events        │
└───────────┬───────────┘
            │
            │ Async
            ▼
      Outbox Publisher
            │
            ▼
      Message Broker
            │
       ┌────┴────┐
       ▼         ▼
   Service A  Service B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Do We Need the Outbox Pattern ?
&lt;/h2&gt;

&lt;p&gt;To understand the Outbox Pattern, we first need to understand the problem it solves.&lt;/p&gt;

&lt;p&gt;Suppose we have an &lt;code&gt;Order Service&lt;/code&gt; that needs to perform two operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Store the order in the database.&lt;/li&gt;
&lt;li&gt;Send the &lt;code&gt;OrderCreated&lt;/code&gt; event to Kafka.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our code might initially look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN TRANSACTION
INSERT INTO orders (...)
COMMIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;publish(OrderCreated)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this seems reasonable.&lt;/p&gt;

&lt;p&gt;But there is a dangerous gap between &lt;code&gt;COMMIT&lt;/code&gt; and &lt;code&gt;publish()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What happens if the database commits successfully but the application crashes before publishing the event ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
   │
   └── Order Created ✅

Message Broker
   │
   └── OrderCreated ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the system is in an inconsistent state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The internal business state has changed.&lt;/li&gt;
&lt;li&gt;The corresponding event was never published.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt; also describes Transactional Outbox as a solution to the Dual Write problem: a situation where one logical operation needs to modify both a database and a messaging system, while failure in one of them can leave the systems inconsistent.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the Dual Write Problem ?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Dual Write&lt;/strong&gt; occurs when one logical operation needs to be writtern into two independent systems.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
    +
Kafka
&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 plaintext"&gt;&lt;code&gt;Database
    +
RabbitMQ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
    +
External API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that we usually don't have a shared transaction between these two systems.&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;1. UPDATE database ✅
2. SEND message    ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the opposite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. SEND message    ✅
2. UPDATE database ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first case, the event is lost.&lt;/p&gt;

&lt;p&gt;In the second case, an event has been published even though the corresponding business state does not actually exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Isn't a Normal Database Transaction Enough ?
&lt;/h2&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Why don't we simply put message publishing inside the transaction ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem is that the database and Message Broker are two independent resources. To make the entire operation &lt;a href="https://en.wikipedia.org/wiki/ACID" rel="noopener noreferrer"&gt;atomic&lt;/a&gt;, we would need some form of &lt;a href="https://en.wikipedia.org/wiki/Distributed_transaction" rel="noopener noreferrer"&gt;distributed transaction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One classic approach is &lt;strong&gt;Two-Phase Commit&lt;/strong&gt;, or &lt;strong&gt;2PC&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In 2PC, a coordinator asks all participants:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are you ready to commit your changes ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Only when all participants agree, the coordinator instruct them to perform the final commit.&lt;/p&gt;

&lt;p&gt;If one participant has a problem, the entire operation can be stopped.&lt;/p&gt;

&lt;p&gt;This approach is theoretically attractive, but modern distributed architectures can introduce problems such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complexity&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Coupling&lt;/li&gt;
&lt;li&gt;Failure handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, not every database or Message Broker supports distributed transactions in the same way.&lt;/p&gt;

&lt;p&gt;The Outbox Pattern asks a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do we really need the database and Broker to participate in one transaction ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead, we can reliably record the critical operation in a local database transaction and defer message publishing until afterward.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does the Outbox Pattern Solve the Dual Write Problem ?
&lt;/h2&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;Database → Commit
Broker   → Publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
├── Business Data
└── Outbox Event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&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;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CREATED'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aggregate_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aggregate_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'event-789'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Order'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'OrderCreated'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{...}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the transaction succeeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order        ✅
Outbox Event ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the transaction fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order        ❌
Outbox Event ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database guarantees that both changes are committed or rolled back together.&lt;/p&gt;

&lt;p&gt;This is the key idea behind the Outbox Pattern.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an Outbox Table ?
&lt;/h2&gt;

&lt;p&gt;An Outbox is usually just a normal database table.&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 sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;              &lt;span class="n"&gt;UUID&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aggregate_type&lt;/span&gt;  &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;aggregate_id&lt;/span&gt;    &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;event_type&lt;/span&gt;      &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;         &lt;span class="n"&gt;JSONB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;      &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;processed_at&lt;/span&gt;    &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual schema can vary depending on your system's requirements.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  1. &lt;code&gt;id&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A unique identifier for the event.&lt;/p&gt;

&lt;p&gt;This ID is extremely important for &lt;a href="https://en.wikipedia.org/wiki/Data_deduplication" rel="noopener noreferrer"&gt;Deduplication&lt;/a&gt; and &lt;a href="https://medium.com/@jyc.dev/idempotency-in-software-engineering-why-it-matters-and-how-to-implement-it-2025-guide-c1ef8ad21965" rel="noopener noreferrer"&gt;Idempotency&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;aggregate_id&lt;/code&gt;
&lt;/h3&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_id = 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This field can be important for maintaining event ordering in many architectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;event_type&lt;/code&gt;
&lt;/h3&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;OrderCreated
OrderPaid
OrderCancelled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;code&gt;payload&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The actual event data:&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;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&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;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalAmount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;250&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;h3&gt;
  
  
  5. &lt;code&gt;created_at&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The time at which the event was created.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;code&gt;processed_at&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;With a polling-based implementation, this field can be used to identify events that have already been processed.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does the Complete Outbox Flow Work ?
&lt;/h2&gt;

&lt;p&gt;Let's look at the complete flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
Order Service
   │
   │ BEGIN TRANSACTION
   ├────────────────────────┐
   │                        │
   ▼                        ▼
Orders Table          Outbox Table
   │                        │
   └──────────┬─────────────┘
              │
            COMMIT
              │
              ▼
       Outbox Publisher
              │
              ▼
        Message Broker
              │
       ┌──────┴──────┐
       ▼             ▼
 Inventory       Notification
 Service           Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Client sends a request to create an Order.&lt;/li&gt;
&lt;li&gt;The Order Service starts a Transaction.&lt;/li&gt;
&lt;li&gt;The Order is stored in the database.&lt;/li&gt;
&lt;li&gt;The corresponding Event is stored in the Outbox.&lt;/li&gt;
&lt;li&gt;The Transaction is committed.&lt;/li&gt;
&lt;li&gt;An Outbox Publisher reads the event from the Outbox.&lt;/li&gt;
&lt;li&gt;The Event is sent to the Message Broker.&lt;/li&gt;
&lt;li&gt;Different Consumers receive the Event.&lt;/li&gt;
&lt;li&gt;After successful publishing, the Outbox Event is cleaned up or marked as processed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An important detail is that the application does not need to wait for the Broker for the original request to succeed.&lt;/p&gt;

&lt;p&gt;This means event publishing can happen asynchronously.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real-World Example: Creating an Order
&lt;/h2&gt;

&lt;p&gt;Suppose a user creates order &lt;code&gt;1001&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Order
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;The application starts a transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Store the Order
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orders

id: 1001
status: CREATED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Store the Event
&lt;/h3&gt;

&lt;p&gt;Inside the same transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;outbox

id: event-abc
event_type: OrderCreated
aggregate_id: 1001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Commit
&lt;/h3&gt;

&lt;p&gt;If the commit succeeds:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, even if the application crashes immediately afterward, the event has not been lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Publish the Event
&lt;/h3&gt;

&lt;p&gt;The Publisher eventually sends:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Consumers Process the Event
&lt;/h3&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;Inventory Service:

OrderCreated
      ↓
Reserve Stock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Notification Service:

OrderCreated
      ↓
Send Confirmation Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analytics Service:

OrderCreated
      ↓
Record Conversion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where the Outbox Pattern becomes especially useful for &lt;a href="https://en.wikipedia.org/wiki/Event-driven_architecture" rel="noopener noreferrer"&gt;Event-Driven Architecture&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Does the Outbox Pattern Prevent Duplicate Messages ?
&lt;/h2&gt;

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

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

&lt;p&gt;The Outbox Pattern can ensure that an event is not lost, but it does not necessarily guarantee that the event will be published exactly once.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;The Publisher reads the event.&lt;/li&gt;
&lt;li&gt;The Publisher sends the event to Kafka.&lt;/li&gt;
&lt;li&gt;Kafka successfully receives the message.&lt;/li&gt;
&lt;li&gt;The Publisher crashes before marking the event as processed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After the Publisher restarts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Publisher
   ↓
"This event is still unprocessed"
   ↓
Publish Again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a result, &lt;code&gt;OrderCreated&lt;/code&gt; may reach the Consumer twice.&lt;/p&gt;

&lt;p&gt;This behavior is normal and is associated with &lt;a href="https://medium.com/@madhur25/meaning-of-at-least-once-at-most-once-and-exactly-once-delivery-10e477fafe16" rel="noopener noreferrer"&gt;At-Least-Once Delivery&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html" rel="noopener noreferrer"&gt;AWS's Transactional Outbox guidance&lt;/a&gt; also discusses duplicate messages and the need for idempotent Consumers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Idempotency: The Other Half of the Story
&lt;/h2&gt;

&lt;p&gt;If you use the Outbox Pattern, you need to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens if the same event reaches a Consumer twice ?&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 plaintext"&gt;&lt;code&gt;PaymentCompleted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose the Consumer processes the event twice and each time performs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$100 → Charge Customer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The customer could potentially be charged twice.&lt;/p&gt;

&lt;p&gt;The Consumer therefore needs a way to detect duplicate events.&lt;/p&gt;

&lt;p&gt;One common approach is to maintain a table such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processed_events

event_id
--------
event-123
event-456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does event-123 exist ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it exists:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If it doesn't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Process
Insert event_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ideally, these operations should also happen inside a transaction.&lt;/p&gt;

&lt;p&gt;This makes the Outbox Pattern and the Idempotent Consumer Pattern complementary solutions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Does Outbox Mean Exactly-Once Delivery ?
&lt;/h2&gt;

&lt;p&gt;This is where terminology matters.&lt;/p&gt;

&lt;p&gt;You sometimes hear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Outbox Pattern provides Exactly-Once Delivery.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That statement is an oversimplification.&lt;/p&gt;

&lt;p&gt;The Outbox Pattern by itself does not provide an exactly-once guarantee.&lt;/p&gt;

&lt;p&gt;A more realistic 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;Producer
   ↓
Outbox
   ↓
At-Least-Once Publish
   ↓
Idempotent Consumer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This combination can provide much more reliable behavior in terms of the final business state.&lt;/p&gt;

&lt;p&gt;However, if the Consumer calls an external API, guaranteeing exactly-once behavior across the entire chain becomes much more complicated.&lt;/p&gt;

&lt;p&gt;The important point is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Exactly-once is not simply a property of one component; it is an end-to-end property.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  How Is an Outbox Event Published to the Broker ?
&lt;/h2&gt;

&lt;p&gt;There are two common approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://medium.com/@nustianrwp/the-transactional-outbox-pattern-a-rigorous-examination-for-distributed-systems-engineers-9c189836f470" rel="noopener noreferrer"&gt;Polling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@nustianrwp/the-transactional-outbox-pattern-a-rigorous-examination-for-distributed-systems-engineers-9c189836f470" rel="noopener noreferrer"&gt;Change Data Capture (CDC)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Approach 1: Polling Publisher
&lt;/h2&gt;

&lt;p&gt;With polling, a worker periodically queries the Outbox table.&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 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;outbox&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;processed_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&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;created_at&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read
 ↓
Publish
 ↓
Mark as processed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The biggest advantage of polling is simplicity.&lt;/p&gt;

&lt;p&gt;You don't need your system to work directly with the database's Transaction Log. Almost any database that supports queries can be used to build this type of architecture.&lt;/p&gt;

&lt;p&gt;However, polling has a latency trade-off.&lt;/p&gt;

&lt;p&gt;For example, if you poll every five seconds, an event created immediately after a polling cycle might have to wait almost five seconds before being detected.&lt;/p&gt;

&lt;p&gt;If you poll more frequently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100ms
50ms
10ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you increase the load on the database.&lt;/p&gt;

&lt;p&gt;So you have a trade-off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Polling Frequency
       ↕
    Latency
       ↕
Database Load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Approach 2: Change Data Capture (CDC)
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://medium.com/@nustianrwp/the-transactional-outbox-pattern-a-rigorous-examination-for-distributed-systems-engineers-9c189836f470" rel="noopener noreferrer"&gt;Change Data Capture (CDC)&lt;/a&gt;, instead of repeatedly querying the Outbox table, we track changes in the database's Transaction Log.&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;Application
     ↓
Database
     ↓
Transaction Log
     ↓
CDC Connector
     ↓
Message Broker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different databases may use transaction logs such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WAL
Binlog
Redo Log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tools such as &lt;a href="https://debezium.io/" rel="noopener noreferrer"&gt;Debezium&lt;/a&gt; can capture changes to an Outbox Table from the Transaction Log and transform them into events.&lt;/p&gt;

&lt;p&gt;Debezium also provides a dedicated &lt;a href="https://debezium.io/documentation/reference/stable/transformations/outbox-event-router.html" rel="noopener noreferrer"&gt;Outbox Event Router&lt;/a&gt; for this scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of CDC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Lower latency&lt;/li&gt;
&lt;li&gt;Less continuous polling&lt;/li&gt;
&lt;li&gt;Suitable for high throughput&lt;/li&gt;
&lt;li&gt;Better alignment with Transaction Log changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages of CDC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More architectural complexity&lt;/li&gt;
&lt;li&gt;More infrastructure and monitoring requirements&lt;/li&gt;
&lt;li&gt;Dependency on database capabilities&lt;/li&gt;
&lt;li&gt;Higher operational complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, CDC is not necessarily better than polling. It is simply more appropriate for certain scales and latency requirements.&lt;/p&gt;




&lt;h2&gt;
  
  
  Polling or CDC: Which Should You Choose ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4aigmsdox815dsjk3hcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4aigmsdox815dsjk3hcl.png" alt=" " width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your system is still relatively new, polling can be a straightforward approach.&lt;/p&gt;

&lt;p&gt;If event volume is high and low latency is particularly important, CDC can become a more suitable option.&lt;/p&gt;

&lt;p&gt;The choice ultimately depends on factors such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event volume&lt;/li&gt;
&lt;li&gt;Latency requirements&lt;/li&gt;
&lt;li&gt;Database capabilities&lt;/li&gt;
&lt;li&gt;Operational complexity&lt;/li&gt;
&lt;li&gt;Infrastructure maturity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Does the Outbox Pattern Preserve Event Ordering ?
&lt;/h2&gt;

&lt;p&gt;Not automatically, and not in every architecture.&lt;/p&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OrderCreated
OrderPaid
OrderShipped
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Consumer may need to receive these events in exactly this order.&lt;/p&gt;

&lt;p&gt;If it receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OrderShipped
OrderCreated
OrderPaid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the business logic could behave incorrectly.&lt;/p&gt;

&lt;p&gt;Therefore, ordering needs to be designed intentionally.&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;aggregate_id = order-123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then route events belonging to the same Aggregate to the same Partition in the Message Broker.&lt;/p&gt;

&lt;p&gt;With Kafka, a Partition Key can help ensure that events for a particular Aggregate are placed in the same Partition and processed in order within that Partition.&lt;/p&gt;

&lt;p&gt;The important distinction is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Outbox Pattern and Message Ordering are related, but they are separate problems.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Happens to the Outbox Table Over Time ?
&lt;/h2&gt;

&lt;p&gt;Suppose your system generates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 events / second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;86,400,000 events / day
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you never delete or archive processed events, the Outbox table will grow rapidly.&lt;/p&gt;

&lt;p&gt;This can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increased database size&lt;/li&gt;
&lt;li&gt;Larger &lt;a href="https://en.wikipedia.org/wiki/Database_index" rel="noopener noreferrer"&gt;database indexes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Heavier backups&lt;/li&gt;
&lt;li&gt;Slower queries&lt;/li&gt;
&lt;li&gt;Higher storage costs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, an Outbox needs a &lt;strong&gt;Lifecycle Strategy&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;Pending
   ↓
Published
   ↓
Retention Period
   ↓
Delete / Archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h4&gt;
  
  
  1. Delete
&lt;/h4&gt;

&lt;p&gt;Delete events after they have been successfully published.&lt;/p&gt;

&lt;p&gt;This is simple and inexpensive, but it makes historical replay more difficult.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Archive
&lt;/h4&gt;

&lt;p&gt;Move events to another storage system after a certain period.&lt;/p&gt;

&lt;p&gt;This can be more useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auditing&lt;/li&gt;
&lt;li&gt;Debugging&lt;/li&gt;
&lt;li&gt;Historical analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Partitioning
&lt;/h4&gt;

&lt;p&gt;Partition the table based on time.&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;outbox_2026_09_18
outbox_2026_09_19
outbox_2026_09_20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Old partitions can then be deleted or archived efficiently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Advantages of the Outbox Pattern
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Preventing Lost Events
&lt;/h3&gt;

&lt;p&gt;The most important advantage of the Outbox Pattern is that when the Business Transaction commits, the Event is also stored.&lt;/p&gt;

&lt;p&gt;Therefore, if the Publisher crashes immediately after the commit, the Event is not lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. No Need for 2PC
&lt;/h3&gt;

&lt;p&gt;The database and Broker do not need to participate in a shared Distributed Transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Separation of Business Operations and Message Publishing
&lt;/h3&gt;

&lt;p&gt;The Business Request does not need to wait for the Broker.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Suitable for Event-Driven Architecture
&lt;/h3&gt;

&lt;p&gt;The Outbox Pattern is particularly useful for communication between Microservices.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Easier Retries
&lt;/h3&gt;

&lt;p&gt;If the Broker is temporarily unavailable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outbox
   ↓
Retry
   ↓
Retry
   ↓
Success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Event remains safely stored in the database.&lt;/p&gt;




&lt;h2&gt;
  
  
  Disadvantages of the Outbox Pattern
&lt;/h2&gt;

&lt;p&gt;The Outbox Pattern solves one class of reliability problems, but it also introduces additional responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Increased Complexity
&lt;/h3&gt;

&lt;p&gt;Instead of having only a database, you may now have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
+
Outbox
+
Publisher
+
Broker
+
Retry
+
Monitoring
+
Cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Duplicate Events
&lt;/h3&gt;

&lt;p&gt;The Publisher may send an Event more than once.&lt;/p&gt;

&lt;p&gt;Therefore, Consumers should be designed to be idempotent.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Eventual Consistency
&lt;/h3&gt;

&lt;p&gt;An Event does not necessarily reach every service immediately after the database transaction commits.&lt;/p&gt;

&lt;p&gt;For a short period, you might have:&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     → CREATED
Inventory Service → still knows nothing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This delay needs to be acceptable from a business perspective.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Outbox Growth
&lt;/h3&gt;

&lt;p&gt;Without a proper lifecycle strategy, the Outbox can become a very large table.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. New Failure Modes
&lt;/h3&gt;

&lt;p&gt;You now need to handle problems such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Publisher Crash
Broker Down
Database Down
Poison Message
Retry Storm
Duplicate Event
Outbox Backlog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Outbox Pattern therefore does not eliminate reliability problems.&lt;/p&gt;

&lt;p&gt;Instead, it changes the types of failures your system needs to handle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Outbox Pattern vs. 2PC
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbbyzu9g2x6cqumfrhv3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbbyzu9g2x6cqumfrhv3b.png" alt=" " width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Outbox Pattern takes a fundamentally different approach from distributed transactions.&lt;/p&gt;

&lt;p&gt;Instead of trying to create one global transaction, it keeps the transaction within the boundaries of a single database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database Transaction
├── Business Data
└── Outbox Event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Message publishing happens afterward.&lt;/p&gt;

&lt;p&gt;The goal is not to make the database and Message Broker participate in the same transaction, but to make the database operation itself reliable and then handle message delivery separately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Outbox vs. Direct Event Publishing
&lt;/h2&gt;

&lt;p&gt;The simple approach is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UPDATE DB
   ↓
PUBLISH EVENT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simple&lt;/li&gt;
&lt;li&gt;Low cost&lt;/li&gt;
&lt;li&gt;Low latency&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Dual Write&lt;/li&gt;
&lt;li&gt;Potential Lost Event&lt;/li&gt;
&lt;li&gt;Failure Window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Outbox approach is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UPDATE DB
   +
INSERT OUTBOX
   ↓
COMMIT
   ↓
PUBLISH ASYNC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Higher reliability&lt;/li&gt;
&lt;li&gt;Easier retries&lt;/li&gt;
&lt;li&gt;No Lost Event in common failures between Commit and Publish&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Costs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Increased complexity&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Eventual_consistency" rel="noopener noreferrer"&gt;Eventual Consistency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Duplicate handling&lt;/li&gt;
&lt;li&gt;Operational overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, if an Event is not actually critical, the Outbox Pattern is not necessarily required.&lt;/p&gt;

&lt;p&gt;For example, if Events are used only for non-critical analytics and losing a small percentage of them is acceptable, keeping the architecture simple may be more valuable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is the Outbox Pattern Only for Microservices ?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;A common misconception is that the Outbox Pattern is exclusively a Microservices pattern.&lt;/p&gt;

&lt;p&gt;Even in a &lt;a href="https://www.geeksforgeeks.org/system-design/monolithic-architecture-system-design/" rel="noopener noreferrer"&gt;Monolithic Architecture&lt;/a&gt;, you may need to perform an external operation after changing the database.&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 Created
     ↓
Call a Webhook
&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 plaintext"&gt;&lt;code&gt;User Registered
     ↓
Send Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the Email Provider is temporarily unavailable, you may not want to fail the user's registration.&lt;/p&gt;

&lt;p&gt;Instead, you can store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
+
Email Event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;inside the same transaction and send the email asynchronously afterward.&lt;/p&gt;

&lt;p&gt;So the Outbox Pattern is better understood as a reliable solution for &lt;a href="https://aws.amazon.com/blogs/compute/understanding-asynchronous-messaging-for-microservices/" rel="noopener noreferrer"&gt;Asynchronous Messaging&lt;/a&gt; rather than something limited to Microservices.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Is the Outbox Pattern Worth Using ?
&lt;/h2&gt;

&lt;p&gt;The Outbox Pattern is particularly valuable when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Event is important to the business.&lt;/li&gt;
&lt;li&gt;Losing an Event is unacceptable.&lt;/li&gt;
&lt;li&gt;The database and Broker are independent systems.&lt;/li&gt;
&lt;li&gt;The architecture is Event-Driven.&lt;/li&gt;
&lt;li&gt;Services communicate asynchronously.&lt;/li&gt;
&lt;li&gt;Retry and reliability are important.&lt;/li&gt;
&lt;li&gt;Immediate consistency between services is not required.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When Isn't the Outbox Pattern Necessary ?
&lt;/h2&gt;

&lt;p&gt;If an Event is completely non-critical, adding an Outbox may introduce unnecessary complexity.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicked button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose this Event is used only for approximate analytics.&lt;/p&gt;

&lt;p&gt;If losing some Events is acceptable, direct publishing—or even an independent analytics system—may be a simpler solution.&lt;/p&gt;

&lt;p&gt;The right architecture depends on the business consequences of failure.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Considerations When Implementing Outbox
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Use a Unique Event ID
&lt;/h3&gt;

&lt;p&gt;Every Event should have a stable identifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event_id = UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ID is essential for Deduplication.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Design Consumers to Be Idempotent
&lt;/h3&gt;

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

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

&lt;/div&gt;



&lt;p&gt;is delivered twice.&lt;/p&gt;

&lt;p&gt;The result should not be:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The Consumer needs to recognize that the Event has already been processed.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Index the Outbox
&lt;/h3&gt;

&lt;p&gt;If you use polling, queries 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;WHERE&lt;/span&gt; &lt;span class="n"&gt;processed_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&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;created_at&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should be supported by appropriate indexes based on your workload and access patterns.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Consider Batch Processing
&lt;/h3&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;1 Event → 1 Query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you may be better off processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100 Events → 1 Batch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://aws.amazon.com/what-is/batch-processing/" rel="noopener noreferrer"&gt;AWS Batch Processing guidance&lt;/a&gt; provides useful background on batch processing.&lt;/p&gt;

&lt;p&gt;However, very large batches can also increase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lock duration&lt;/li&gt;
&lt;li&gt;Memory usage&lt;/li&gt;
&lt;li&gt;Retry costs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the batch size should be chosen carefully.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Use Retry with Backoff
&lt;/h3&gt;

&lt;p&gt;If the Broker is unavailable, you should not continuously retry every few milliseconds.&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;1s
2s
4s
8s
16s
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use exponential backoff together with appropriate retry limits and policies.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Don't Forget &lt;a href="https://www.linkedin.com/posts/mehradsadeghi_softwarearchitecture-distributedsystems-microservices-share-7499746869149884416-5ha3/" rel="noopener noreferrer"&gt;Dead-Letter&lt;/a&gt; Handling
&lt;/h3&gt;

&lt;p&gt;Sometimes an Event will consistently fail.&lt;/p&gt;

&lt;p&gt;If you retry indefinitely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event
 ↓
Fail
 ↓
Retry
 ↓
Fail
 ↓
Retry
 ↓
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can create a &lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/architecture/antipatterns/retry-storm/" rel="noopener noreferrer"&gt;Retry Storm&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A problematic Event therefore needs an explicit failure-handling strategy, such as a Dead Letter mechanism.&lt;/p&gt;




&lt;h2&gt;
  
  
  An Important Note About Monitoring
&lt;/h2&gt;

&lt;p&gt;One of the most useful Outbox metrics is the number of Events waiting to be published.&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;Outbox Pending Events = 12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;might be completely normal.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outbox Pending Events = 2,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;could indicate that the Publisher has fallen significantly behind.&lt;/p&gt;

&lt;p&gt;Useful metrics can include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outbox Backlog
Publish Latency
Publish Failure Rate
Retry Count
Oldest Unprocessed Event Age
Consumer Lag
Dead Letter Count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One particularly valuable metric is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Oldest Unprocessed Event Age
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;Age = 45 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if the total number of pending Events is relatively small, an old unprocessed Event could indicate an operational problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Outbox Pattern and Eventual Consistency
&lt;/h2&gt;

&lt;p&gt;The Outbox Pattern forces us to accept an important reality of distributed systems:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not everything needs to be immediately consistent.&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 plaintext"&gt;&lt;code&gt;T0:
Order Created

T0 + 20ms:
Outbox Published

T0 + 50ms:
Inventory Updated

T0 + 100ms:
Notification Sent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a short period, the system might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Service     → CREATED
Inventory Service → Previous State
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not necessarily a bug.&lt;/p&gt;

&lt;p&gt;If your business requirements allow this delay, Eventual Consistency can be a perfectly reasonable trade-off.&lt;/p&gt;

&lt;p&gt;In Event-Driven Architectures, this is one of the fundamental design considerations.&lt;/p&gt;

&lt;p&gt;Duplication, ordering, and idempotency all need to be deliberately designed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Outbox Pattern&lt;/strong&gt; is a solution to one of the classic problems in distributed systems: the &lt;strong&gt;Dual Write Problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of having an application simultaneously modify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
+
Message Broker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we store the business state change and its corresponding Event in a single local database transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
├── Business Data
└── Outbox Event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A separate process then transfers the Event to the Message Broker.&lt;/p&gt;

&lt;p&gt;The main benefit is straightforward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the original transaction commits, the corresponding Event is also persisted and can be retried later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the Outbox Pattern is not the end of the story.&lt;/p&gt;

&lt;p&gt;You still need to deal with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate messages&lt;/li&gt;
&lt;li&gt;Idempotency&lt;/li&gt;
&lt;li&gt;Ordering&lt;/li&gt;
&lt;li&gt;Eventual Consistency&lt;/li&gt;
&lt;li&gt;Retries&lt;/li&gt;
&lt;li&gt;Outbox Growth&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Cleanup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, the Outbox Pattern does not eliminate distributed-system complexity.&lt;/p&gt;

&lt;p&gt;It moves that complexity into areas where it can be managed more explicitly.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Question for Discussion
&lt;/h2&gt;

&lt;p&gt;If losing an Event is unacceptable for your system, but a few seconds of Eventual Consistency is tolerable, would you introduce the additional complexity of the Outbox Pattern, retries, and idempotency ?&lt;/p&gt;

&lt;p&gt;And at what point would you decide that architectural simplicity is more valuable than higher messaging reliability ?&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://microservices.io/patterns/data/transactional-outbox.html%20?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Transactional Outbox — Microservices.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html" rel="noopener noreferrer"&gt;AWS Prescriptive Guidance — Transactional Outbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://debezium.io/documentation/reference/stable/transformations/outbox-event-router.html" rel="noopener noreferrer"&gt;Debezium — Outbox Event Router&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/architecture/databases/guide/transactional-out-box-cosmos" rel="noopener noreferrer"&gt;Microsoft Azure Architecture Center — Transactional Outbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/igornosatov_15/the-outbox-pattern-a-love-letter-to-eventual-consistency-3ch3"&gt;The Outbox Pattern: A Love Letter to Eventual Consistency&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microservices</category>
      <category>distributedsystems</category>
      <category>outboxpattern</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Circuit Breaker Pattern Explained: How to Prevent Cascading Failures in Distributed Systems</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Wed, 16 Sep 2026 13:05:24 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/circuit-breaker-pattern-explained-how-to-prevent-cascading-failures-in-distributed-systems-1jc6</link>
      <guid>https://dev.to/mehradsadeghi/circuit-breaker-pattern-explained-how-to-prevent-cascading-failures-in-distributed-systems-1jc6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkfy3aoqm3lnl2363wn2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkfy3aoqm3lnl2363wn2y.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;small&gt; Circuit Breaker Pattern &lt;/small&gt;&lt;/center&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;What happens when one service fails, but your entire system keeps calling it anyway ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine your payment service is down. Normally, every purchase request follows a path 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;User
 ↓
Order Service
 ↓
Payment Service
 ↓
Bank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the Payment Service is unavailable — or perhaps it’s simply extremely slow. A request that normally takes &lt;strong&gt;200 ms&lt;/strong&gt; now takes &lt;strong&gt;10 seconds&lt;/strong&gt;. If your system continues sending requests to it, what happens ?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Request queues grow.&lt;/li&gt;
&lt;li&gt;  Threads and connections remain occupied.&lt;/li&gt;
&lt;li&gt;  Timeouts increase.&lt;/li&gt;
&lt;li&gt;  Latency goes up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And eventually, services that were perfectly healthy can start failing too.&lt;/p&gt;

&lt;p&gt;In other words, &lt;strong&gt;one failing dependency can potentially bring down an entire system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where the &lt;a href="https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern" rel="noopener noreferrer"&gt;&lt;strong&gt;Circuit Breaker pattern&lt;/strong&gt;&lt;/a&gt; comes in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of continuously calling a dependency that is already failing, the system temporarily stops sending requests to it and &lt;strong&gt;fails fast&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal isn’t to fix the broken service. The goal is to &lt;strong&gt;prevent its failure from spreading&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is the Circuit Breaker Pattern ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Circuit Breaker is a &lt;a href="https://www.geeksforgeeks.org/system-design/resilient-distributed-systems/" rel="noopener noreferrer"&gt;resilience&lt;/a&gt; pattern commonly used in distributed systems to protect services from repeatedly calling an unhealthy dependency.&lt;/p&gt;

&lt;p&gt;The idea comes from electrical circuit breakers. When electrical current becomes dangerously high, a circuit breaker interrupts the circuit to prevent further damage.&lt;/p&gt;

&lt;p&gt;Software can apply a similar idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Healthy dependency
↓
Requests flow
↓
Dependency starts failing
↓
Failure threshold reached
↓
Circuit opens
↓
Requests fail fast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Circuit Breaker doesn’t repair the dependency.&lt;/p&gt;

&lt;p&gt;Instead, it can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Stop unnecessary requests to a failing service&lt;/li&gt;
&lt;li&gt;  Protect your own application’s resources&lt;/li&gt;
&lt;li&gt;  Reduce additional load on the unhealthy dependency&lt;/li&gt;
&lt;li&gt;  Help prevent &lt;a href="https://medium.com/@ninadwalanj/how-failure-cascades-in-distributed-systems-eccc48c9851a" rel="noopener noreferrer"&gt;cascading failures&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Give the dependency time to &lt;a href="https://www.geeksforgeeks.org/operating-systems/recovery-in-distributed-systems/" rel="noopener noreferrer"&gt;recover&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Allow the system to &lt;a href="https://www.geeksforgeeks.org/system-design/graceful-degradation-in-distributed-systems/" rel="noopener noreferrer"&gt;degrade gracefully&lt;/a&gt; when possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful way to think about it is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Circuit Breaker doesn’t eliminate failure. It prevents failure from becoming a larger system-wide failure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Do Distributed Systems Need Circuit Breakers ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In a simple &lt;a href="https://www.geeksforgeeks.org/system-design/monolithic-architecture-system-design/" rel="noopener noreferrer"&gt;monolithic application&lt;/a&gt;, you might call a function like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calculatePrice()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the function fails, handling the failure is usually relatively straightforward. But &lt;a href="https://en.wikipedia.org/wiki/Distributed_computing" rel="noopener noreferrer"&gt;distributed systems&lt;/a&gt; are different.&lt;/p&gt;

&lt;p&gt;A call to another service crosses a network boundary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Service A
↓
Service B
↓
Service C
↓
External APIService A
↓
Service B
↓
Service C
↓
External API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike a local function call, a remote call can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Time out&lt;/li&gt;
&lt;li&gt;  Lose its connection&lt;/li&gt;
&lt;li&gt;  Become extremely slow&lt;/li&gt;
&lt;li&gt;  Return a 5xx error&lt;/li&gt;
&lt;li&gt;  Be rate-limited&lt;/li&gt;
&lt;li&gt;  Become completely unavailable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the more important problem is that &lt;strong&gt;failure can propagate between services&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 Service
↓
starts failing
↓
Order Service waits
↓
Threads become occupied
↓
Requests start queuing
↓
Latency increases
↓
Error rate increases
↓
The entire service comes under pressure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;strong&gt;cascading failure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The original problem may have started in one service, but the resulting resource exhaustion can spread to otherwise healthy parts of the system.&lt;/p&gt;

&lt;p&gt;Circuit Breaker is one of the patterns that can help interrupt this chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reliability, High Availability, and Circuit Breakers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Two concepts often appear in discussions about distributed systems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reliability:&lt;/strong&gt; is about a system behaving dependably in the presence of failures and recovering appropriately when failures occur.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High Availability:&lt;/strong&gt; is about keeping a system accessible to users even when parts of its infrastructure or dependencies experience problems.&lt;/p&gt;

&lt;p&gt;A Circuit Breaker does &lt;strong&gt;not&lt;/strong&gt; make an external service permanently available.&lt;/p&gt;

&lt;p&gt;Instead, it can help isolate its failure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dependency Failure
↓
Circuit Breaker
↓
Failure Isolation
↓
Graceful Degradation
↓
System remains responsive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where the idea of &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/resilience-analysis-framework/overview.html" rel="noopener noreferrer"&gt;&lt;strong&gt;failure isolation&lt;/strong&gt;&lt;/a&gt; becomes important.&lt;/p&gt;

&lt;p&gt;Instead of allowing one dependency’s failure to spread across the entire system, we try to limit its &lt;strong&gt;blast radius&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Does a Circuit Breaker Work ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A Circuit Breaker is commonly modeled as a &lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine" rel="noopener noreferrer"&gt;state machine&lt;/a&gt; with three primary states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Closed&lt;/li&gt;
&lt;li&gt;  Open&lt;/li&gt;
&lt;li&gt;  Half-Open&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CLOSED - Everything Is Normal&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When the Circuit Breaker is &lt;strong&gt;CLOSED&lt;/strong&gt;, requests are allowed to reach the dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
↓
Circuit Breaker
↓
Payment Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Circuit Breaker monitors the results of those requests. 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;100 requests
95 successes
5 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the failure rate exceeds the configured threshold, the circuit transitions to OPEN.&lt;/p&gt;

&lt;p&gt;But an important detail is that a failure threshold doesn’t necessarily mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Five requests failed consecutively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The threshold can be based on different measurements, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Number of failures&lt;/li&gt;
&lt;li&gt;  Failure percentage&lt;/li&gt;
&lt;li&gt;  Number of timeouts&lt;/li&gt;
&lt;li&gt;  Failures within a time window&lt;/li&gt;
&lt;li&gt;  A combination of multiple metrics&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;50 failures in the last 100 requests
&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 plaintext"&gt;&lt;code&gt;Failure Rate &amp;gt; 30% during the last 30 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The right threshold depends on the actual behavior of the dependency and the reliability &lt;a href="https://en.wikipedia.org/wiki/Service-level_objective" rel="noopener noreferrer"&gt;objectives&lt;/a&gt; of your system. There is no universal magic number.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;OPEN - Stop Calling the Failing Service&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When the Circuit Breaker transitions to &lt;strong&gt;OPEN&lt;/strong&gt;, its behavior changes completely.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
↓
Circuit Breaker
↓
Payment Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
↓
Circuit Breaker
↓
FAIL FAST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request never reaches the Payment Service. This is the central idea behind the Circuit Breaker pattern. If we already have strong evidence that a dependency is unhealthy, why should every new request wait for another network timeout ?&lt;/p&gt;

&lt;p&gt;Suppose the Payment Service has a &lt;strong&gt;10-second timeout&lt;/strong&gt;. Now imagine 1,000 concurrent requests all waiting for that timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 requests × 10 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A significant amount of your application’s resources can remain occupied simply waiting for a dependency that is already failing.&lt;/p&gt;

&lt;p&gt;With an open circuit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
↓
Circuit = OPEN
↓
Immediate failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system can reject the request much earlier.&lt;/p&gt;

&lt;p&gt;That can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Free threads&lt;/li&gt;
&lt;li&gt;  Preserve connections&lt;/li&gt;
&lt;li&gt;  Reduce resource consumption&lt;/li&gt;
&lt;li&gt;  Keep latency more predictable&lt;/li&gt;
&lt;li&gt;  Prevent additional traffic from reaching the unhealthy dependency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes &lt;strong&gt;failing quickly is better than failing slowly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But the circuit should not remain open forever. If it did, the system would never discover that the dependency has recovered.&lt;/p&gt;

&lt;p&gt;After a configured period, the Circuit Breaker can transition to HALF-OPEN.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;HALF-OPEN - Has the Service Recovered ?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is one of the most subtle parts of the pattern.&lt;/p&gt;

&lt;p&gt;Suppose the Payment Service was unavailable, but now appears to be healthy again. Should we immediately send all traffic back to it ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not necessarily&lt;/strong&gt;. The service may have recovered only partially. For example, it might have just restarted and currently be capable of handling only a small amount of traffic.&lt;/p&gt;

&lt;p&gt;Instead of immediately allowing thousands of requests through, the Circuit Breaker can allow a limited number of &lt;strong&gt;test requests&lt;/strong&gt;.&lt;br&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;HALF-OPEN
↓
5 test requests
↓
Are they successful ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the requests succeed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HALF-OPEN
↓
Successful requests
↓
CLOSED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The circuit returns to normal operation.&lt;/p&gt;

&lt;p&gt;If the test requests fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HALF-OPEN
↓
Failure
↓
OPEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The circuit opens again.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Does HALF-OPEN Allow Only a Few Requests ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Because &lt;strong&gt;service recovery doesn’t necessarily mean full recovery&lt;/strong&gt;. Imagine a Payment Service that was down and has just come back online. It might currently be capable of processing only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20 requests / second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your system suddenly sends:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;you could create another overload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Recovery
↓
Traffic spike
↓
Overload
↓
Failure again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words, your system can accidentally overwhelm the dependency immediately after it recovers.&lt;/p&gt;

&lt;p&gt;Half-Open provides a controlled way to test recovery:&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;0 requests
↓
10,000 requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 requests
↓
A few test requests
↓
Evaluate results
↓
Gradually increase traffic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact number of test requests is implementation- and system-dependent. There is no universal value that works for every architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Real-World Scenario: Payment Service Failure&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s put everything together. Imagine an online store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
↓
Order Service
↓
Payment Service
↓
Bank Gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under normal conditions:&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
↓
Circuit Breaker
↓
Payment Service
↓
Bank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is working normally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: The Failure Starts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Bank Gateway begins experiencing problems. The Payment Service starts timing out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment Request
↓
Timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Circuit Breaker records these failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: The Failure Threshold Is Reached&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose our policy is:&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
40 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and our configured rule is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failure Rate &amp;gt; 30% → OPEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The threshold has been exceeded. The Circuit Breaker opens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: New Requests Fail Fast&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now a new request arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
↓
Order Service
↓
Circuit = OPEN
↓
Immediate Failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Order Service no longer calls the Payment Service.&lt;/p&gt;

&lt;p&gt;This prevents the application from repeatedly waiting for a dependency that is already known to be unhealthy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: The System&lt;/strong&gt; &lt;a href="https://www.geeksforgeeks.org/system-design/graceful-degradation-in-distributed-systems/" rel="noopener noreferrer"&gt;&lt;strong&gt;Degrades Gracefully&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the circuit is open, the system still has to decide what the user should experience. For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Payment is temporarily unavailable. Please try again in a few minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or the application might have another valid strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Keep the order in a PENDING state&lt;/li&gt;
&lt;li&gt;  Put the operation into a queue&lt;/li&gt;
&lt;li&gt;  Switch to another payment provider&lt;/li&gt;
&lt;li&gt;  Return non-critical information from a cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;fallback&lt;/strong&gt; becomes important.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is a Fallback?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A fallback answers a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If the primary path fails, do we have a meaningful alternative ?&lt;/strong&gt;&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 plaintext"&gt;&lt;code&gt;Primary Payment Provider
↓
FAILED
↓
Secondary Payment Provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But a fallback is not always possible. For a payment operation, you cannot simply return &lt;em&gt;Payment successful,&lt;/em&gt; when the payment was never actually processed.&lt;/p&gt;

&lt;p&gt;The fallback must therefore be &lt;strong&gt;consistent with the business logic&lt;/strong&gt;. A fallback is not a fake success. It is an alternative behavior that is safe and meaningful for that particular operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Circuit Breaker ≠ Retry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;These two concepts are often confused. They solve different problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retry says:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The request failed. Maybe trying again will succeed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Circuit Breaker says:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This dependency has been failing repeatedly. Stop sending requests to it for now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Retry can be useful for &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/best-practices/transient-faults" rel="noopener noreferrer"&gt;&lt;strong&gt;transient failures&lt;/strong&gt;&lt;/a&gt;, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Temporary network glitch&lt;/li&gt;
&lt;li&gt;  Temporary timeout&lt;/li&gt;
&lt;li&gt;  Temporary throttling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if the dependency is genuinely down, excessive retries can make the situation worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Retries Can Cause a Cascading Failure&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose you have 1,000 requests and every failed request is retried three times. You might end up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 original requests + 3,000 retries = 4,000 requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s exactly what you don’t want when the dependency is already overloaded.&lt;/p&gt;

&lt;p&gt;Now imagine:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Service C fails. Service B retries its requests to C. Service A retries its requests to B.&lt;/p&gt;

&lt;p&gt;The result can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C fails
↓
B retries
↓
A retries
↓
More traffic
↓
C becomes even more overloaded
↓
More failures
↓
Cascading failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can lead to a &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/antipatterns/retry-storm/" rel="noopener noreferrer"&gt;&lt;strong&gt;retry storm&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So should we eliminate retries ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No&lt;/strong&gt;. The problem isn’t retrying itself. The problem is &lt;strong&gt;uncontrolled retries&lt;/strong&gt;. A more resilient design might combine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
↓
Timeout
↓
Retry
↓
Exponential Backoff + Jitter
↓
Circuit Breaker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important point is that retries should generally be limited to failures where another attempt has a reasonable chance of succeeding.&lt;/p&gt;

&lt;p&gt;For example, retrying a transient 503 Service Unavailable may make sense in some systems.&lt;/p&gt;

&lt;p&gt;Retrying a 401 Unauthorized generally does not solve the underlying problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Exponential Backoff and Jitter&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine 10,000 requests fail at approximately the same time. If every client retries exactly one second later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 second
↓
10,000 requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ve created another traffic spike.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://dilankam.medium.com/understanding-retries-exponential-backoffs-and-circuit-breakers-in-distributed-systems-4355db103505" rel="noopener noreferrer"&gt;&lt;strong&gt;exponential backoff&lt;/strong&gt;&lt;/a&gt;, the delay between retries increases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1s
2s
4s
8s
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps spread retries over a longer period.&lt;/p&gt;

&lt;p&gt;But there’s still a problem. If every client follows exactly the same schedule, they can still retry at roughly the same moments. That’s where &lt;a href="https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/" rel="noopener noreferrer"&gt;&lt;strong&gt;jitter&lt;/strong&gt;&lt;/a&gt; helps.&lt;br&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;1s
2s
4s
8s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;different clients might retry at slightly different times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.2s
1.8s
2.4s
3.1s
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is to spread retry traffic instead of allowing thousands of clients to synchronize their retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Idempotency: The Problem You Must Consider When Retrying&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Retries introduce another important problem: &lt;strong&gt;duplicate side effects&lt;/strong&gt;.&lt;br&gt;
Imagine:&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 /payments
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request reaches the Payment Service. The payment is successfully processed. But the response is lost because of a network failure. What does the client see?&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;From the client’s perspective, it doesn’t know whether the payment succeeded. So it retries:&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 /payments
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you potentially have:&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 → Payment successful
↓
Response lost
↓
Retry
↓
Request #2 → Payment successful again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may have charged the customer twice. This is where &lt;strong&gt;idempotency&lt;/strong&gt; becomes critical. For example, the client could send an idempotency key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Idempotency-Key: ABC123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Payment Service can use that key to recognize that the same logical operation has already been processed.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Retry
↓
Same Idempotency Key
↓
Same Logical Operation
↓
No Duplicate Side Effect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore, whenever you introduce retries, ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this operation actually safe to retry ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Important Circuit Breaker Configuration Parameters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Implementing a Circuit Breaker isn’t simply a matter of adding an if statement. Several parameters need to be defined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Failure Threshold&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How many failures should cause the circuit to open ?&lt;br&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;Failure Rate &amp;gt; 50%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A threshold that is too low may cause the circuit to open because of temporary failures.&lt;/p&gt;

&lt;p&gt;A threshold that is too high may allow the dependency to cause significant damage before the circuit reacts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Recovery Timeout&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the circuit is open, how long should we wait before testing the dependency 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 plaintext"&gt;&lt;code&gt;30 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A timeout that is too short can produce this cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPEN
↓
HALF-OPEN
↓
Failure
↓
OPEN
↓
HALF-OPEN
↓
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, a timeout that is too long may prevent requests from reaching a dependency even after it has recovered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Number of HALF-OPEN Requests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the circuit enters HALF-OPEN, how many requests should be allowed through ?&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;1 request
&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 plaintext"&gt;&lt;code&gt;5 requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or a limited percentage of traffic.&lt;/p&gt;

&lt;p&gt;Allowing more requests can provide more information about recovery, but it also creates more load on the recovering dependency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Which Failures Should Open the Circuit ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not every error should necessarily be treated as evidence that a dependency is unhealthy.&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;Timeout → likely relevant
503 → likely relevant
Connection error → likely relevant
401 → probably not
400 → probably not
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If every 4xx error contributes to the Circuit Breaker threshold, you could incorrectly conclude that the entire dependency is unavailable.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Circuit Breaker Has a Cost Too&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;No resilience pattern is free. Circuit Breaker provides important benefits, but it also introduces complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Potential benefits&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Helps prevent cascading failures&lt;/li&gt;
&lt;li&gt;  Reduces load on an unhealthy dependency&lt;/li&gt;
&lt;li&gt;  Enables fail-fast behavior&lt;/li&gt;
&lt;li&gt;  Protects application resources&lt;/li&gt;
&lt;li&gt;  Supports &lt;a href="https://www.geeksforgeeks.org/system-design/graceful-degradation-in-distributed-systems/" rel="noopener noreferrer"&gt;graceful degradation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Improves system resilience&lt;/li&gt;
&lt;li&gt;  Enables controlled recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Potential costs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  More application complexity&lt;/li&gt;
&lt;li&gt;  Additional monitoring requirements&lt;/li&gt;
&lt;li&gt;  Threshold tuning&lt;/li&gt;
&lt;li&gt;  State management&lt;/li&gt;
&lt;li&gt;  Fallback design&lt;/li&gt;
&lt;li&gt;  More difficult debugging&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.testdevlab.com/blog/false-positives-and-negatives-in-software-testing" rel="noopener noreferrer"&gt;False positives&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.testdevlab.com/blog/false-positives-and-negatives-in-software-testing" rel="noopener noreferrer"&gt;False negatives&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if your threshold is too sensitive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Temporary failure
↓
Circuit opens
↓
Requests rejected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;even though the dependency wasn’t actually down. If the threshold is too permissive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dependency is failing
↓
Circuit remains CLOSED
↓
More failures
↓
More resource consumption
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So configuring a Circuit Breaker is a &lt;strong&gt;trade-off&lt;/strong&gt;, not a search for one perfect number.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Where Should the Circuit Breaker Live ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A common placement is close to the remote call:&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
↓
Circuit Breaker
↓
Payment Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the decision close to the dependency being protected.&lt;/p&gt;

&lt;p&gt;However, Circuit Breaking can also be implemented at other layers, depending on the architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Application layer&lt;/li&gt;
&lt;li&gt;  API Gateway&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://aws.amazon.com/what-is/service-mesh/" rel="noopener noreferrer"&gt;Service Mesh&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/sidecar-design-pattern-for-microservices/" rel="noopener noreferrer"&gt;Sidecar&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Service Mesh for example, can provide resilience features without requiring every application to implement the same logic. But that introduces another trade-off. Moving more resilience behavior into infrastructure can simplify application code, while potentially making debugging and understanding system behavior more complicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Do You Always Need a Circuit Breaker ?&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;p&gt;Circuit Breaker is not automatically appropriate for every operation.&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 javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this is a local, fast operation with no meaningful remote dependency, adding a Circuit Breaker may simply introduce unnecessary complexity.&lt;/p&gt;

&lt;p&gt;Circuit Breakers become more interesting when dealing with things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Remote APIs&lt;/li&gt;
&lt;li&gt;  External providers&lt;/li&gt;
&lt;li&gt;  Database dependencies&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@AI-Simplified/distributed-systems-and-microservices-guide-to-streamlined-software-architectures-2782673e5808" rel="noopener noreferrer"&gt;Microservices&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Third-party services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key question isn’t:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do we use microservices ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens to our system when this dependency becomes slow, unavailable, or unreliable ?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Circuit Breaker Alone Is Not Resilience&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One common misconception is Circuit Breaker = Resilience. It isn’t.&lt;/p&gt;

&lt;p&gt;Circuit Breaker is only &lt;strong&gt;one tool&lt;/strong&gt; in a broader resilience strategy.&lt;/p&gt;

&lt;p&gt;A more complete design might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     ┌─────────────┐
     │   Timeout   │
     └──────┬──────┘
            ↓
     ┌─────────────┐
     │    Retry    │
     └──────┬──────┘
            ↓
┌───────────────────────┐
│ Exponential Backoff   │
│       + Jitter        │
└───────────┬───────────┘
            ↓
    ┌─────────────┐
    │   Circuit   │
    │   Breaker   │
    └──────┬──────┘
           ↓
    ┌─────────────┐
    │  Fallback   │
    └─────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the system, other patterns and mechanisms may also be relevant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead" rel="noopener noreferrer"&gt;Bulkheads&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/smiah/rate-limiting-in-distributed-system-3h59"&gt;Rate limiting&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/distributed-task-queue-distributed-systems/" rel="noopener noreferrer"&gt;Queues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://en.wikipedia.org/wiki/Distributed_cache" rel="noopener noreferrer"&gt;Caching&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://copyconstruct.medium.com/health-checks-in-distributed-systems-aa8a0e8c1672" rel="noopener noreferrer"&gt;Health checks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/observability-in-distributed-systems/" rel="noopener noreferrer"&gt;Observability&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dzone.com/articles/importance-of-idempotency-in-distributed-systems" rel="noopener noreferrer"&gt;Idempotency&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resilience usually comes from &lt;strong&gt;combining the right mechanisms&lt;/strong&gt;, not from adding one pattern everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Do You Know Your Circuit Breaker Is Working ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A Circuit Breaker without observability is difficult to operate. At a minimum, you should be able to monitor metrics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Circuit state&lt;/li&gt;
&lt;li&gt;  Failure rate&lt;/li&gt;
&lt;li&gt;  Success rate&lt;/li&gt;
&lt;li&gt;  Timeout rate&lt;/li&gt;
&lt;li&gt;  Number of circuit openings&lt;/li&gt;
&lt;li&gt;  Half-Open attempts&lt;/li&gt;
&lt;li&gt;  Recovery time&lt;/li&gt;
&lt;li&gt;  Fallback rate&lt;/li&gt;
&lt;li&gt;  Request latency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State transitions can also be important monitoring events.&lt;br&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;Circuit: CLOSED → OPEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may indicate a significant problem with an external dependency.&lt;/p&gt;

&lt;p&gt;Without monitoring, you may know that requests are failing — but not know &lt;strong&gt;why the Circuit Breaker opened, how often it opens, or whether it is actually helping.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Goal Isn’t to Eliminate Errors&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is one of the most important ideas behind the pattern. A Circuit Breaker does &lt;strong&gt;not necessarily reduce the number of errors users see&lt;/strong&gt;. In fact, after a circuit opens, you may see more immediate failures. But those failures can be much more controlled.&lt;/p&gt;

&lt;p&gt;Without a Circuit Breaker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 requests
↓
1,000 timeouts
↓
10 seconds each
↓
Thread exhaustion
↓
Entire service becomes unhealthy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a Circuit Breaker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 requests
↓
Circuit OPEN
↓
1,000 fast failures
↓
Dependency protected
↓
Main service remains responsive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In both cases, there are failures. But the second scenario prevents those failures from consuming resources indefinitely. That’s the key distinction.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The goal of a Circuit Breaker isn’t to make failure disappear. It’s to turn an uncontrolled failure into a controlled one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that is one of the fundamental ideas behind resilient &lt;a href="https://en.wikipedia.org/wiki/Distributed_computing" rel="noopener noreferrer"&gt;distributed systems&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The State Machine in One Picture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s summarize the state transitions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLOSED&lt;/strong&gt;: Requests are allowed through.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLOSED
↓
Requests flow normally
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If failures exceed the configured threshold:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OPEN:&lt;/strong&gt; Requests fail fast without calling the dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPEN
↓
Fail Fast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the configured recovery timeout:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;HALF-OPEN:&lt;/strong&gt; A limited number of test requests are allowed.&lt;/p&gt;

&lt;p&gt;If recovery succeeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HALF-OPEN → CLOSED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the dependency fails again:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;So the complete lifecycle is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7tvncrvcu4ecigtn9z9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7tvncrvcu4ecigtn9z9.png" alt=" " width="799" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Image by geeksforgeeks
&lt;/h6&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;The Bigger Lesson&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It’s useful to remember the three states, But understanding &lt;strong&gt;why&lt;/strong&gt; they exist is much more important.&lt;/p&gt;

&lt;p&gt;When a dependency is failing, continuing to send more requests isn’t necessarily resilience. Sometimes the most resilient thing your system can do is &lt;strong&gt;stop making the problem worse&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Circuit Breaker, together with carefully designed timeouts, limited retries, exponential backoff, jitter, fallback strategies, and idempotency, can help prevent a localized dependency failure from turning into a much larger outage.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When a dependency is unhealthy, protect your system first — and give the dependency a controlled chance to recover.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Circuit Breaker pattern is a resilience mechanism for systems that depend on remote services or external resources where failures, timeouts, and temporary unavailability are possible.&lt;/p&gt;

&lt;p&gt;Its three primary states are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLOSED
↓
Requests flow normally
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPEN
↓
Requests fail fast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HALF-OPEN
↓
A limited number of requests test recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important lesson isn’t memorizing these states. It’s understanding the philosophy behind them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A resilient system doesn’t just know how to handle failure. It knows when to stop making a failure worse.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Final Thought Experiment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine your Payment Service is completely down. Your system receives &lt;strong&gt;10,000 payment requests per minute&lt;/strong&gt;. Which behavior makes more sense ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1:&lt;/strong&gt; Retry every request three times.&lt;br&gt;
&lt;strong&gt;Option 2:&lt;/strong&gt; Open the Circuit Breaker after the failure rate crosses the configured threshold and fail fast.&lt;br&gt;
&lt;strong&gt;Option 3:&lt;/strong&gt; Use a combination of:&lt;/p&gt;

&lt;p&gt;The interesting part isn’t memorizing which pattern to use. The real engineering challenge is understanding &lt;strong&gt;how these mechanisms interact under failure&lt;/strong&gt;. That’s where resilient distributed-system design begins.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Further Reading&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://learn.microsoft.com/ar-sa/azure/architecture/patterns/circuit-breaker" rel="noopener noreferrer"&gt;Microsoft Azure — Circuit Breaker Pattern&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/best-practices/transient-faults" rel="noopener noreferrer"&gt;Microsoft Azure — Transient Fault Handling&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://learn.microsoft.com/uk-ua/azure/architecture/antipatterns/retry-storm" rel="noopener noreferrer"&gt;Microsoft Azure — Retry Storm Antipattern&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://aws.amazon.com/blogs/compute/using-the-circuit-breaker-pattern-with-aws-step-functions-and-amazon-dynamodb/" rel="noopener noreferrer"&gt;AWS — Using the Circuit Breaker Pattern with Step Functions and DynamoDB&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs" rel="noopener noreferrer"&gt;AWS Builders’ Library — Making retries safe with idempotent APIs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://martinfowler.com/bliki/CircuitBreaker.html" rel="noopener noreferrer"&gt;Martin Fowler — Circuit Breaker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern" rel="noopener noreferrer"&gt;Circuit Breaker Design Pattern&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/resilient-distributed-systems/" rel="noopener noreferrer"&gt;Resilient Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://blog.bytebytego.com/p/top-strategies-to-improve-reliability" rel="noopener noreferrer"&gt;Top Strategies to Improve Reliability in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@ninadwalanj/how-failure-cascades-in-distributed-systems-eccc48c9851a" rel="noopener noreferrer"&gt;How failure cascades in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/operating-systems/recovery-in-distributed-systems/" rel="noopener noreferrer"&gt;Recovery in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/monolithic-architecture-system-design/" rel="noopener noreferrer"&gt;Monolithic Architecture&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine" rel="noopener noreferrer"&gt;Finite-State Machine&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://en.wikipedia.org/wiki/Service-level_objective" rel="noopener noreferrer"&gt;Service-Level Objective&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/retries-strategies-in-distributed-systems/" rel="noopener noreferrer"&gt;Retries Strategies in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/computer-networks/failure-detection-and-recovery-in-distributed-systems/" rel="noopener noreferrer"&gt;Failure Detection and Recovery in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/graceful-degradation-in-distributed-systems/" rel="noopener noreferrer"&gt;Graceful Degradation in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.oracle.com/en/database/other-databases/timesten/22.1/scaleout/recovering-transient-errors.html#GUID-B8CC179C-C56A-4994-9607-D1DB2EB5F32F" rel="noopener noreferrer"&gt;Recovering from Transient Errors&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/antipatterns/retry-storm/" rel="noopener noreferrer"&gt;Retry Storm Antipattern&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dilankam.medium.com/understanding-retries-exponential-backoffs-and-circuit-breakers-in-distributed-systems-4355db103505" rel="noopener noreferrer"&gt;Understanding Retries, Exponential Backoffs, and Circuit Breakers in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/" rel="noopener noreferrer"&gt;Exponential Backoff And Jitter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.testdevlab.com/blog/false-positives-and-negatives-in-software-testing" rel="noopener noreferrer"&gt;What Are False Positives and Negatives in Software Testing ?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://aws.amazon.com/what-is/service-mesh/" rel="noopener noreferrer"&gt;What is a Service Mesh ?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/sidecar-design-pattern-for-microservices/" rel="noopener noreferrer"&gt;Sidecar Design Pattern for Microservices&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@AI-Simplified/distributed-systems-and-microservices-guide-to-streamlined-software-architectures-2782673e5808" rel="noopener noreferrer"&gt;Distributed Systems and Microservices: Guide to Streamline Software Architectures&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead" rel="noopener noreferrer"&gt;Bulkhead Pattern&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/smiah/rate-limiting-in-distributed-system-3h59"&gt;Rate Limiting in Distributed System&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/distributed-task-queue-distributed-systems/" rel="noopener noreferrer"&gt;Distributed Task Queue — Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://copyconstruct.medium.com/health-checks-in-distributed-systems-aa8a0e8c1672" rel="noopener noreferrer"&gt;Health Checks and Graceful Degradation in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.geeksforgeeks.org/system-design/observability-in-distributed-systems/" rel="noopener noreferrer"&gt;Observability in Distributed Systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dzone.com/articles/importance-of-idempotency-in-distributed-systems" rel="noopener noreferrer"&gt;Idempotency in Distributed Systems: When and Why It Matters&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://en.wikipedia.org/wiki/Distributed_computing" rel="noopener noreferrer"&gt;Distributed Computing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microservices</category>
      <category>distributedsystems</category>
      <category>softwareengineering</category>
      <category>circuitbreakerpattern</category>
    </item>
    <item>
      <title>MySQL Overselling: Why SELECT Isn't Enough and How SELECT ... FOR UPDATE Solves It</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Sun, 13 Sep 2026 14:51:03 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/mysql-overselling-why-select-isnt-enough-and-how-select-for-update-solves-it-m0p</link>
      <guid>https://dev.to/mehradsadeghi/mysql-overselling-why-select-isnt-enough-and-how-select-for-update-solves-it-m0p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsy3p4647t25e2behs667.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsy3p4647t25e2behs667.jpg" alt=" " width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine you’re running an online store, there’s exactly &lt;strong&gt;one item left&lt;/strong&gt; in stock. Two customers click &lt;strong&gt;Buy&lt;/strong&gt; at almost exactly the same time. Both requests reach your application. Both transactions ask the database:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And both get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now both customers believe the product is available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what happens next ? Welcome to the overselling problem.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Naive Implementation
&lt;/h3&gt;

&lt;p&gt;A simple purchase flow might look like this:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Application checks:&lt;/span&gt;
&lt;span class="c1"&gt;-- Is stock &amp;gt; 0 ?&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this seems perfectly reasonable. But there’s a race condition.&lt;/p&gt;

&lt;p&gt;Imagine two transactions:&lt;br&gt;
&lt;/p&gt;

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

SELECT stock               SELECT stock
     |                           |
     v                           v
   stock=1                    stock=1
     |                           |
     v                           v
"Available!"                 "Available!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both transactions read the same value before either one has completed the purchase. The problem isn’t necessarily that MySQL is broken. The problem is that our &lt;strong&gt;read and decision are not protected as one atomic operation&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Doesn’t REPEATABLE READ Solve This ?
&lt;/h3&gt;

&lt;p&gt;This is an important question. InnoDB’s default isolation level is REPEATABLE READ. So you might think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If I’m using REPEATABLE READ, shouldn’t MySQL prevent this ?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Not necessarily&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A normal:&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="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a consistent, nonlocking read.&lt;/p&gt;

&lt;p&gt;Under &lt;code&gt;REPEATABLE READ&lt;/code&gt;, it can read from the transaction's consistent snapshot.&lt;/p&gt;

&lt;p&gt;Isolation determines what your transaction sees. It doesn’t automatically mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Nobody else can modify the row after I read it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s a completely different requirement.&lt;/p&gt;

&lt;p&gt;If your business operation is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Read this row, verify a condition, and then modify it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;you often need a &lt;strong&gt;locking read&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter SELECT … FOR UPDATE
&lt;/h3&gt;

&lt;p&gt;MySQL provides:&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="p"&gt;...&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not just a normal read. It is a &lt;strong&gt;locking read&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;MySQL/InnoDB locks the records returned by the query, and another transaction attempting to acquire a conflicting lock on the same records has to wait until the first transaction commits or rolls back.&lt;/p&gt;

&lt;p&gt;Now our two transactions look very different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction A Gets There First
&lt;/h3&gt;

&lt;p&gt;Suppose Transaction A executes:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database finds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and locks the relevant record.&lt;/p&gt;

&lt;p&gt;Transaction B now tries:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But Transaction A is already holding the conflicting lock.&lt;/p&gt;

&lt;p&gt;So Transaction B waits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transaction A                 Transaction B
FOR UPDATE
     |
     v
 stock = 1
     |
  LOCK ROW
     |
     |                       FOR UPDATE
     |                            |
     |                            v
     |                         WAIT...
     |
 UPDATE stock = 0
     |
 INSERT ORDER
     |
   COMMIT
     |
  UNLOCK
                                |
                                v
                          FOR UPDATE succeeds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Transaction B gets its turn.&lt;/p&gt;

&lt;p&gt;The important part is that &lt;strong&gt;Transaction B doesn’t get to make its decision before Transaction A finishes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Correct Purchase Flow
&lt;/h3&gt;

&lt;p&gt;A safer implementation looks like this:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the application checks the returned value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="n"&gt;purchase&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;reject&lt;/span&gt; &lt;span class="n"&gt;purchase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If stock is available:&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;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the product is already sold out:&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;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important property is that the &lt;strong&gt;check and subsequent modification happen while the relevant row is locked&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Key Idea: Lock Before You Decide
&lt;/h3&gt;

&lt;p&gt;This is the mental model worth remembering:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unsafe&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;READ
  ↓
CHECK
  ↓
UPDATE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that another transaction can interfere between the read and the update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safer&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;LOCK + READ
     ↓
   CHECK
     ↓
   UPDATE
     ↓
   COMMIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lock protects the critical section.&lt;/p&gt;

&lt;h3&gt;
  
  
  But There’s Another Option
&lt;/h3&gt;

&lt;p&gt;For a simple inventory decrement, you don’t always need to read the row first. You can make the condition part of the update itself:&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;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check how many rows were affected.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;affected_rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the purchase can proceed.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;affected_rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;there wasn’t enough stock.&lt;/p&gt;

&lt;p&gt;This approach can be extremely useful because the business condition is enforced directly by the database operation.&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 sql"&gt;&lt;code&gt;&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- If one row was updated:&lt;/span&gt;
&lt;span class="c1"&gt;-- create the order&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a real implementation, the application should only insert the order when the update actually succeeded.&lt;/p&gt;

&lt;h3&gt;
  
  
  So When Should You Use SELECT … FOR UPDATE ?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; is particularly useful when your business logic needs to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the current state of a row.&lt;/li&gt;
&lt;li&gt;Make a decision based on that state.&lt;/li&gt;
&lt;li&gt;Modify that same data.&lt;/li&gt;
&lt;li&gt;Keep another transaction from changing it between those steps.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ul&gt;
&lt;li&gt;inventory reservation&lt;/li&gt;
&lt;li&gt;seat reservation&lt;/li&gt;
&lt;li&gt;wallet balance updates&lt;/li&gt;
&lt;li&gt;account transfers&lt;/li&gt;
&lt;li&gt;job claiming&lt;/li&gt;
&lt;li&gt;resource allocation&lt;/li&gt;
&lt;li&gt;order processing&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 sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;accounts&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;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Check balance
     ↓
Calculate new balance
     ↓
UPDATE account
     ↓
COMMIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lock protects the critical decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Common Misunderstanding
&lt;/h3&gt;

&lt;p&gt;One common misconception is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“FOR UPDATE locks the entire table."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s not generally how InnoDB works.&lt;/p&gt;

&lt;p&gt;InnoDB uses row-level locking, although the exact locks acquired depend on the query, indexes, search conditions, and isolation level. For some range queries, InnoDB can also use gap locks or next-key locks.&lt;/p&gt;

&lt;p&gt;For example, a unique-index lookup such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can lock the matching index record.&lt;/p&gt;

&lt;p&gt;Range-based locking is more complicated.&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 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;price&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;may involve range-related locking behavior depending on the indexes and isolation level.&lt;/p&gt;

&lt;p&gt;This is one reason understanding indexes is important when reasoning about MySQL concurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t Forget the Transaction
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;FOR UPDATE&lt;/code&gt; makes sense inside a transaction.&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 sql"&gt;&lt;code&gt;&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lock is part of the transaction’s concurrency control. You don’t want to acquire a lock, perform a tiny operation, release it, and then perform the critical business operation later. The entire critical section should be designed intentionally.&lt;/p&gt;

&lt;h3&gt;
  
  
  What About Deadlocks ?
&lt;/h3&gt;

&lt;p&gt;Locks solve one class of concurrency problems, but they introduce another possibility: &lt;strong&gt;deadlocks&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transaction A                 Transaction B
locks Row 1                   locks Row 2
     |                              |
     v                              v
tries Row 2                    tries Row 1
     |                              |
     +---------- WAIT &amp;lt;-------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now both transactions are waiting for each other.&lt;/p&gt;

&lt;p&gt;InnoDB detects deadlocks and rolls back one of the transactions so that the other can continue.&lt;/p&gt;

&lt;p&gt;This means production applications using transactions and locks should generally be prepared to &lt;strong&gt;retry transactions when appropriate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Locking isn’t something you simply add without considering transaction boundaries, lock ordering, indexes, and failure handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Real Lesson
&lt;/h3&gt;

&lt;p&gt;The important lesson isn’t simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Use SELECT ... FOR UPDATE."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The deeper lesson is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Concurrency bugs happen when a business decision depends on data that can change between the read and the write.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You need to identify that critical section and choose an appropriate concurrency-control strategy.&lt;/p&gt;

&lt;p&gt;Sometimes that’s:&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="p"&gt;...&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes it’s an atomic conditional update:&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;UPDATE&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes it’s an optimistic concurrency strategy. And sometimes a database constraint is the best solution. The correct choice depends on the business operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Takeaway
&lt;/h3&gt;

&lt;p&gt;When building a system that handles concurrent requests, don’t ask only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Which isolation level should I use ?”&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;“What happens if two transactions execute these exact statements at the same time ?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s the question that exposes race conditions.&lt;/p&gt;

&lt;p&gt;For an inventory operation, this:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are not equivalent.&lt;/p&gt;

&lt;p&gt;The first reads. The second &lt;strong&gt;reads with an intention to modify and acquires a lock&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once you understand that distinction, MySQL transaction isolation becomes much easier to reason about.&lt;/p&gt;

&lt;p&gt;And more importantly, you can start designing systems that remain correct even when thousands of users click &lt;strong&gt;Buy&lt;/strong&gt; at exactly the same time.&lt;/p&gt;

</description>
      <category>database</category>
      <category>mysql</category>
      <category>backend</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Two Transactions, One Row: What Does MySQL Actually Let You See ?</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Sun, 13 Sep 2026 14:47:01 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/two-transactions-one-row-what-does-mysql-actually-let-you-see--52ga</link>
      <guid>https://dev.to/mehradsadeghi/two-transactions-one-row-what-does-mysql-actually-let-you-see--52ga</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqza8g26cw9195elmkiu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqza8g26cw9195elmkiu.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two users, One database row, Both reading and writing at almost exactly the same time. Who sees what ?&lt;/p&gt;

&lt;p&gt;Can one transaction see another transaction’s uncommitted changes ?&lt;br&gt;
Can the same query return different results inside a single transaction ?&lt;br&gt;
And why does &lt;code&gt;SELECT&lt;/code&gt; sometimes give you a snapshot, while &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt;&lt;br&gt;
 gives you something completely different ?&lt;/p&gt;

&lt;p&gt;If you’ve ever wondered what MySQL actually does when transactions run concurrently, this is where it gets interesting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html" rel="noopener noreferrer"&gt;InnoDB&lt;/a&gt; gives you four &lt;a href="https://en.wikipedia.org/wiki/Isolation_(database_systems)" rel="noopener noreferrer"&gt;transaction isolation levels&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;READ UNCOMMITTED&lt;/li&gt;
&lt;li&gt;READ COMMITTED&lt;/li&gt;
&lt;li&gt;REPEATABLE READ&lt;/li&gt;
&lt;li&gt;SERIALIZABLE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most developers know their names, fewer can predict what will actually happen when two transactions execute at the same time.&lt;/p&gt;

&lt;p&gt;That’s what we’re going to do here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No abstract definitions first. No memorizing a table.&lt;/strong&gt; We’ll make the transactions collide and see what MySQL does.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Do We Need Transactions ?
&lt;/h2&gt;

&lt;p&gt;Consider a typical e-commerce purchase. When a customer buys a product, several database operations may need to happen together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the product inventory.&lt;/li&gt;
&lt;li&gt;Decrease the inventory.&lt;/li&gt;
&lt;li&gt;Create the order.&lt;/li&gt;
&lt;li&gt;Record the payment.&lt;/li&gt;
&lt;li&gt;Update the order status.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What happens if the inventory is successfully decreased but creating the order fails ?&lt;/p&gt;

&lt;p&gt;You could end up with a database where the product’s inventory has decreased, but no corresponding order exists.&lt;/p&gt;

&lt;p&gt;That’s exactly the kind of problem transactions are designed to prevent.&lt;/p&gt;

&lt;p&gt;A transaction lets us treat multiple database operations as a single logical unit:&lt;/p&gt;

&lt;p&gt;Either all of the operations succeed, or the changes are rolled back.&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 sql"&gt;&lt;code&gt;&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something goes wrong:&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;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transactions are one of the foundations of &lt;a href="https://en.wikipedia.org/wiki/ACID" rel="noopener noreferrer"&gt;ACID&lt;/a&gt;, and the I in ACID stands for Isolation. Isolation is where things get interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Transaction Isolation Level ?
&lt;/h2&gt;

&lt;p&gt;Imagine two transactions running at approximately 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;Transaction A                Transaction B
      |                            |
      |---- read data ------------&amp;gt;|
      |                            |
      |                       update data
      |                            |
      |&amp;lt;--- what can A see ? ------|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both transactions may be reading and modifying the same data. The isolation level defines the rules for what each transaction is allowed to see while other transactions are running.&lt;/p&gt;

&lt;p&gt;Those rules can dramatically change the behavior of your application.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Can you see another transaction’s uncommitted changes ?&lt;/li&gt;
&lt;li&gt;Can the same query return a different value later ?&lt;/li&gt;
&lt;li&gt;Do you keep seeing the same snapshot ?&lt;/li&gt;
&lt;li&gt;Does your read lock the row ?&lt;/li&gt;
&lt;li&gt;Can another transactions modify the row while you’re making a decision ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s find out.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. READ UNCOMMITTED - When Uncommitted Data Becomes Visible
&lt;/h3&gt;

&lt;p&gt;READ UNCOMMITTED is the least restrictive isolation level. A transaction can potentially see changes made by another transaction before those changes have been committed. This is known as a dirty read.&lt;/p&gt;

&lt;p&gt;Suppose the database contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transaction A starts:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But Transaction A hasn’t committed yet.&lt;/p&gt;

&lt;p&gt;Now Transaction B executes:&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;SET&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt; &lt;span class="k"&gt;ISOLATION&lt;/span&gt; &lt;span class="k"&gt;LEVEL&lt;/span&gt; &lt;span class="k"&gt;READ&lt;/span&gt; &lt;span class="k"&gt;UNCOMMITTED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transaction B may see:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Wait. That 0 hasn't actually been committed.&lt;/p&gt;

&lt;p&gt;Now Transaction A rolls everything back:&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;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual value goes back to:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Transaction B just observed a value that never became part of the committed database state. That’s a dirty read.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why is this dangerous ?
&lt;/h4&gt;

&lt;p&gt;Imagine applying the same idea to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;payments&lt;/li&gt;
&lt;li&gt;bank balances&lt;/li&gt;
&lt;li&gt;inventory&lt;/li&gt;
&lt;li&gt;orders&lt;/li&gt;
&lt;li&gt;seat reservations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could make a business decision based on data that ultimately disappears. A simple way to remember it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;READ UNCOMMITTED: you get more concurrency by giving up consistency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. READ COMMITTED - Only See What Has Been Committed
&lt;/h3&gt;

&lt;p&gt;READ COMMITTED takes a more conservative approach. A transaction doesn’t see another transaction’s uncommitted changes through a normal consistent read. But there’s a catch.&lt;/p&gt;

&lt;p&gt;The data you see can change while your transaction is still running.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Initial stock = 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transaction A starts:&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;SET&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt; &lt;span class="k"&gt;ISOLATION&lt;/span&gt; &lt;span class="k"&gt;LEVEL&lt;/span&gt; &lt;span class="k"&gt;READ&lt;/span&gt; &lt;span class="k"&gt;COMMITTED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sees:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now Transaction B changes the value:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transaction A executes the same query again:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The same transaction saw 10 and later 5. That’s a Non-Repeatable Read.&lt;/p&gt;

&lt;p&gt;But why this happens ? Because under READ COMMITTED, each consistent read can establish its own fresh snapshot.&lt;/p&gt;

&lt;h4&gt;
  
  
  When is READ COMMITTED useful ?
&lt;/h4&gt;

&lt;p&gt;It’s a good fit for systems where seeing relatively fresh committed data is more important than maintaining one consistent snapshot throughout the entire transaction.&lt;/p&gt;

&lt;p&gt;It also changes InnoDB’s locking behavior. For locking READ, UPDATE, and DELETE, InnoDB generally uses record locks rather than gap locks, except where gap locking is needed for foreign-key and duplicate-key checks.&lt;/p&gt;

&lt;p&gt;A simple way to remember it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;READ COMMITTED: every consistent read sees committed data as of that read, so a later read can see changes committed by other transactions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. REPEATABLE READ - Your Transaction Gets a Snapshot
&lt;/h3&gt;

&lt;p&gt;Now we reach InnoDB’s default isolation level: REPEATABLE READ.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transaction A starts:&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;SET&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt; &lt;span class="k"&gt;ISOLATION&lt;/span&gt; &lt;span class="k"&gt;LEVEL&lt;/span&gt; &lt;span class="k"&gt;REPEATABLE&lt;/span&gt; &lt;span class="k"&gt;READ&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sees:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now Transaction B changes the value:&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;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transaction A runs the same query again:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for a normal, non-locking consistent read, it can still see &lt;strong&gt;10&lt;/strong&gt;, not &lt;strong&gt;5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why is that ? Because consistent reads in a REPEATABLE READ transaction use the transaction's snapshot.&lt;/p&gt;

&lt;p&gt;So from Transaction A’s perspective, the database can effectively look like:&lt;/p&gt;

&lt;p&gt;Transaction A’s view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;even though the current committed value is now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. SERIALIZABLE - Make Concurrency Behave More Like Sequential Execution
&lt;/h3&gt;

&lt;p&gt;SERIALIZABLE is the strictest of the four isolation levels. Its goal is to provide behavior that is closer to transactions executing one after another rather than freely interleaving.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transaction A
     |
     | read/write
     |
     v
Transaction B
     |
     | waits
     v
Transaction A commits
     |
     v
Transaction B continues
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In InnoDB, when auto-commit is disabled, plain &lt;code&gt;SELECT&lt;/code&gt; statements under SERIALIZABLE are implicitly converted to locking reads using &lt;code&gt;FOR SHARE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This provides stronger consistency guarantees, but the additional locking can reduce concurrency.&lt;/p&gt;

&lt;p&gt;So while &lt;code&gt;SERIALIZABLE&lt;/code&gt; sounds like the safest choice, it isn't automatically the best choice. Stronger isolation comes with a cost.&lt;/p&gt;

&lt;p&gt;A simple way to remember it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SERIALIZABLE: strongest isolation, but concurrency becomes more expensive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Comparing the Four Levels&lt;/p&gt;

&lt;p&gt;Here’s the quick mental model:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbms7lawihbpxfvuasmx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbms7lawihbpxfvuasmx1.png" alt=" " width="799" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But don’t treat this table as the whole story.&lt;/p&gt;

&lt;p&gt;InnoDB’s behavior also involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-multi-versioning.html" rel="noopener noreferrer"&gt;MVCC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/9.7/en/innodb-consistent-read.html" rel="noopener noreferrer"&gt;consistent reads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-locking-reads.html" rel="noopener noreferrer"&gt;locking reads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html" rel="noopener noreferrer"&gt;record locks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html" rel="noopener noreferrer"&gt;gap locks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html" rel="noopener noreferrer"&gt;next-key locks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/9.7/en/innodb-transaction-model.html" rel="noopener noreferrer"&gt;transaction boundaries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-physical-structure.html" rel="noopener noreferrer"&gt;indexes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part isn’t memorizing the table. &lt;strong&gt;It’s being able to predict what happens when two transactions collide&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bigger Lesson
&lt;/h3&gt;

&lt;p&gt;Here’s the part that matters most in real applications:&lt;/p&gt;

&lt;p&gt;Choosing an isolation level doesn’t automatically make your concurrent code correct.&lt;/p&gt;

&lt;p&gt;Isolation level determines the visibility and concurrency rules of transactions, But your SQL statements determine how you interact with the data.&lt;/p&gt;

&lt;p&gt;Compare:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&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="n"&gt;stock&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;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They may look almost identical, but they are not.&lt;/p&gt;

&lt;p&gt;The first is a consistent read.&lt;/p&gt;

&lt;p&gt;The second is a locking read.&lt;/p&gt;

&lt;p&gt;And when two requests hit your application at almost exactly the same time, that difference can determine whether your system behaves correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Question You Should Ask
&lt;/h3&gt;

&lt;p&gt;When debugging or designing concurrent database code, don’t ask only:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Which isolation level am I using ?”&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;“What happens if two transactions execute these exact statements at the same time ?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s the question that exposes race conditions.&lt;/p&gt;

&lt;p&gt;Once you start thinking in terms of concurrent transactions instead of isolated SQL statements, MySQL’s transaction model becomes much easier to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Takeaway
&lt;/h3&gt;

&lt;p&gt;Transaction isolation isn’t just a list of four configuration values. It’s a set of rules governing what your transactions can see, when they can see it, and how they interact with other transactions.&lt;/p&gt;

&lt;p&gt;If you remember only one thing from this article, remember this:&lt;/p&gt;

&lt;p&gt;The real test of your database design isn’t what happens when one transaction runs. It’s what happens when two transactions run at the same time.&lt;/p&gt;

&lt;p&gt;And when those two transactions are fighting over the last item in stock, the difference between a normal &lt;code&gt;SELECT&lt;/code&gt; and &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; suddenly becomes very important.&lt;/p&gt;

&lt;p&gt;That’s where we’re going next.&lt;/p&gt;

&lt;p&gt;Next: &lt;a href="https://dev.to/mehradsadeghi/mysql-overselling-why-select-isnt-enough-and-how-select-for-update-solves-it-m0p"&gt;MySQL Overselling - Why &lt;code&gt;SELECT&lt;/code&gt; Isn't Enough and How &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; Solves It&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>mysql</category>
      <category>softwareengineering</category>
      <category>backend</category>
    </item>
    <item>
      <title>Clean Code Made Simple - Part 3</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Mon, 15 Aug 2022 17:28:54 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/clean-code-made-simple-part-3-22hd</link>
      <guid>https://dev.to/mehradsadeghi/clean-code-made-simple-part-3-22hd</guid>
      <description>&lt;p&gt;Further to my last posts &lt;a href="https://dev.to/mehradsadeghi/clean-code-made-simple-part-1-2f32"&gt;Part 1&lt;/a&gt; and &lt;a href="https://dev.to/mehradsadeghi/clean-code-made-simple-part-2-l53"&gt;Part 2&lt;/a&gt; of Clean Code Made Simple, &lt;br&gt;
in this post I'm going to continue introducing techniques from &lt;a href="https://en.wikipedia.org/wiki/Robert_C._Martin" rel="noopener noreferrer"&gt;Robert C. Martin&lt;/a&gt;’s &lt;a href="https://www.google.com/aclk?sa=L&amp;amp;ai=DChcSEwii56mA5bL5AhWXt3cKHW49DWYYABABGgJlZg&amp;amp;sig=AOD64_0RHTphNDrbz7XN-NjV31HGTV4IFA&amp;amp;ctype=5&amp;amp;q=&amp;amp;ved=0ahUKEwjo8qOA5bL5AhUkuqQKHaN7DF8Qww8Iuwk&amp;amp;adurl=" rel="noopener noreferrer"&gt;Clean Code book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#11 Law of Demeter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As wikipedia says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Law of Demeter (LoD) or principle of least knowledge is a design guideline for developing software, particularly object-oriented programs. can be succinctly summarized in each of the following ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.&lt;/li&gt;
&lt;li&gt;Each unit should only talk to its friends; don't talk to strangers.&lt;/li&gt;
&lt;li&gt;Only talk to your immediate friends.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that we have a basic understanding of Demeter's law, in order to prevent breaking it, which one of the following structures do you think is better?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getAbsolutePathOfScratchDirectoryOption&lt;/span&gt;&lt;span class="p"&gt;();&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 php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getScratchDirectoryOption&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAbsolutePath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;well non is good. If ctx is an object, we should be telling it to do something; we should not be asking it about its internals.&lt;/p&gt;

&lt;p&gt;Consider far from code about (in that module) we needed the &lt;code&gt;outputDir&lt;/code&gt; like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$outFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$outputDir&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$className&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".class"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$fout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileOutputStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$outFile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$bos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BufferedOutputStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what if we told the ctx object to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$bos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createScratchFileStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$classFileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That seems like a reasonable thing for an object to do! This allows ctx to hide its internals and prevents the current function from having to violate the Law of Demeter by navigating through objects it shouldn’t know about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#12 Standard Pattern Names&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By using the standard pattern names, such as &lt;code&gt;COMMAND&lt;/code&gt; or &lt;code&gt;VISITOR&lt;/code&gt;, in the names of the classes that implement those patterns, you can succinctly describe your design to other developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#13 Doing One Thing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How do you think we can figure out a function is doing more than “one thing”?&lt;/p&gt;

&lt;p&gt;The answer is that if you can extract another function from it with a name that is not merely a restatement of its implementation, Then you would know it's doing more than one thing.&lt;/p&gt;

&lt;p&gt;To do so, we need to make sure that the statements within our function are all at the same level of abstraction. for example&lt;br&gt;
&lt;code&gt;getHtml()&lt;/code&gt; is at a very high level of abstraction,&lt;br&gt;
&lt;code&gt;$pagePathName = PathParser::render($pagePath);&lt;/code&gt; is at intermediate abstraction,&lt;br&gt;
and something like &lt;code&gt;-&amp;gt;append("\n")&lt;/code&gt; is at low level of abstraction&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#14 Base Class and Derivatives&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most common reason for partitioning concepts into base and derivative classes is so that the higher level base class concepts can be independent of the lower level derivative class concepts. Therefore, when we see base classes mentioning the names of their derivatives, we suspect a problem. In general, base classes should know nothing about their derivatives.&lt;/p&gt;

&lt;p&gt;There are exceptions to this rule, of course. Sometimes the number of derivatives is strictly fixed, and the base class has code that selects between the derivatives. We see this a lot in finite state machine implementations. However, in that case the derivatives and base class are strongly coupled and always deploy together. In the general case we want to be able to deploy derivatives and bases separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#15 Naming&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Methods should have verb or verb phrase names like postPayment, deletePage, or save.&lt;br&gt;
Accessors, mutators, and predicates should be named for their value and prefixed with get,&lt;br&gt;
set, and is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$customer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mike"&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="nv"&gt;$paycheck&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isPosted&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay. This is it for this part. You can join my &lt;a href="https://t.me/themehradsadeghi" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt; channel to get notified of the latest posts. Also, you can follow me on &lt;a href="https://twitter.com/realmehrad" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://linkedin.com/in/mehradsadeghi" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>php</category>
      <category>design</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Clean Code Made Simple - Part 2</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Thu, 11 Aug 2022 16:49:00 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/clean-code-made-simple-part-2-l53</link>
      <guid>https://dev.to/mehradsadeghi/clean-code-made-simple-part-2-l53</guid>
      <description>&lt;p&gt;Further to my last post &lt;a href="https://dev.to/mehradsadeghi/clean-code-made-simple-part-1-2f32"&gt;Clean Code Made Simple - Part 1&lt;/a&gt;, in this post I'm going to continue introducing techniques from &lt;a href="https://en.wikipedia.org/wiki/Robert_C._Martin" rel="noopener noreferrer"&gt;Robert C. Martin&lt;/a&gt;’s &lt;a href="https://www.google.com/aclk?sa=L&amp;amp;ai=DChcSEwii56mA5bL5AhWXt3cKHW49DWYYABABGgJlZg&amp;amp;sig=AOD64_0RHTphNDrbz7XN-NjV31HGTV4IFA&amp;amp;ctype=5&amp;amp;q=&amp;amp;ved=0ahUKEwjo8qOA5bL5AhUkuqQKHaN7DF8Qww8Iuwk&amp;amp;adurl=" rel="noopener noreferrer"&gt;Clean Code book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#6 Hiding Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Which one of below code snippets do you think is better designed?&lt;/p&gt;

&lt;p&gt;1)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&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;function&lt;/span&gt; &lt;span class="n"&gt;getFuelTankCapacityInGallons&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;function&lt;/span&gt; &lt;span class="n"&gt;getGallonsOfGasoline&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;2)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&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;function&lt;/span&gt; &lt;span class="n"&gt;getPercentFuelRemaining&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;In both of the above cases the second option is preferable. We do not want to expose the details of our data as much as possible. Rather we want to express our data in abstract terms. Serious thought needs to be put into the best way to represent the data that an object contains. The worst option is to blithely add getters and setters.&lt;/p&gt;

&lt;p&gt;So in any situation where it's suitable to hide the data of an object, You may do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#7 Simple Design Rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kent Beck introduced these 4 rules as basic criteria to design programs better:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs all the tests&lt;/li&gt;
&lt;li&gt;Contains no duplication&lt;/li&gt;
&lt;li&gt;Expresses the intent of the programmer&lt;/li&gt;
&lt;li&gt;Minimizes the number of classes and methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an effort to make our classes and methods small, we might create too many tiny classes and methods. we should also keep our function and class counts low. this is the forth rule of simple design rules by kent which is more important than other ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#8 Intention Revealing Functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;how do you think this code snippet can get better ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getFlaggedCells&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nv"&gt;$flaggedCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cells&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$cell&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="nv"&gt;$cell&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;STATUS_VALUE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$flaggedCells&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cell&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;return&lt;/span&gt; &lt;span class="nv"&gt;$flaggedCells&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;We can write an intention-revealing function (call it isFlagged) to hide the magic numbers. It results in a new version of the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getFlaggedCells&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nv"&gt;$flaggedCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cells&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$cell&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="nv"&gt;$cell&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isFlagged&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nv"&gt;$flaggedCells&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cell&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$flaggedCells&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;&lt;strong&gt;#9 Writing Tests Leads to Better Designs&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Systems that aren’t testable aren’t verifiable. Arguably, a system that cannot be verified should never be deployed. Fortunately, making our systems testable pushes us toward a design where our classes are small and single purpose. Writing tests leads to better designs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;#10 Separation of Concerns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What would you recommend the direction of arrows should be, to separate construction from use ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main             Application



Builder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Directions should be as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            run
  Main  ---------&amp;gt;  Application
   |
   | build and construct
  \|/
Builder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It simply means that the construction of our application should be separate from using it. These two steps are fundamentally separate and decoupling them gives us a better design and structure.&lt;/p&gt;

&lt;p&gt;Okay. This is it for this part. You can join my &lt;a href="https://t.me/themehradsadeghi" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt; channel to get notified of the latest posts. Also, you can follow me on &lt;a href="https://twitter.com/realmehrad" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://linkedin.com/in/mehradsadeghi" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>php</category>
      <category>cleancode</category>
      <category>softwaredesign</category>
    </item>
    <item>
      <title>Clean Code Made Simple - Part 1</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Sun, 07 Aug 2022 08:13:00 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/clean-code-made-simple-part-1-2f32</link>
      <guid>https://dev.to/mehradsadeghi/clean-code-made-simple-part-1-2f32</guid>
      <description>&lt;p&gt;I’ve read &lt;a href="https://en.wikipedia.org/wiki/Robert_C._Martin" rel="noopener noreferrer"&gt;Robert C. Martin&lt;/a&gt;’s &lt;a href="https://www.google.com/aclk?sa=L&amp;amp;ai=DChcSEwii56mA5bL5AhWXt3cKHW49DWYYABABGgJlZg&amp;amp;sig=AOD64_0RHTphNDrbz7XN-NjV31HGTV4IFA&amp;amp;ctype=5&amp;amp;q=&amp;amp;ved=0ahUKEwjo8qOA5bL5AhUkuqQKHaN7DF8Qww8Iuwk&amp;amp;adurl=" rel="noopener noreferrer"&gt;Clean Code book&lt;/a&gt; a couple of years ago. It’s a great book, Especially for those who are in the junior years of their career. It helps you become a more mature software developer/engineer and write quality code more often.&lt;/p&gt;

&lt;p&gt;I aggregated the tips, tricks, and practices I’ve learned from this book and will publish them in multiple parts.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that there are quotes and code examples that I’ve used from the original book in this series.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So without further ado, Let’s start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#1 Short Functions Are Better&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What uncle bob says about a function’s length is that the smaller a function is, The better.&lt;br&gt;
He suggests that the block of code inside an &lt;code&gt;if&lt;/code&gt; statement, &lt;code&gt;else&lt;/code&gt; statement, and &lt;code&gt;while&lt;/code&gt; statement should be just one line. Also, the indent level of a function should not be more than one or two.&lt;/p&gt;

&lt;p&gt;It’s a good practice if you could do it. It’s not always possible to follow this rule strictly, But try to do it as much as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#2 Introduce Instance Variables When Possible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Passing instance variables instead of primitive parameters into a function is a good idea when it’s proper. But when it’s proper?&lt;/p&gt;

&lt;p&gt;Consider a large function with many variables declared within it. Let’s say you want to extract one small part of that function into a separate function. However, the code you want to extract uses four of the variables declared in the function.&lt;/p&gt;

&lt;p&gt;This is a situation where passing an instance variable may be a good idea.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&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;function&lt;/span&gt; &lt;span class="n"&gt;__construct&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// doing some logic&lt;/span&gt;
   &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$var1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$var1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// doing some logic with vars&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;Will become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$var&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;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;VarThing&lt;/span&gt; &lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="p"&gt;;&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;function&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// doing some logic&lt;/span&gt;
   &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHtml&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getHtml&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// $this-&amp;gt;var is accessible here&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;&lt;strong&gt;#3 The BUILD-OPERATE-CHECK Pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You’ve probably heard of Arrange-Act-Assert or AAA pattern before, Which is similar to the &lt;code&gt;Build-Operate-Check&lt;/code&gt; pattern.&lt;/p&gt;

&lt;p&gt;How do you think we can improve the following code?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testGetPageHieratchyAsXml&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne.ChildOne"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageTwo"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pages"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$responder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SerializedPageResponder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$responder&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;makeResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FitNesseContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"text/xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContentType&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&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;function&lt;/span&gt; &lt;span class="n"&gt;testGetPageHieratchyAsXmlDoesntContainSymbolicLinks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nv"&gt;$pageOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne.ChildOne"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageTwo"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$pageOne&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nv"&gt;$properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getProperties&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$symLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$properties&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SymbolicPage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PROPERTY_NAME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$symLinks&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SymPage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"PageTwo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$pageOne&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pages"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$responder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SerializedPageResponder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$responder&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;makeResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FitNesseContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"text/xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContentType&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertNotSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SymPage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&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;function&lt;/span&gt; &lt;span class="n"&gt;testGetDataAsHtml&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;PathParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
           &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TestPageOne"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;"test page"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TestPageOne"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$responder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SerializedPageResponder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$responder&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;makeResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FitNesseContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"text/xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContentType&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertSubString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$xml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we can improve it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testGetPageHierarchyAsXml&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;makePages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"PageOne.ChildOne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"PageTwo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;submitRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"type:pages"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseIsXML&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseContains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testSymbolicLinksAreNotInXmlPageHierarchy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makePage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;makePages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PageOne.ChildOne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"PageTwo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;addLinkTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"PageTwo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"SymPage"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;submitRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"type:pages"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseIsXML&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseContains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseDoesNotContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SymPage"&lt;/span&gt;&lt;span class="p"&gt;);&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;function&lt;/span&gt; &lt;span class="n"&gt;testGetDataAsXml&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;makePageWithContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TestPageOne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"test page"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;submitRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TestPageOne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"type:data"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseIsXML&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;assertResponseContains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;Test"&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;The benefit of this pattern is that the vast majority of annoying details have been eliminated. The tests get right to the point and use only the data types and functions that they truly need. Anyone who reads these tests should be able to understand what they do very quickly, without being misled or overwhelmed by details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#4 Single Responsibility and Error Handling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The best way to describe this is to quote directly from the book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Functions should do one thing. Error handing is one thing. Thus, a function that handles errors should do nothing else. This implies that if the keyword try exists in a function, it should be the very first word in the function and that there should be nothing after the catch/finally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;#5 Better Error Handling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;how do you think this piece of code can get better shaped?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ACMEPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DeviceResponseException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reportPortError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Device response exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ATM1212UnlockedException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reportPortError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Unlock exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GMXError&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reportPortError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Device response exception"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;/// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can simplify our code considerably by wrapping the API that we are calling and making sure that it returns a common exception type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LocalPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PortDeviceFailure&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;reportError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalPort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$innerPort&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;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$portNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;innerPort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ACMEPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$portNumber&lt;/span&gt;&lt;span class="p"&gt;);&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;function&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;innerPort&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DeviceResponseException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PortDeviceFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ATM1212UnlockedException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PortDeviceFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GMXError&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PortDeviceFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wrappers like the one we defined for ACMEPort can be very useful.&lt;/p&gt;

&lt;p&gt;Okay. This is it for this part. I’ll continue posting the next parts soon. You can join my &lt;a href="https://t.me/themehradsadeghi" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt; channel to get notified of the latest posts. Also, you can follow me on &lt;a href="https://twitter.com/realmehrad" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://linkedin.com/in/mehradsadeghi" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>programming</category>
      <category>php</category>
      <category>softwaredesign</category>
    </item>
    <item>
      <title>A Few Words on Webhooks</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Mon, 01 Aug 2022 18:58:00 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/a-few-words-on-webhooks-9gm</link>
      <guid>https://dev.to/mehradsadeghi/a-few-words-on-webhooks-9gm</guid>
      <description>&lt;p&gt;In 2006 during working on a startup, Jeff Lindsay wrote about an architectural pattern he called “webhooks”. Since then almost all web developers have heard this term.&lt;/p&gt;

&lt;p&gt;I think webhooks are mostly based on the Observer design pattern. Observer is a pattern where an observer is observing (looking) for an event to be fired. The important part here is that the observer is not polling anything, It registers itself to the origin to get notified when the desired event happens.&lt;br&gt;
Polling is another method where the destination is checking for new changes in origin constantly, As opposed to what the observer pattern does.&lt;/p&gt;

&lt;p&gt;Webhooks are very similar to observers. A webhook is basically an endpoint that should be notified (called) when an event is dispatched. This approach is better than the “Polling” method in most cases. It is faster and uses less resource.&lt;/p&gt;

&lt;p&gt;So by webhooks, Applications can use a so-called “hook”, To send automated messages to each other when something (an event) happens. For example, When you buy a product online, You receive an email or an SMS. What happens here is that the email or SMS provider provides an endpoint (in this context a webhook) and the store calls this endpoint when for example an order is placed.&lt;/p&gt;

&lt;p&gt;You can learn more about webhooks in this crash course on &lt;a href="https://www.youtube.com/watch?v=41NOoEz3Tzc" rel="noopener noreferrer"&gt;youtube&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web</category>
      <category>webhook</category>
      <category>webhooks</category>
    </item>
    <item>
      <title>Laravel CRUD Generator</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Tue, 22 Sep 2020 15:56:00 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/laravel-crud-generator-33on</link>
      <guid>https://dev.to/mehradsadeghi/laravel-crud-generator-33on</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/mehradsadeghi/laravel-crud-generator" rel="noopener noreferrer"&gt;Laravel CRUD Generator&lt;/a&gt; is a simple and light-weight wrapper on Laravel's default controller generator, Which makes creating a controller with a pre-defined CRUD like a breeze.&lt;/p&gt;

&lt;p&gt;You can define your validation rules in an interactive way that &lt;a href="https://github.com/mehradsadeghi/laravel-crud-generator" rel="noopener noreferrer"&gt;crud-generator&lt;/a&gt; provides. Also it is compatible with Laravel 5.x, 6.x, 7.x, 8.x and 9.x.&lt;/p&gt;

&lt;p&gt;There is demo available &lt;a href="https://github.com/mehradsadeghi/laravel-crud-generator" rel="noopener noreferrer"&gt;here&lt;/a&gt; which is showing how it's done :)&lt;/p&gt;

&lt;h4&gt;
  
  
  Installation
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$ composer require mehradsadeghi/laravel-crud-generator&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;It works based on your &lt;code&gt;$fillable&lt;/code&gt; property of the target model.&lt;/p&gt;

&lt;p&gt;If you would like to use &lt;code&gt;$guarded&lt;/code&gt; instead of &lt;code&gt;$fillable&lt;/code&gt;, It is supported too. In that case you'll need to have an existing Schema (table), Then the crud generator will automatically figures out your fillables.&lt;/p&gt;

&lt;p&gt;As an example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ php artisan make:crud UserController --model=User&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you would like to have validaiton rules too, You may enter the &lt;code&gt;--validation&lt;/code&gt; option:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ php artisan make:crud UserController --model=User --validation&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Customizing Default Stubs
&lt;/h4&gt;

&lt;p&gt;It is possible to publish default stubs and change them in a way that fulfills your requirements.&lt;/p&gt;

&lt;p&gt;In order to do this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ php artisan crud:publish&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The published stubs will be located within stubs/crud directory in the root of your application. Any changes you make to these stubs will be reflected when you generate crud.&lt;/p&gt;

&lt;p&gt;Feel free to take a look at &lt;a href="https://github.com/mehradsadeghi/laravel-crud-generator" rel="noopener noreferrer"&gt;crud-generator&lt;/a&gt; repository.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>crud</category>
      <category>generator</category>
    </item>
    <item>
      <title>How To Filter Your Eloquent Queries Based on URL Query String in Laravel Like a Pro</title>
      <dc:creator>Mehrad Sadeghi</dc:creator>
      <pubDate>Fri, 31 Jul 2020 17:50:00 +0000</pubDate>
      <link>https://dev.to/mehradsadeghi/how-to-filter-your-eloquent-queries-based-on-url-query-string-in-laravel-like-a-pro-7i2</link>
      <guid>https://dev.to/mehradsadeghi/how-to-filter-your-eloquent-queries-based-on-url-query-string-in-laravel-like-a-pro-7i2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx4fufgo280rufwu551p3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx4fufgo280rufwu551p3.png" alt="Alt Text" width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Describing the Problem
&lt;/h2&gt;

&lt;p&gt;You have probably faced the situation where you needed to filter your query based on given parameters in url query-string and after developing the logics, You've had a code-base like what we can in the above image.&lt;/p&gt;

&lt;p&gt;This approach works, But it's not a good practice.&lt;/p&gt;

&lt;p&gt;When the number of parameters starts to grow, The number of these kind of &lt;code&gt;if&lt;/code&gt; statements also grows and your code gets huge and hard to maintain.&lt;/p&gt;

&lt;p&gt;Also it's against the Open/Closed principal of SOLID principles, Because when you have a new parameter, You need to get into your existing code and add a new logic (which may breaks the existing implementations).&lt;/p&gt;

&lt;p&gt;So we have to design a way to make our filters logics separated from each other and apply them into the final query, which is the whole idea behind the package I wrote for Laravel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel Filter Query String
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;First you need to install the package:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$ composer require mehradsadeghi/laravel-filter-querystring&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then you should &lt;code&gt;use&lt;/code&gt; the &lt;code&gt;FilterQueryString&lt;/code&gt; trait in your model, And define &lt;code&gt;$filters&lt;/code&gt; property which can be consist of available filters or your custom filters.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Mehradsadeghi\FilterQueryString\FilterQueryString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;FilterQueryString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="mf"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then you need to use &lt;code&gt;filter()&lt;/code&gt; method in your eloquent query. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Available Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sort&lt;/li&gt;
&lt;li&gt;Comparisons&lt;/li&gt;
&lt;li&gt;In&lt;/li&gt;
&lt;li&gt;Like&lt;/li&gt;
&lt;li&gt;Where clause&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the purpose of explaining each method, Imagine we have such data in our &lt;code&gt;users&lt;/code&gt; table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;reza&lt;/td&gt;
&lt;td&gt;reza@example.com&lt;/td&gt;
&lt;td&gt;reza123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;hossein&lt;/td&gt;
&lt;td&gt;hossein@example.com&lt;/td&gt;
&lt;td&gt;hossein123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-11-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And assume our query is something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sort
&lt;/h3&gt;

&lt;p&gt;Sort is the equivalent to &lt;code&gt;order by&lt;/code&gt; sql statement which can be used flexible in &lt;code&gt;FilterQueryString&lt;/code&gt;:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?sort=field
?sort=field,sort_type
?sort[0]=field1&amp;amp;sort[1]=field2
?sort[0]=field1&amp;amp;sort[1]=field2,sort_type
?sort[0]=field1,sort_type&amp;amp;sort[1]=field2,sort_type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sort'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Single &lt;code&gt;sort&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?sort=created_at&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reza&lt;/td&gt;
&lt;td&gt;reza@example.com&lt;/td&gt;
&lt;td&gt;reza123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hossein&lt;/td&gt;
&lt;td&gt;hossein@example.com&lt;/td&gt;
&lt;td&gt;hossein123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-11-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Note&lt;/strong&gt; that when you're not defining &lt;code&gt;sort_type&lt;/code&gt;, It'll be &lt;code&gt;asc&lt;/code&gt; by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multiple &lt;code&gt;sort&lt;/code&gt;s&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?sort[0]=age,desc&amp;amp;sort[1]=created_at,desc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hossein&lt;/td&gt;
&lt;td&gt;hossein@example.com&lt;/td&gt;
&lt;td&gt;hossein123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-11-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reza&lt;/td&gt;
&lt;td&gt;reza@example.com&lt;/td&gt;
&lt;td&gt;reza123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Comparisons
&lt;/h3&gt;

&lt;p&gt;Comparisons are consist of 6 filters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;greater&lt;/li&gt;
&lt;li&gt;greater_or_equal&lt;/li&gt;
&lt;li&gt;less&lt;/li&gt;
&lt;li&gt;less_or_equal&lt;/li&gt;
&lt;li&gt;between&lt;/li&gt;
&lt;li&gt;not_between&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?greater=field,value
?greater_or_equal=field,value
?less=field,value
?less_or_equal=field,value
?between=field,value1,value2
?not_between=field,value1,value2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'greater'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'greater_or_equal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'less'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'less_or_equal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'between'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'not_between'&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example of &lt;code&gt;greater&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?greater=age,20&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;hossein&lt;/td&gt;
&lt;td&gt;hossein@example.com&lt;/td&gt;
&lt;td&gt;hossein123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-11-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example of &lt;code&gt;not_between&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?not_between=age,21,30&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reza&lt;/td&gt;
&lt;td&gt;reza@example.com&lt;/td&gt;
&lt;td&gt;reza123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  In
&lt;/h3&gt;

&lt;p&gt;In clause is the equivalent to &lt;code&gt;where in&lt;/code&gt; sql statement.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?in=field,value1,value2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'in'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;code&gt;https://example.com?in=name,mehrad,reza&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reza&lt;/td&gt;
&lt;td&gt;reza@example.com&lt;/td&gt;
&lt;td&gt;reza123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Like
&lt;/h3&gt;

&lt;p&gt;Like clause is the equivalent to &lt;code&gt;like '%value%'&lt;/code&gt; sql statement.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?like=field,value
?like[0]=field1,value1&amp;amp;like[1]=field2,value2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'like'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Single &lt;code&gt;like&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?like=name,meh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Multiple &lt;code&gt;like&lt;/code&gt;s&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?like[0]=name,meh&amp;amp;like[1]=username,dar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Where Clause (default filter)
&lt;/h3&gt;

&lt;p&gt;Generally when your query string parameters are not one of previous available methods, It'll get filtered by the default filter which is the &lt;code&gt;where&lt;/code&gt; sql statement. It's the proper filter when you need to directly filter one of your table's columns.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?field=value
?field1=value&amp;amp;field2=value
?field1[0]=value1&amp;amp;field1[1]=value2
?field1[0]=value1&amp;amp;field1[1]=value2&amp;amp;field2[0]=value1&amp;amp;field2[1]=value2 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming we want to filter &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; database columns, In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;code&gt;https://example.com?name=mehrad&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;&lt;code&gt;https://example.com?age=22&amp;amp;username=dariush123&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;&lt;code&gt;https://example.com?name[0]=mehrad&amp;amp;name[1]=dariush&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;&lt;code&gt;https://example.com?name[0]=mehrad&amp;amp;name[1]=dariush&amp;amp;username[0]=mehrad123&amp;amp;username[1]=reza1234&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mehrad&lt;/td&gt;
&lt;td&gt;mehrad@example.com&lt;/td&gt;
&lt;td&gt;mehrad123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Custom Filters
&lt;/h3&gt;

&lt;p&gt;By custom filters you can define your own methods as filters. This helps with the Open/Closed of SOLID principles, Hence each time a new filter is needed, you don't have to edit previous filters and you can just write a separate method for it.&lt;/p&gt;

&lt;p&gt;Let's create a custom filter. Assuming you want to create a filter named &lt;code&gt;all_except&lt;/code&gt; which retrieves all users except the one that is specified:&lt;/p&gt;

&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'all_except'&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;function&lt;/span&gt; &lt;span class="n"&gt;all_except&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'!='&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&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;To test our newly added filter:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com?all_except=mehrad&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;reza&lt;/td&gt;
&lt;td&gt;reza@example.com&lt;/td&gt;
&lt;td&gt;reza123&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;2020-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hossein&lt;/td&gt;
&lt;td&gt;hossein@example.com&lt;/td&gt;
&lt;td&gt;hossein123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-11-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that your custom defined filters have the most priority which means you can even override available filters.&lt;/p&gt;

&lt;p&gt;For example lets change &lt;code&gt;in&lt;/code&gt; filter in a way that only accepts 3 values:&lt;/p&gt;

&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'in'&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;function&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nv"&gt;$exploded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&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="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exploded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// throwing an exception or whatever you like to do&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exploded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;whereIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$exploded&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;&lt;strong&gt;Another&lt;/strong&gt; good example for custom filters are when you don't want to expose your database table's column name. For example assume we don't want to expose that we have a column named &lt;code&gt;username&lt;/code&gt; in &lt;code&gt;users&lt;/code&gt; table:&lt;/p&gt;

&lt;p&gt;In User.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'by'&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;function&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&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;&lt;code&gt;https://example.com?by=dariush123&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;email&lt;/th&gt;
&lt;th&gt;username&lt;/th&gt;
&lt;th&gt;age&lt;/th&gt;
&lt;th&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dariush&lt;/td&gt;
&lt;td&gt;dariush@example.com&lt;/td&gt;
&lt;td&gt;dariush123&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;2020-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Minor Tip
&lt;/h4&gt;

&lt;p&gt;In order to prevent your model to get messy or populated with filter methods, You can create a trait for it and put everything about filters inside the trait.&lt;/p&gt;

&lt;p&gt;You can also take a look at &lt;a href="https://github.com/mehradsadeghi/laravel-filter-querystring" rel="noopener noreferrer"&gt;Laravel Filter Query String&lt;/a&gt; GitHub repo.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>eloquent</category>
      <category>query</category>
      <category>filter</category>
    </item>
  </channel>
</rss>
