<?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: Yoav Abrahami</title>
    <description>The latest articles on DEV Community by Yoav Abrahami (@yoav_abrahami_736759c4edd).</description>
    <link>https://dev.to/yoav_abrahami_736759c4edd</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2707109%2F85279187-062b-4c56-9bcd-7ef7a803589b.jpg</url>
      <title>DEV Community: Yoav Abrahami</title>
      <link>https://dev.to/yoav_abrahami_736759c4edd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yoav_abrahami_736759c4edd"/>
    <language>en</language>
    <item>
      <title>Running microservices? Here is what we learned how to build reliable microservices at scale</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Mon, 05 May 2025 07:22:40 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/running-microservices-here-is-what-we-learned-how-to-build-reliable-microservices-at-scale-4jco</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/running-microservices-here-is-what-we-learned-how-to-build-reliable-microservices-at-scale-4jco</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk" class="crayons-story__hidden-navigation-link"&gt;Microservices Reliability Playbook, Part 1 - Introduction to Risk&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/yoav_abrahami_736759c4edd" class="crayons-avatar  crayons-avatar--l  "&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%2Fuploads%2Fuser%2Fprofile_image%2F2707109%2F85279187-062b-4c56-9bcd-7ef7a803589b.jpg" alt="yoav_abrahami_736759c4edd profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/yoav_abrahami_736759c4edd" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Yoav Abrahami
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Yoav Abrahami
                
              
              &lt;div id="story-author-preview-content-2457681" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/yoav_abrahami_736759c4edd" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuploads%2Fuser%2Fprofile_image%2F2707109%2F85279187-062b-4c56-9bcd-7ef7a803589b.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Yoav Abrahami&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 4 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk" id="article-link-2457681"&gt;
          Microservices Reliability Playbook, Part 1 - Introduction to Risk
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/microservices"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;microservices&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sre"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sre&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/reliability"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;reliability&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 7 - Call Patterns</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:42 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021</guid>
      <description>&lt;p&gt;Microservices Call Patterns focus on improving reliability of a single network call, such as retry and cache.&lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk"&gt;Introduction to Risk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Introduction to Microservices Reliability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Call Patterns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pass Through Cache Pattern
&lt;/h2&gt;

&lt;p&gt;The Pass Through Cache Pattern is using a cache service in front of a microservice. The cache has three functions - improves performance, improves reliability and, in addition, can answer for cached data even if the microservice is not available. Most cache systems are designed to be five-nines, with a single network call to fetch cached data (if not served from memory).&lt;/p&gt;

&lt;p&gt;The cache pattern however has a few fundamental problems that limit its ability to improve reliability. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Not all microservice API calls can be cached. In a nutshell, we can only cache read operations that are slowly changing.&lt;/li&gt;
&lt;li&gt;Cache systems are statistical systems, caching only part of the API calls. As a result, in case of a problem with the underlying system, a cache system can only support the cached data.&lt;/li&gt;
&lt;li&gt;Cache systems are designed to be non persistent. On updates, flush or other events the cache system may have small amount of cached api calls, again limiting it ability to improve reliability&lt;/li&gt;
&lt;li&gt;A Cache system incurs one additional network call to the cache system, which is required regardless of cache hit or miss. &lt;/li&gt;
&lt;li&gt;All the above amounts to a challenge to comprehend why some operations are cached and some are not, creating a potentially unexpected pattern of errors for the upstream system calling the cache.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As a result, to calculate the predicted reliability of a system with cache, we need to compute the predicted reliability of the system with a cache hit and without a cache hit, factoring in the additional network call to the cache system, and combine using weighted average the predicted reliability. The formula for predicted reliability becomes&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.amazonaws.com%2Fuploads%2Farticles%2F8kbd0zgk75gbdr6xvw2d.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%2Fuploads%2Farticles%2F8kbd0zgk75gbdr6xvw2d.png" alt="predicted reliability equals 1 minus ((1 - predicted reliability with cache) times (cache hit rate) + (1 - predicted reliability without cache) times (cache miss rate))" width="608" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, the formula becomes quite complicated, and if we have multiple cache systems it becomes even more difficult to comprehend - hence the complication of comprehending reliability of systems with cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retry Pattern
&lt;/h2&gt;

&lt;p&gt;The retry pattern is a simple way to handle some failures and improve reliability. Why some? As a general rule, retry handles momentary outages we denote here as risk of load and latency, but fail to handle (in most cases) the outages due to risk of change. &lt;/p&gt;

&lt;p&gt;Outages caused by load and latency tend to be momentary - and another try even 1ms later can succeed where the previous one failed. However, outages caused by change tend to take minutes to tens of minutes to fix, and in some cases more. As a result, retrying a few milliseconds later will most probably hit the same outrage caused by change.&lt;/p&gt;

&lt;p&gt;Retry also implies the operation to retry is idempotent - it is designed to be retied. Read operations are idempotent by definition, while operations with side effects, persistence, data updates, inserts or deletes are by default not idempotent. However, in some cases such operations can be modelled as idempotent.&lt;/p&gt;

&lt;p&gt;Mutation operations can be made idempotent using an operation key by checking if an operation with the key already happened. While this sounds very generic, we all know a few implementations of this general idea - such as using a transaction id, optimistic locking or update by insert with client provided primary key value. The common among all is that if we retry, while the original request has succeeded, the second can be detected using the key value and handled accordingly (for instance, prevent the double doing while returning a success to the client).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction_id&lt;/strong&gt; - the providing service on receiving a mutation operation with a transaction id, first writes it to a write ahead log and then processes the mutation to other tables. If the transaction id already exists in the write ahead log, a duplicate key error is potentially ignored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic locking&lt;/strong&gt; - the providing service checks the client supplied version, and if that version does not match the current version + 1, it rejects the operation. On retry, if the previous attempt worked, the version number has already advanced and the second try will fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update by insert&lt;/strong&gt; - The providing service does an insert into a log table (similar to transaction id) instead of an update. For instance, consider an inventory system that on checkout updates the inventory to have one less product. An update operation of &lt;code&gt;update inventory set product_inventory = product_inventory - count&lt;/code&gt; is not idempotent. However, an insert operation of &lt;code&gt;insert into ordered_inventory (product_id, order_id, count) values (?, ?, ?)&lt;/code&gt; is idempotent if we have a primary key or unique index on &lt;code&gt;product_id, order_id&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is the effect of retry on predicted reliability? First, it only affects the ‘risk of load and latency’ component, and then it reduces the risk divided by the number of retries.&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.amazonaws.com%2Fuploads%2Farticles%2Ftxfgy7u1oxll8iddj1j3.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%2Fuploads%2Farticles%2Ftxfgy7u1oxll8iddj1j3.png" alt="Predicted Reliability with retry equals 1 - (1 - risk load and latency without retry) divided by (number of retries) " width="631" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fallback Pattern
&lt;/h2&gt;

&lt;p&gt;The fallback pattern recognizes that risk exists and things can fail. Once something does fail, the system is designed to do something different, such as fallback to another service, to another product flow or to shutdown a feature.&lt;/p&gt;

&lt;p&gt;Fallback can be implemented as &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fallback of a certain microservice can be an equivalent microservice deployed into another data center, another cloud, another zone (handles risk of load and latency)&lt;/li&gt;
&lt;li&gt;Fallback of a certain microservice can be a delayed deployed microservice, such as 1 week ago version (handles risk of change, yet requires forward / backward compatibility)&lt;/li&gt;
&lt;li&gt;Fallback of a certain microservice can be another implementation of the microservice using another software stack or another SaaS provider, like another payment provider, another type of cloud database, another email provider, etc. We can have multiple providers with different transaction prices, trying the more cost effective first, and if that fails, use the more costly option.&lt;/li&gt;
&lt;li&gt;Fallback can be by changing functionality - if we detect the email service fails, we can try the SMS service instead.&lt;/li&gt;
&lt;li&gt;Fallback can be by shutting down a feature - if the coupon service fails, we can block the ability to add coupons on checkout. If the shipping calculator service fails, we can show the cart without shipping cost and show a message that shipping costs will be provided using email soon, or we can use a generic average shipping code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The impact of a fallback pattern improves reliability by handling the error cases, and turning them into another valid flow. While the fallback itself can fail, the reality is that the end result is way more reliable.&lt;/p&gt;

&lt;p&gt;The predicted reliability of a system with a fallback becomes  &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.amazonaws.com%2Fuploads%2Farticles%2Fxonklz530j4tmxv1ao2o.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%2Fuploads%2Farticles%2Fxonklz530j4tmxv1ao2o.png" alt="Predicted Reliability with fallback equals (predicted reliability of the system upstream of the fallback) times ((predicted reliability of the system downstream of the fallback) plus (1 - (predicted reliability of the system downstream of the fallback) times (fallback system predicted reliability)))" width="616" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the formula above, we break the system to anything before the microservice with a fallback pattern implemented (upstream system) and anything after (downstream system). The fallback only handles features of the downstream system, compensating given its own reliability. &lt;/p&gt;

&lt;h2&gt;
  
  
  Circuit Breaker
&lt;/h2&gt;

&lt;p&gt;The Circuit Breaker pattern is a pattern to ensure a downstream subsystem load does not exceed a certain limit, or that a specific customer / tenant / client consumes all the resources and creates a “denial of service” equivalent on the downstream system.&lt;/p&gt;

&lt;p&gt;When a circuit breaker is activated, it is knowingly causing errors, like 429 too many requests or 504 timeouts. Circuit Breaker creates a clear cutoff point at which client services experience and can expect a failure, falling back to another flow. &lt;/p&gt;

&lt;p&gt;Consider for instance a personalized recommended products service, which gives product recommendations adapted specifically for each user on a product page. If this service fails or is overloaded, a circuit breaker can be activated to prevent additional load on the service. A fallback can be to hide the recommended products section in the product page, or show a cached generic (not personalized) recommended products.&lt;/p&gt;

&lt;p&gt;We have to ask - why is Circuit Breaker considered a reliability pattern if it creates errors? The Circuit Breaker protects a downstream system from resource exhaustion and improves the reliability for other clients of the downstream system.&lt;/p&gt;

&lt;p&gt;Circuit Breaker can be implemented as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A limit of API calls per client per period of time.&lt;/li&gt;
&lt;li&gt;A backoff on the number of errors or rate of errors from the downstream system,  triggering the circuit breaker for a period of time.&lt;/li&gt;
&lt;li&gt;A backoff on downstream system load, such as downstream system returns 429 or 504 HTTP status (or equivalent), enabling the downstream system cooldown for a period of time.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 6 - Multi-Service Patterns</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:39 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl</guid>
      <description>&lt;p&gt;Multi-Service Patterns combine both reader and writers to larger and more complex systems&lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk"&gt;Introduction to Risk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Introduction to Microservices Reliability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Multi-Service Patterns&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Command Query Responsibility Segregation (CQRS) Pattern
&lt;/h2&gt;

&lt;p&gt;The CQRS pattern combines the ideas of the Writer Pattern with a Queue and the Reader Pattern. &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.amazonaws.com%2Fuploads%2Farticles%2Fwyx4fp742l98kkg5pulx.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%2Fuploads%2Farticles%2Fwyx4fp742l98kkg5pulx.png" alt="CQRS Pattern Diagram" width="535" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The pattern mandates that writes are written as Commands into a queue. A Command is just a message with instructions to mutate data - insert, update or delete, for one or more tables or services. A processor service accepts the Command, does the processing, enrichments and any other operations needed, and writes optimized for reads data to a database used by a reader service.&lt;/p&gt;

&lt;p&gt;There are multiple variations of the CQRS pattern, using an event log instead of a queue, deciding when and how to update the reader service (sometimes called materialized views), yet the main principles remain the same - simple writer and simple reader services.&lt;/p&gt;

&lt;p&gt;Regarding consistency, what is the source of truth? How does a client see their own writing? How do we ensure no two conflicting writes? All of those topics have multiple solutions, from optimistic locking to client retrying reads until they get their latest writes - all with advantages and disadvantages which are a whole topic by themselves.&lt;/p&gt;

&lt;p&gt;The main advantage of the CQRS pattern is the decoupling of the system into 3 components - the writer which is simple, the reader which is simple, and the processor which can be complex. &lt;/p&gt;

&lt;p&gt;CQRS is frequently used combined with Event Sourcing to create a log of events or commands, the writes. Those events can be partial writes, which are then summarized by the processor into the full up to date system state available to readers. &lt;/p&gt;

&lt;p&gt;In addition, this architecture allows creating multiple readers to each get the slice of data optimized for their use case, all based on the same written data.&lt;/p&gt;

&lt;p&gt;The pattern optimizes latency for both reads and writes, ensures high reliability of both, at the price of added complexity to the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Split by SLO Pattern
&lt;/h2&gt;

&lt;p&gt;The split by SLP Pattern is similar to the previous (Split Read / Write by SLO Pattern), but on a larger scale. Consider a group of micro services who are supporting multiple business flows. Those different business flows may have different SLA, and as a result we have different SLO operations running on the same set of microservices. The pattern suggests to split the group into two separate groups of microservices, such that one group supports the higher SLO operations independent of the lower SLO group, while the lower SLO group can rely on the higher SLO group.&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.amazonaws.com%2Fuploads%2Farticles%2Fnb1n26jk4d7kbu6gy3pr.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%2Fuploads%2Farticles%2Fnb1n26jk4d7kbu6gy3pr.png" alt="Split by SLO Pattern diagram" width="481" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For instance, consider the cart example we had before. The higher SLO operations are the operations that support the checkout flow, while the lower SLO operations are operations such as updating the product catalog, the shipping configuration or the tax configuration. In addition, analytical operations are also of lower SLO. The split by SLO pattern mandates that we split the system into checkout supporting services and all other services. As we do so, we may employ the Split Read / Write by SLO Pattern for services such as the product catalog, tax and shipment.&lt;/p&gt;

&lt;p&gt;Lets focus on the shipping calculator service. The service has one function to calculate the shipping costs of items in a cart. However, it has more functions - to manage the shipping rules probably with CRUD APIs, including validations, maybe simulate calculations for some rules management application, and maybe more operations. We want to decouple the risk of change and risk of load of all other functions from the higher SLO function of calculate shipping for a cart. We split the service into a reader (who only performs the shipping calculation) and a writer who does everything else, including the CRUD operations of shipping rules.&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.amazonaws.com%2Fuploads%2Farticles%2F9ra0t1b5zdgdl1r8v8k5.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%2Fuploads%2Farticles%2F9ra0t1b5zdgdl1r8v8k5.png" alt="Example diagram of Split by SLO for shipping calculator operation" width="637" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: Why do we consider checkout operations to have higher SLO, while all other operations are of lower SLO? SLO definition is a business definition that considers risk and the ability to absorb delays or other problems vs investment in higher SLO system. For online commerce, the most critical operation is the checkout operation, as it and it alone generates money. All other operations are supporting, and even if they fail, as long as the checkout continues to operate the business is in a good situation.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 5 - Write patterns</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:34 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p</guid>
      <description>&lt;p&gt;Microservices Write Patterns focus on how to write data in a reliable way, including writing to multiple microservices.&lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk"&gt;Introduction to Risk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Introduction to Microservices Reliability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Write Patterns&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Writer Pattern
&lt;/h2&gt;

&lt;p&gt;The writer pattern isolates write operations from processing. It is useful when write operations have to have highest reliability. The writer pattern assumes a simple write, for complex multi-table or multi-service writes consider the multi-writer pattern.&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.amazonaws.com%2Fuploads%2Farticles%2Febz1oc7xkyywdvkkkhu7.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%2Fuploads%2Farticles%2Febz1oc7xkyywdvkkkhu7.png" alt="Writer Pattern Diagram" width="534" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One example of an application of the writer pattern is the order writer - once an order has been paid, a system has to write the order with a high reliability service to ensure no orders are lost. Then, it can start handling all the aspects of the order, from fulfillment to updating different “my account” pages, analytics, etc.&lt;/p&gt;

&lt;p&gt;Once the writing is done, the writer pattern triggers a call to the processor / reader service to process the write operation (e.g. the order).&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple writer service as an ideal microservice, five-nines reliability.&lt;/li&gt;
&lt;li&gt;No processing on write - less chance of failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The call to the processing of the order is non-garanteed, as the service first writes the order, then calls the processing. In case of failure of the processing, we have an order that has not been processed. This requires another mechanism to ensure all orders are processed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Writer Pattern with a Queue
&lt;/h2&gt;

&lt;p&gt;The writer pattern may use a persistent queue instead of a table for the write, so that both the update of the written data and the processing are driven by the queue. Persistent queues are a great tool to create reliable multi-reaction writes, which can be utilized here. &lt;/p&gt;

&lt;p&gt;The writer does only two things - validates the write (access control and business validation) and writes the data to a persistent queue. &lt;/p&gt;

&lt;p&gt;This pattern has a downside that it is challenging to get a client to read their own writes immediately, and it is challenging to propagate processing failure to the client. One technique to resolve both is to return a “ticket number” on the write operation, and another API on the processor to get the status of the “ticket number” - was the processing completed and now the writer can read their own writes? Was the processing successful, and if not why?&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.amazonaws.com%2Fuploads%2Farticles%2Fwpizjk45mv7ah5qr0717.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%2Fuploads%2Farticles%2Fwpizjk45mv7ah5qr0717.png" alt="Writer Pattern with a Queue diagram" width="437" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For instance, applied to the same order service, the order writer writes the order to a queue, which then the processor dequeues, gets the order, writes the order to the database as well as performs any needed processing. &lt;/p&gt;

&lt;p&gt;The main advantage of this pattern compared to the Writer pattern is the error handling and persistence we get from the queue. All we need to ensure the data (an order) will be processed is the writer service and the queue to be operational. &lt;/p&gt;

&lt;p&gt;In case the processor / reader is not online, or has a problem, the queue saves the written data (orders) to be processed later, or retried.&lt;/p&gt;

&lt;p&gt;Also, we note that the writer service is very simple, decoupling the risk of change related to all the processing (order processing).&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Writer Pattern
&lt;/h2&gt;

&lt;p&gt;The multi-writer pattern is a generalization of the Writer Pattern with a Queue, in case we have to write to multiple microservices in a reliable way.&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.amazonaws.com%2Fuploads%2Farticles%2F63x4ikr7lqdp9xrdh5xf.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%2Fuploads%2Farticles%2F63x4ikr7lqdp9xrdh5xf.png" alt="Multi-writer pattern diagram" width="455" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider a write operation for the product catalog, at which the catalog, inventory and categories are each managed by a different microservice. The multi-writer pattern allows one to create a single product writer that gets the details of the product, category and inventory, and writes it all to a queue. Each processing service accepts the message from the queue and handles the writes to its database.&lt;/p&gt;

&lt;p&gt;The advantage of this pattern is that it decouples writes from processing and reads, while allowing multiple services to be reliably updated.&lt;/p&gt;

&lt;p&gt;However, this pattern also introduces a risk that some of the writes have completed successfully, while other writes have failed or are pending due to some delay. The pattern does not guarantee transactional write to multiple microservices, creating the risk of inconsistencies. Such inconsistencies can be mitigated into an eventual consistent system using the persistent queue and a retry mechanism, one that eventually will complete all the writes and restore the system into a consistent state.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 4 - Read patterns</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:30 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo</guid>
      <description>&lt;p&gt;Microservices Read Patterns focus on how to read data in a reliable and fast way, given constraints such as multi-service reads.&lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk"&gt;Introduction to Risk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Introduction to Microservices Reliability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Read Patterns&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reader Pattern
&lt;/h2&gt;

&lt;p&gt;The Reader pattern mandates that we split a system into two microservices (reader and writer), favoring higher SLO for read operations. The Reader service is built to be very simple, with reading data from the database and returning it, working on the same database that the writer writes into. The reader may perform complex queries including joins to read the data.  &lt;/p&gt;

&lt;p&gt;For instance we can consider a product catalog CRUD service. We can consider the get product and search for product APIs as the more critical APIs that require 0.99999 % reliability, while the rest of the update APIs can have a lower SLO. The product catalog reader service may query the products, categories, variants, inventory and other tables to fulfill the get product and search for product APIs.&lt;/p&gt;

&lt;p&gt;The Reader Pattern applied to the product catalog&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.amazonaws.com%2Fuploads%2Farticles%2F0tivaubyj5b0uh3tq3u9.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%2Fuploads%2Farticles%2F0tivaubyj5b0uh3tq3u9.png" alt="splitting a microservice to reader vs writer / processor" width="551" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also note that regarding risk of change, it is more likely that more changes are applied to the Create / Update / Delete operations of the product catalog, while the Read operation tends to be more stable. In any case, we isolate the read operation from risk of change of the Create / Update / Delete operations.&lt;/p&gt;

&lt;p&gt;It is important to note that this pattern is great when the database schema is simple. However, when a read operation requires reading from multiple tables using complex queries, stored procedures or multiple queries, those also affect latency and reliability.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple reader service as an ideal microservice, five-nines reliability.&lt;/li&gt;
&lt;li&gt;Decouple risk of change of write and processing operations from higher SLO read operations&lt;/li&gt;
&lt;li&gt;Isolate high SLO read operations from other lower SLO operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For complex DB schema with references, read operations still need complex queries or multiple queries, which impacts latency and reliability.&lt;/li&gt;
&lt;li&gt;Shared dependency on the database (Reader vs writer / processor)&lt;/li&gt;
&lt;li&gt;Coupling on the DB Schema - changes that require DB change still risk the higher SLO&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reader with Preprocessing and Enrichment Pattern
&lt;/h2&gt;

&lt;p&gt;Preprocessing is reading data from multiple tables and creating a new derived table to support read operations. For instance, consider a product catalog preprocessing the products, categories and variants tables into a single product-read table, from which all product information can be read by key.&lt;/p&gt;

&lt;p&gt;Enrichments are a type of processing that adds data from other services to the current service data on reads. For example, consider enriching a product with inventory quantity or the association of product with categories and taxonomies (assuming categories and inventory are managed on separate services).&lt;/p&gt;

&lt;p&gt;The default RWP service will call the other services on reads to enrich the product information, which means reducing reliability and increasing latency..&lt;/p&gt;

&lt;p&gt;The Reader with Preprocessing and Enrichment Pattern mandates that on reads, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The service does a simple SQL query to get the data, most commonly by primary key. The writer, on getting an insert or update operation, after updating the normalized table, also updates the derived preprocessed table for the reader.&lt;/li&gt;
&lt;li&gt;The service does not call any other service. Instead, the enrichments are happening as part of the proceeding on the Writer / Processor service. The Writer, on getting an insert or update operation, calls other services, creates the enriched data and saves it in the database.&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2F4mgi1r0y0rvk1v1b6ekk.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%2Fuploads%2Farticles%2F4mgi1r0y0rvk1v1b6ekk.png" alt="Reader with Preprocessing and Enrichment Pattern" width="477" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One has to ask what happens when the enrichment data changes? For instance, when inventory data changes (due to a purchase or new stock), or due to a change in categories?&lt;/p&gt;

&lt;p&gt;First, we note that both inventory and categories for a product are “&lt;strong&gt;slowly changing data&lt;/strong&gt;”, that is, data that changes a few times a day, at most a few times an hour, but is not interactive data. This allows us to reverse the update flow, and have the inventory and categories systems notify the product catalog Writer / Processor service to re-enrich the products, so that the reader will have them ready when needed.&lt;/p&gt;

&lt;p&gt;The generic rule is that &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preprocessing (without enrichment) applies to eventually consistent data (for which we can regain consistency, see below).&lt;/li&gt;
&lt;li&gt;Enrichment preprocessing only applies for slowly changing data, such that it is possible to process it beforehand on update triggers (data change events).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Second, did the system lose consistency due to not actively checking on reading the inventory? We claim it did not, as it was not consistent in the first place. Consider the full system includes the client (using a browser or mobile app) who sees the product from the catalog and the availability to purchase. Between the time of seeing the product and adding it to the cart the inventory can change again and again. As a result, the only consistent inventory check has to be done on checkout, on order creation (or reservation logic, if available).&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolated Reader
&lt;/h2&gt;

&lt;p&gt;The Isolated Reader pattern is a variation of the Read pattern and the Reader with Enrichment pattern to decouple the dependency on the database, decoupling both risk of change and risk of load and latency sourced at the shared database. In addition, the pattern simplifies the database queries on reads to become trivial queries, again improving both reliability and latency.&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.amazonaws.com%2Fuploads%2Farticles%2Fo14c5a94n7z3lejrhox6.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%2Fuploads%2Farticles%2Fo14c5a94n7z3lejrhox6.png" alt="Isolated Reader Diagram" width="633" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the Isolated Reader pattern, the Writer / Processor service and database hold the canonical data structure, while the Reader database holds the enriched, simplified and indexed data prepared for reads.&lt;/p&gt;

&lt;p&gt;The Writer / Processor service, on a write / update / delete operation, first writes to the canonical database. Then, it triggers a process to compute the reader database data and update the reader database.&lt;/p&gt;

&lt;p&gt;For instance, in the product catalog example, the writer / processor may have tables of products with relations to product options, brands, categories, etc. It can be built as a normalized table with relationships, constraints and whatever makes sense.&lt;/p&gt;

&lt;p&gt;The product catalog Reader products table will be a single table, with all the references materialized, including enrichment from other services such as the inventory data.&lt;/p&gt;

&lt;p&gt;The Isolated Reader Pattern extends the Reader with Preprocessing and Enrichment Pattern by isolating the database hardware in addition to the microservices and data schema, decoupling risk of change and load of the database itself. It is the most efficient, reliable and fast read pattern, excluding additional layers such as cache.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 3 - Microservices Patterns</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:26 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93</guid>
      <description>&lt;p&gt;In the third part of the Microservices Reliability Playbook, we explore how to build reliable microservices systems using our understanding of how to predict reliability.  &lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk"&gt;Introduction to Risk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Introduction to Microservices Reliability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microservices Patterns&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ideal system, and in fact the only system how meets the five-nines target, is the following&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.amazonaws.com%2Fuploads%2Farticles%2Fnt42ndkr8zc3lr5uruhb.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%2Fuploads%2Farticles%2Fnt42ndkr8zc3lr5uruhb.png" alt="Ideal system with one service and one database" width="150" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obviously, the ideal system looks like a monolithic system!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, are microservices the wrong choice? Actually, no. Microservices mitigate other types of risk, such as risk of change and reducing blast radius in case of a problem. Microservices solve an organizational problem of multiple teams working concurrently and independently. &lt;/p&gt;

&lt;p&gt;So the next question is how do we regain reliability with a microservices architecture? Here comes microservices patterns!&lt;/p&gt;

&lt;h2&gt;
  
  
  Single Read / Write / Process (RWP) Service Pattern
&lt;/h2&gt;

&lt;p&gt;The baseline - classic micro service&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.amazonaws.com%2Fuploads%2Farticles%2Fj3whekz5oxglvzcqzaq6.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%2Fuploads%2Farticles%2Fj3whekz5oxglvzcqzaq6.png" alt="classic microservice with database and external service calls" width="285" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This type of system couples risk of change and risk of load and latency all into one process. A write operation may prevent a read operation due to load, or a change in write or processing logic can cause read operations to fail, or vice versa.&lt;/p&gt;

&lt;p&gt;Considering such a system that, for example, during read or write operations, the processing is calling another 10 microservices (transitively), the system reliability drops as per the above formula for predicting reliability.&lt;/p&gt;

&lt;p&gt;For instance, with a product catalog service, the additional calls can be to validate a write, enrich the catalog with inventory or other information, categorization, etc.&lt;/p&gt;

&lt;p&gt;This is the simplest and most straightforward way of building a micro-service and that is a good starting point for talks on increasing reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Microservice Patterns
&lt;/h2&gt;

&lt;p&gt;When considering microservice patterns, the most common concept is that of CRUD services, which support reading (R) and writing data (CUD). However, we have to keep in mind that services commonly also process data, such that whatever is read from their database or other services is processed before a read operation. The processing can be sync or asynchronous.&lt;/p&gt;

&lt;p&gt;For this discussion we define Read / Write / Process (RWP) as a service that supports data written into it, the data can be processed by the same service and by fetching data from services (enrichments) and supports reading the processed and enriched data.&lt;/p&gt;

&lt;p&gt;We categorize the patterns into 4 groups - Read Patterns, Write Patterns, Multi-Service Patterns and Call Patterns. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read Patterns&lt;/strong&gt; focus on how to read data in a reliable and fast way, given constraints such as multi-service reads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write Patterns&lt;/strong&gt; focus on how to write data in a reliable way, including writing to multiple microservices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Service Patterns&lt;/strong&gt; combine both reader and writers to larger and more complex systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Call Patterns&lt;/strong&gt; focus on improving reliability of a single network call, such as retry and cache.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Optimize for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Single RWP Service&lt;/td&gt;
&lt;td&gt;Simplicity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;Reader&lt;/td&gt;
&lt;td&gt;High reliability, any database schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;Reader with Preprocessing and Enrichments&lt;/td&gt;
&lt;td&gt;High reliability, simple database schema, preventing other service calls during reads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;Isolated Reader&lt;/td&gt;
&lt;td&gt;High reliability, non-simple database schema, enrichments. This is the most reliable and fast reader pattern.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;Writer&lt;/td&gt;
&lt;td&gt;High reliability and fast consistent writes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;Write with a Queue&lt;/td&gt;
&lt;td&gt;Decouple data processing from writes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write&lt;/td&gt;
&lt;td&gt;Multi-Writer&lt;/td&gt;
&lt;td&gt;Multi-service writes and processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-Service&lt;/td&gt;
&lt;td&gt;Command Query Responsibility Segregation (CQRS)&lt;/td&gt;
&lt;td&gt;High reliability and fast consistent writes &amp;amp; High reliability and fast reads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-Service&lt;/td&gt;
&lt;td&gt;Split by SLO&lt;/td&gt;
&lt;td&gt;Focused high reliability for sub-systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call&lt;/td&gt;
&lt;td&gt;Pass Through Cache&lt;/td&gt;
&lt;td&gt;Improve latency and reduce load from downstream system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call&lt;/td&gt;
&lt;td&gt;Retry&lt;/td&gt;
&lt;td&gt;Overcome random network failures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call&lt;/td&gt;
&lt;td&gt;Fallback&lt;/td&gt;
&lt;td&gt;High reliability by expecting failure and having contingency plan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call&lt;/td&gt;
&lt;td&gt;Circuit Breaker&lt;/td&gt;
&lt;td&gt;Detecting failure and preventing load on failed system&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Next: Read the details of the patterns in&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 2 - Introduction to Microservices Reliability</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:20 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6</guid>
      <description>&lt;p&gt;Microservices is an architectural style that breaks down an application into small, independent services that communicate with each other using well-defined APIs. These services are designed to be loosely coupled, meaning they can be developed, deployed, and scaled independently. In essence, a microservices architecture is about building applications as a collection of small, independent services that work together to achieve a larger goal.&lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk"&gt;Introduction to Risk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Introduction to Microservices Reliability&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first question being asked about micro services is how large should they be? A single function? A single file? A persistent entity and its APIs? A logical Module? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The simplest answer is that a microservice is as large as the team managing it&lt;/strong&gt;. One team can own multiple micro services, but one micro service can be owned by only one team.&lt;/p&gt;

&lt;p&gt;To understand this statement, one just reviews the risk of change above. If a microservice gets contributions from two or more teams, in order to release the microservice both teams have to synchronize on changes to the microservices and have all changes in a state of done. There is an added risk that one team deploys (for example, due to a hot fix) while another team change is not done, and by deploying introducing a bug.&lt;/p&gt;

&lt;p&gt;But is that the only rule for microservices size? Actually no, there is another rule that will cause a team to have multiple microservices - managing blast radius, or the SLO (service level objectives) of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Level Objectives
&lt;/h2&gt;

&lt;p&gt;Before diving into Reliability of microservices, let's review how we define service level objectives for a software component. SLO is composed of 4 definitions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Availability&lt;/strong&gt; - the ability of a system to give a response, including an error response. A client calling a system and receiving a timeout (from the system, or the client decides to stop waiting), for that client the system is not available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency&lt;/strong&gt; - the time it takes to get a response, including an error response. Do note that latency turns into an availability problem once the client or some intermediate communication element decides to stop waiting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error rate&lt;/strong&gt; - when the system gives an error that is not the fault of the client. We are talking about HTTP 500s type of errors. To be clear - HTTP 400s errors, such as a client accessing unauthorized API and getting an error should not be counted as part of this error rate - this error rate captures the inability of a system to fulfill a valid request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correctness&lt;/strong&gt; - the ability of a system to give a correct response. For example, we expect the add API to return 2 for 1+1. If it returns any other number, the response is not correct. Normally, when a system is not able to return a correct response, we say it has a bug.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All the above should be measured on a per request basis, not on a time basis. The reason is that software systems do not have the same load at all times, and using time basis gives more weight to the low load periods. Take that to the extreme - a system that is up and running idle 24x7, yet gets 10 calls in one minute and fails all of them, is it 99% available (according to time basis) or 0% available (according to request basis)? &lt;/p&gt;

&lt;p&gt;For this discussion, we define &lt;strong&gt;reliability as SLO availability * (1 - error rate)&lt;/strong&gt; and measure it with the x-nines measure, or percent of operations that succeed. Five-nines means that 99.999% of the operations succeed.&lt;/p&gt;

&lt;p&gt;As stated in the previous section, we define reliability as&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.amazonaws.com%2Fuploads%2Farticles%2Fw53xyle7jhj9217kdvdq.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%2Fuploads%2Farticles%2Fw53xyle7jhj9217kdvdq.png" alt="reliability equals availability times (1 - error rate)" width="543" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reliability is not a global attribute of the system - instead, it is an attribute of each independent API of the system&lt;/strong&gt;. A system with 50 APIs has 50 reliability scores, one for each API. &lt;/p&gt;

&lt;p&gt;Side note - the above statement depends on how we define an API. If we have an API “do anything”, which performs multiple different actions based on different inputs, it is not very beneficial to measure its reliability as one API. In such a case, we can measure reliability per API and key API inputs which determine which action to perform. Consider an API such as run task, which gets a task id as an input - as different tasks can be quite different, it makes sense to compute reliability per task and not just per the API.&lt;/p&gt;

&lt;p&gt;To measure reliability, one has to monitor each API for availability (when it is called and does not answer in a reasonable time) and error rate (when it answers with uncalled for error). &lt;/p&gt;

&lt;p&gt;For example, an API with 10,000 calls during a day, of which &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;40 calls have failed to reach the API&lt;/li&gt;
&lt;li&gt;100 calls have reached the API and timed out&lt;/li&gt;
&lt;li&gt;200 calls returned a 5XX error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API reliability is then 1 - 340/10000 = 1 - 0.034 = 9.964%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Predicting Reliability
&lt;/h2&gt;

&lt;p&gt;Reliability of a distributed system can be predicted based on only two measures of the system itself, which factor in the risks of Load and Latency and the risk of Change. Those two measures enable architects, developers and managers to predict the reliability of a system, or the impact of a change to the system on the system reliability.  &lt;/p&gt;

&lt;p&gt;The risks of security incidents and malfunctions depend on external elements and cannot be predicted from examining the distributed system itself. &lt;/p&gt;

&lt;p&gt;The two measures are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Number of Network hops&lt;/strong&gt;: The number of network calls between services, up to data persistence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Number of Artifacts&lt;/strong&gt;: The number of releasable software artifacts involved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reliability can be predicted using the two above measures by &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.amazonaws.com%2Fuploads%2Farticles%2F7dtc3se3h8r0ejc766i9.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%2Fuploads%2Farticles%2F7dtc3se3h8r0ejc766i9.png" alt="predicted reliability = (load and latency reliability) in the power of (number of network hops) times (change reliability) in the power of (number of artifacts)" width="496" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given we can assume the single network call reliability is five-nines or 0.99999%, and that Change Reliability per artifact is also five-nines, or 0.99999%, the model formula simplifies to &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.amazonaws.com%2Fuploads%2Farticles%2Fr7b9i5x8a5bg654sfjwl.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%2Fuploads%2Farticles%2Fr7b9i5x8a5bg654sfjwl.png" alt="predicted reliability = (0.99999) in the power of (number of network hops) times (0.99999) in the power of (number of artifacts)" width="522" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or simplified to&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.amazonaws.com%2Fuploads%2Farticles%2Fqwkhgi53g8n8n7u85bmu.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%2Fuploads%2Farticles%2Fqwkhgi53g8n8n7u85bmu.png" alt="predicted reliability = (0.99999) in the power of (number of network hops plus number of artifacts)" width="418" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of Predicted Reliability
&lt;/h3&gt;

&lt;p&gt;Let’s consider a toy model of a commerce cart, that includes multiple services - &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A cart service, owning the line items and cart totals calculation&lt;/li&gt;
&lt;li&gt;A product catalog&lt;/li&gt;
&lt;li&gt;A tax service, which calculates the tax depending on the items in the cart&lt;/li&gt;
&lt;li&gt;A shipment service, which calculates the tax depending on the items in the cart&lt;/li&gt;
&lt;li&gt;A coupon service, which validates coupons added to the cart and assess their value and applicability to the cart items&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In addition, our micro services system has non functionals for access control and quota. &lt;br&gt;
We also assume each micro service has a database, and each call to a micro service includes one query to the database.&lt;/p&gt;

&lt;p&gt;Our system looks kind of like the following:&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.amazonaws.com%2Fuploads%2Farticles%2F1zbdpt416bypgtv12vi5.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%2Fuploads%2Farticles%2F1zbdpt416bypgtv12vi5.png" alt="network diagram of the example ecomm microservices system" width="595" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now, let's examine the transaction to load the cart data for display, including the line items and total price.&lt;/p&gt;

&lt;p&gt;The number of artifacts involved is 7 (with micro services we count the database as part of the micro service deployment unit).&lt;/p&gt;

&lt;p&gt;The number of network calls is 35&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 Cart to Cart DB&lt;/li&gt;
&lt;li&gt;6 Cart to other micro services + 6 each micro services to their DB&lt;/li&gt;
&lt;li&gt;8, from 4 micro services to 2 micro services (from Product Catalog, Tax calculator, shipping calculator &amp;amp; coupons to Access Control &amp;amp; Quotas) + 8 for ACL and Quotas DB Access &lt;/li&gt;
&lt;li&gt;3 additional calls to product catalog from Tax calculator, Shipping Calculator and coupons + 3 calls to product catalog DB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Using our formula, the predicted reliability of the system is 0.99999^(35+7) = 0.9995 or 99.95%&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring Microservices
&lt;/h2&gt;

&lt;p&gt;Ok, we have defined how to predict the reliability of a system only using the number of network calls and artifacts. But what is the best way to monitor and create alerts on the system such that we know if we have a problem and can react fast?&lt;/p&gt;

&lt;p&gt;Our first intuition is to set an alert every minute (or so) at an error rate of 1-5%. &lt;/p&gt;

&lt;p&gt;But does it help? Does it guarantee we keep the SLO we aim for, be it 3-9s (99.9%),  4-9s (99.99%) or above? At the same time, does it cause too much unnecessary noise? How do we balance alerting?&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended Alerts Strategy
&lt;/h3&gt;

&lt;p&gt;We note there are different kinds of risks which have different error patterns. Risk of change tends to cause short periods of high error rate, which we want to detect early. Risk of load and latency tends to create a constant error rate that can slightly increase or decrease depending on many factors. We want to factor both and still detect risk of change errors fast without false positives.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We remind that reliability is defined per API, and as such to be measured per API individually, based on the number of calls to the API. &lt;/li&gt;
&lt;li&gt;We want to implement, per API, a measure of 

&lt;ol&gt;
&lt;li&gt;Number of calls &lt;/li&gt;
&lt;li&gt;Number of errors&lt;/li&gt;
&lt;li&gt;Latency p50, p95, p99, p999 (percentails 50, 95, 99, 99.9)&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;We need to define what the latency limit is. Any API call latency above this threshold is considered also an error. 

&lt;ol&gt;
&lt;li&gt;This threshold has to be below the timeout limit, which is considered an error by default.&lt;/li&gt;
&lt;li&gt;or semantic threshold at which the API returns a regular response while logging the latency as an error. &lt;/li&gt;
&lt;li&gt;For most API, this threshold can be at around x10 of the mean latency, or x2-x3 of the p90 latency. &lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;We want a fast alert at a lower threshold, set as

&lt;ol&gt;
&lt;li&gt;One minute interval for high traffic APIs&lt;/li&gt;
&lt;li&gt;Moving average over 5 minutes, computed every minute for lower traffic APIs&lt;/li&gt;
&lt;li&gt;With error rate limit of about 5-10%&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;We want a slow alert at a higher threshold, set as

&lt;ol&gt;
&lt;li&gt;One day interval, or&lt;/li&gt;
&lt;li&gt;One week moving average, computed daily&lt;/li&gt;
&lt;li&gt;At almost the SLO target limit (for 4-9s, we set error rate at ~0.001%)&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The latency threshold is intended to detect momentary load and latency risk effects - if an API latency becomes considerably larger but does not reach the timeout threshold.&lt;/li&gt;
&lt;li&gt;The fast alert is intended to detect risk of change effects - if some changes cause the service to fail, we want fast feedback.&lt;/li&gt;
&lt;li&gt;The slow alert is intended to detect load and latency risk effects - gradual degradation over time, or a buildup of errors over time. By setting a threshold that is close to the required SLO we can both detect early and have time to react and fix. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next: &lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Reliability Playbook, Part 3 - Microservices Patterns&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Microservices Reliability Playbook, Part 1 - Introduction to Risk</title>
      <dc:creator>Yoav Abrahami</dc:creator>
      <pubDate>Sun, 04 May 2025 08:53:13 +0000</pubDate>
      <link>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk</link>
      <guid>https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-1-introduction-to-risk-2mbk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;When you have a monolith, you’ve got one big problem to solve. Switch to microservices, and now you’ve got 99 smaller problems—plus a distributed system. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maintaining reliability with microservices distributed systems are challenging. This playbook explores the risks involved, the theory why, how to measure, alert and predict reliability and how to mitigate using architectural patterns.&lt;/p&gt;

&lt;p&gt;Microservices Reliability Playbook&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction to Risk&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Introduction to Microservices Reliability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-3-microservices-patterns-5f93"&gt;Microservices Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-4-read-patterns-3djo"&gt;Read Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-5-write-patterns-102p"&gt;Write Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-6-multi-service-patterns-mgl"&gt;Multi-Service Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-7-call-patterns-3021"&gt;Call Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://yoav68.wixstudio.com/playbook/_functions/microservices_reliability_playbook" rel="noopener noreferrer"&gt;Download the full Playbook at a free PDF&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I first learned about microservices in 1998. Yes, a quick search will reveal microservices as a name was introduced in 2011-12, attributed to &lt;strong&gt;Martin Fowler&lt;/strong&gt; and &lt;strong&gt;James Lewis&lt;/strong&gt;. Yet, in 1998 I read a book by &lt;strong&gt;James R. Callan&lt;/strong&gt; about collaborative computing from which I learned all about microservices, 13 years before they were named.&lt;/p&gt;

&lt;p&gt;I joined Wix in 2010 to figure out what the iTab is and how the company's product can work on mobile. However, by the end of the year I have transitioned to join the team building Wix Infrastructure with &lt;strong&gt;Eugene Olshenbaum&lt;/strong&gt;, &lt;strong&gt;Aviran Mordo&lt;/strong&gt; and the rest of Wix Engineering. &lt;/p&gt;

&lt;p&gt;With this work, we will explore why we should be using microservices, how large they should be, what are the risk factors when using microservices, how to mitigate those risks, how to monitor microservices and guidelines to build reliable microservices systems.&lt;/p&gt;

&lt;p&gt;To understand microservices, we first need to understand how they evolved. In the 90s, we have been using what is now called 2 tier applications - a desktop application connected to a central database (it was before the time of web or mobile applications). &lt;/p&gt;

&lt;p&gt;Those desktop applications had to contain all the functionality, from all the UI to all the business logic, and in some cases database migration logic (for lazy migrations). Developing those applications was very productive using tools like Visual Basic, Delphi and later C#.&lt;/p&gt;

&lt;p&gt;However, as the application grows and the number of developers grows to over 10, the effects of working in a monolith emerge - different teams are not ready at the same time, efforts for merging work, different assumptions on the database, etc.&lt;/p&gt;

&lt;p&gt;Late 90s and the early 2000s, we moved to 3-tier applications, placing a server between the desktop application and the database. This server decoupled the business logic from the UI, allowing for two teams to work in parallel. Yet, with application and complexity growth, it was clear we need a more robust pattern.&lt;/p&gt;

&lt;p&gt;From the mid to late 2000s, the shift to web applications created modular client applications, as each web page is independent. Microservices emerged at the same time to decouple backend development and enable scaling the team, as well as create smaller blast radii in case of a problem.&lt;/p&gt;

&lt;p&gt;But what is the underlying cause for those shifts and what are we solving? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Risk!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Risks in Software
&lt;/h2&gt;

&lt;p&gt;Risk in software is defined as the chance that given a deployed software system will fail to function, due to any reason. There are 4 types of risks for software systems&lt;/p&gt;

&lt;h3&gt;
  
  
  Malfunctions
&lt;/h3&gt;

&lt;p&gt;Malfunctions happen when some infrastructure breaks, such as the hardware, network, electricity, the cloud provider has an outage or similar. Obviously, if such a thing happens, our software system will fail to function.&lt;/p&gt;

&lt;p&gt;Some Software systems are designed to be resilient to malfunctions (most notably IP networks) by deploying adaptive routing algorithms and making a design decision of no global true state.&lt;/p&gt;

&lt;p&gt;In most cases, when building software systems we assume our infrastructure is reliable, or we handle malfunctions using availability zones or multiple regions (for cloud applications) and multiple data centers (for on prem systems) and switching from one to the other in case of malfunction. &lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;Risk from security incidents is the risk of someone, employee or a 3rd party, going into the system and preventing it from working, partially or as a whole. Ransomware attacks are just one such example.&lt;/p&gt;

&lt;p&gt;Another type of security risk is data breaches, at which someone uses a software or access vulnerability to steal data or proprietary information.&lt;/p&gt;

&lt;p&gt;Malicious users can also abuse a system, using it for unintended intents such as attacking other systems, impersonating, consuming unintended resources, etc.&lt;/p&gt;

&lt;p&gt;Normally, security teams deploy different measures to prevent those types of risks, which we will not expand on in this playbook.&lt;/p&gt;

&lt;h3&gt;
  
  
  Change
&lt;/h3&gt;

&lt;p&gt;The risk of change is the risk caused when a team of developers deploy a software change. With the change, on every deployment, they have a chance to &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduce a bug&lt;/li&gt;
&lt;li&gt;Introduce a breaking change some other component is not ready for (dependencies)&lt;/li&gt;
&lt;li&gt;Introduce additional CPU / IO / memory load the deployment is not ready for (application load)&lt;/li&gt;
&lt;li&gt;Broken deployment&lt;/li&gt;
&lt;li&gt;Adversely affect other components in other systems which may seem unrelated to the original deployment (also denoted as blast radii of the failure)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the type of risk microservices aim to solve.&lt;/p&gt;

&lt;p&gt;We can calculate the reliability due to risk of change of a component using the following formula: &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.amazonaws.com%2Fuploads%2Farticles%2Feb8ho8n916fas7z3tnfi.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%2Fuploads%2Farticles%2Feb8ho8n916fas7z3tnfi.png" alt="Formula of risk of change due to change - 1 minus (the time to detect and fix) times (percent of deployments with a problem) times (the blast radius) divided by (period of time between deployments)" width="625" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;“Percent of deployments with a problem” - can be mitigated using methodologies like TDD (test driven development), lab deployments and manual QA.&lt;/li&gt;
&lt;li&gt;“Blast radii” - is given a problem, how much of the overall system is affected? &lt;/li&gt;
&lt;li&gt;“Time to detect and fix a problem” - can be mitigated using modern monitoring and alerting tools as well as having fast automated deployment pipeline&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Microservices aims to reduce the “blast radius” of a problem. Continuous Delivery aims to reduce the size of a change and those reduce the “percent of deployments with a problem” as well as the “blast radius”. Overall, both reduce the risk of change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load and Latency
&lt;/h3&gt;

&lt;p&gt;The risk from load and latency is the risk that given two processes (two microservices, server and database, client and server, or any other two), the call from the first to the second will delay up to a timeout due to different loads and latencies in the places we do not see.&lt;/p&gt;

&lt;p&gt;To understand load and latency, one just needs to consider what happens between two adjacent cloud hosts - which appears virtually to be side by side. The reality is they are probably on different locations in the cloud data center, and the packets get translated from the virtual network IP address to the physical network IP address, goes through a switch, a few routers, a switch again, target network stack and process. All the devices and layers deploy queues for load management, which most of the time offer quick response, yet sometimes offer really slow response. &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.amazonaws.com%2Fuploads%2Farticles%2F5phval7g8r14xk8mljkp.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%2Fuploads%2Farticles%2F5phval7g8r14xk8mljkp.png" alt="Network Stack Diagram" width="632" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result is similar to a &lt;a href="https://en.wikipedia.org/wiki/Log-normal_distribution" rel="noopener noreferrer"&gt;Log-Normal distribution&lt;/a&gt; with a cutoff after which higher latency numbers have higher probability due to how queues are working. In this work we use a model based on Log-Normal distribution (μ=0.5, 𝝈=0.7) with a cutoff at 20ms, which effectively gives five-nines network (latency probability of 0.99999 to be below 20ms). The probability is visualized below.&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.amazonaws.com%2Fuploads%2Farticles%2Fw44keolxn800bzs8n1j2.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%2Fuploads%2Farticles%2Fw44keolxn800bzs8n1j2.png" alt="The probability of Network Latency on Public Networks" width="652" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To summarize load and latency risk, two micro services communicate at a five-nines reliability, but will fail to communicate at 0.00001 probability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next: &lt;a href="https://dev.to/yoav_abrahami_736759c4edd/microservices-reliability-playbook-part-2-introduction-to-microservices-reliability-22k6"&gt;Microservices Reliability Playbook, Part 2 - Introduction to Microservices Reliability&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>sre</category>
      <category>reliability</category>
    </item>
  </channel>
</rss>
