<?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>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>
