<?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: Oleksandr Kashytskyi</title>
    <description>The latest articles on DEV Community by Oleksandr Kashytskyi (@oleksandr_kashytskyi_a630).</description>
    <link>https://dev.to/oleksandr_kashytskyi_a630</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%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg</url>
      <title>DEV Community: Oleksandr Kashytskyi</title>
      <link>https://dev.to/oleksandr_kashytskyi_a630</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oleksandr_kashytskyi_a630"/>
    <language>en</language>
    <item>
      <title>Ever seen a docker-compose.test.yml that's just a full copy of docker-compose.yml? I wrote a short guide on fixing that with one shared base file, extends and profiles, so a new environment is a few lines instead of a copy-paste. Full code inside, ready to</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Tue, 13 Oct 2026 10:27:53 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/ever-seen-a-docker-composetestyml-thats-just-a-full-copy-of-docker-composeyml-i-wrote-a-short-49g2</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/ever-seen-a-docker-composetestyml-thats-just-a-full-copy-of-docker-composeyml-i-wrote-a-short-49g2</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme" class="crayons-story__hidden-navigation-link"&gt;Efficent usage of Docker&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="/oleksandr_kashytskyi_a630" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg" alt="oleksandr_kashytskyi_a630 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/oleksandr_kashytskyi_a630" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Oleksandr Kashytskyi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Oleksandr Kashytskyi
                
                
              
              &lt;div id="story-author-preview-content-2292911" 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="/oleksandr_kashytskyi_a630" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Oleksandr Kashytskyi&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/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 13&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/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme" id="article-link-2292911"&gt;
          Efficent usage of Docker
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/architecture"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;architecture&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/docker"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;docker&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/softwareengineering"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwareengineering&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/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              2&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&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;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>automation</category>
      <category>devops</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Efficent usage of Docker</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Tue, 13 Oct 2026 10:24:19 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/efficent-usage-of-docker-2pme</guid>
      <description>&lt;p&gt;I've seen this more than once, even on production projects. Somebody needs a test environment, so they create &lt;code&gt;docker-compose.test.yml&lt;/code&gt;, copy the whole &lt;code&gt;docker-compose.yml&lt;/code&gt; into it, and declare every service again from scratch.&lt;/p&gt;

&lt;p&gt;Ctrl+C and Ctrl+V are great shortcuts, until they end up in your infrastructure. Sooner or later the copies drift apart: one file gets a Postgres upgrade, the other doesn't, and your tests happily pass against a database version you don't actually run.&lt;/p&gt;

&lt;p&gt;Docker Compose can do much better with two features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A shared base file&lt;/strong&gt;: every service is declared once and reused with &lt;code&gt;extends&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profiles&lt;/strong&gt;: one &lt;code&gt;docker-compose.yml&lt;/code&gt; holds all environments, and you choose which one to start.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add one env file per environment and a well-chosen &lt;code&gt;command&lt;/code&gt;, and adding a new environment becomes a few lines instead of a full copy-paste.&lt;/p&gt;

&lt;p&gt;The snippets are simplified from my side project, &lt;a href="https://github.com/kot-1999/flowers_shop_be" rel="noopener noreferrer"&gt;a flower shop backend&lt;/a&gt;, but the pattern works for any stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The full setup&lt;/li&gt;
&lt;li&gt;How to run it&lt;/li&gt;
&lt;li&gt;The shared base file&lt;/li&gt;
&lt;li&gt;Profiles&lt;/li&gt;
&lt;li&gt;Env files&lt;/li&gt;
&lt;li&gt;The command key&lt;/li&gt;
&lt;li&gt;Try it yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The full setup
&lt;/h2&gt;

&lt;p&gt;Here's everything at once, then we'll take it apart piece by piece. The example is a Node.js app with PostgreSQL and MailHog (a fake SMTP server that catches outgoing emails).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── docker-compose.base.yml   # shared service settings
├── docker-compose.yml        # environments: dev and test
├── .env.dev
└── .env.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;docker-compose.base.yml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:22.12.0&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${PORT}:${PORT}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./:/usr/src/app&lt;/span&gt;
    &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/src/app&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:17.3&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PORT}:${POSTGRES_PORT}&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=${POSTGRES_DB}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=${POSTGRES_PASSWORD}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PGPORT=${POSTGRES_PORT}&lt;/span&gt;

  &lt;span class="na"&gt;mailhog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mailhog/mailhog&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${EMAIL_SMTP_PORT}:${EMAIL_SMTP_PORT}&lt;/span&gt;  &lt;span class="c1"&gt;# SMTP&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${EMAIL_HTTP_PORT}:${EMAIL_HTTP_PORT}&lt;/span&gt;  &lt;span class="c1"&gt;# web UI&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MH_SMTP_BIND_ADDR=0.0.0.0:${EMAIL_SMTP_PORT}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MH_UI_BIND_ADDR=0.0.0.0:${EMAIL_HTTP_PORT}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MH_API_BIND_ADDR=0.0.0.0:${EMAIL_HTTP_PORT}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;docker-compose.yml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dev_app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.base.yml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env.dev&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev_postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mailhog&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sh -c "npm ci &amp;amp;&amp;amp; npm run start"&lt;/span&gt;

  &lt;span class="na"&gt;test_app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.base.yml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env.test&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test_postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mailhog&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sh -c "npm ci &amp;amp;&amp;amp; npm test"&lt;/span&gt;

  &lt;span class="na"&gt;dev_postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.base.yml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./docker/pgdata:/var/lib/postgresql/data&lt;/span&gt;

  &lt;span class="na"&gt;test_postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.base.yml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;tmpfs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/lib/postgresql/data&lt;/span&gt;

  &lt;span class="na"&gt;mailhog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.base.yml&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mailhog&lt;/span&gt;
    &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;.env.dev&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NODE_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000
&lt;span class="nv"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev_secret

&lt;span class="nv"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;54321
&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;development
&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin
&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres
&lt;span class="nv"&gt;POSTGRES_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql://admin:postgres@dev_postgres:54321/development

&lt;span class="nv"&gt;EMAIL_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mailhog
&lt;span class="nv"&gt;EMAIL_SMTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1025
&lt;span class="nv"&gt;EMAIL_HTTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8025
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;.env.test&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NODE_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3001
&lt;span class="nv"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;test_secret

&lt;span class="nv"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;54322
&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql://test:test@test_postgres:54322/test

&lt;span class="nv"&gt;EMAIL_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mailhog
&lt;span class="nv"&gt;EMAIL_SMTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1025
&lt;span class="nv"&gt;EMAIL_HTTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8025
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to run it
&lt;/h2&gt;

&lt;p&gt;One command per environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Development&lt;/span&gt;
docker compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.dev &lt;span class="nt"&gt;--profile&lt;/span&gt; dev up

&lt;span class="c"&gt;# Tests&lt;/span&gt;
docker compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.test &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;up &lt;span class="nt"&gt;--exit-code-from&lt;/span&gt; test_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole interface. Now let's see why it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shared base file
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker-compose.base.yml&lt;/code&gt; describes each service once, with only the settings that are the same in every environment: image, ports, volumes and basic configuration. There are no profiles, no names and no commands in it. It's not meant to be started on its own; it's a library of building blocks.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt; then builds the real services from those blocks with &lt;code&gt;extends&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dev_postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose.base.yml&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
  &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dev_postgres&lt;/code&gt; gets everything from the base &lt;code&gt;postgres&lt;/code&gt; service and adds only what makes it different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why bother:&lt;/strong&gt; the Postgres version, ports and settings now live in exactly one place. Upgrade the image once and every environment gets it. No more "which file is the right one?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; with &lt;code&gt;extends&lt;/code&gt;, profiles and env files combined, it can be hard to see what Compose will actually run. &lt;code&gt;docker compose config&lt;/code&gt; prints the final merged result with all variables filled in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.dev &lt;span class="nt"&gt;--profile&lt;/span&gt; dev config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Profiles
&lt;/h2&gt;

&lt;p&gt;A profile is a label on a service. When you run &lt;code&gt;docker compose --profile dev up&lt;/code&gt;, only services labelled &lt;code&gt;dev&lt;/code&gt; start:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Profile&lt;/th&gt;
&lt;th&gt;Starts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;dev_app&lt;/code&gt;, &lt;code&gt;dev_postgres&lt;/code&gt;, &lt;code&gt;mailhog&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;test_app&lt;/code&gt;, &lt;code&gt;test_postgres&lt;/code&gt;, &lt;code&gt;mailhog&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is what replaces the copy-pasted &lt;code&gt;docker-compose.test.yml&lt;/code&gt;. Both environments live in one file, side by side, and each one only adds what is actually different.&lt;/p&gt;

&lt;p&gt;A few decisions worth explaining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Postgres is per environment.&lt;/strong&gt; &lt;code&gt;dev_postgres&lt;/code&gt; mounts a folder, so my dev data survives restarts. &lt;code&gt;test_postgres&lt;/code&gt; keeps its data in memory (&lt;code&gt;tmpfs&lt;/code&gt;), so every test run starts with an empty database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MailHog is shared.&lt;/strong&gt; It's listed in both profiles, &lt;code&gt;dev&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt;. It doesn't care which environment sends an email; it catches everything and judges nobody.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;tmpfs&lt;/code&gt; and not just "no volume"?&lt;/strong&gt; My first version simply left the volume out, and that's not enough. The &lt;code&gt;postgres&lt;/code&gt; image declares its own volume, so Docker quietly creates one anyway. &lt;code&gt;--exit-code-from&lt;/code&gt; stops the containers but doesn't remove them, so the next &lt;code&gt;up&lt;/code&gt; starts the same container with the same data. A &lt;code&gt;tmpfs&lt;/code&gt; mount is wiped every time the container stops, so the reset happens only for tests and never touches your dev data. Easy to check: insert a row in one test run, run the exact same command again without &lt;code&gt;down&lt;/code&gt;, and the row should be gone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One gotcha:&lt;/strong&gt; a service &lt;em&gt;without&lt;/em&gt; a &lt;code&gt;profiles&lt;/code&gt; key starts with every profile. So give every service a profile, or you'll wonder why your test run also started something it shouldn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Env files
&lt;/h2&gt;

&lt;p&gt;Each profile gets its own env file: &lt;code&gt;.env.dev&lt;/code&gt; for &lt;code&gt;dev&lt;/code&gt; and &lt;code&gt;.env.test&lt;/code&gt; for &lt;code&gt;test&lt;/code&gt;. The compose files stay the same; only the values change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The variable names are identical in every environment.&lt;/strong&gt; Dev and test both have &lt;code&gt;PORT&lt;/code&gt;, &lt;code&gt;JWT_SECRET&lt;/code&gt;, &lt;code&gt;POSTGRES_URL&lt;/code&gt; and so on, just with different values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;.env.dev&lt;/th&gt;
&lt;th&gt;.env.test&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PORT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3000&lt;/td&gt;
&lt;td&gt;3001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;JWT_SECRET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;dev_secret&lt;/td&gt;
&lt;td&gt;test_secret&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POSTGRES_PORT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;54321&lt;/td&gt;
&lt;td&gt;54322&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POSTGRES_DB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;development&lt;/td&gt;
&lt;td&gt;test&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the structure of your config and secrets never changes, and your app never has to ask "which environment am I in?". It reads &lt;code&gt;process.env&lt;/code&gt; and gets on with life.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A new environment is a new env file plus a small edit.&lt;/strong&gt; Want &lt;code&gt;staging&lt;/code&gt;? Create &lt;code&gt;.env.staging&lt;/code&gt;, add a &lt;code&gt;staging_app&lt;/code&gt; and &lt;code&gt;staging_postgres&lt;/code&gt; that extend the base services, and give them a &lt;code&gt;staging&lt;/code&gt; profile. That's it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--env-file&lt;/code&gt; and &lt;code&gt;env_file&lt;/code&gt; are two different things.&lt;/strong&gt; They look almost the same but do different jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--env-file .env.dev&lt;/code&gt; on the command line fills in the &lt;code&gt;${...}&lt;/code&gt; placeholders &lt;em&gt;inside the compose files&lt;/em&gt;, like ports and passwords.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;env_file: .env.dev&lt;/code&gt; inside a service passes the variables &lt;em&gt;into the container&lt;/em&gt;, so the app can read them from &lt;code&gt;process.env&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this setup the app uses the same file for both, so everything about an environment lives in one place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The same port inside and outside.&lt;/strong&gt; A line like &lt;code&gt;${POSTGRES_PORT}:${POSTGRES_PORT}&lt;/code&gt; maps the host port to the same port inside the container. For that to work, the service has to listen on that port too, which is what &lt;code&gt;PGPORT&lt;/code&gt; does for Postgres and the &lt;code&gt;MH_*_BIND_ADDR&lt;/code&gt; variables do for MailHog. The result: one number per service, and dev and test never point at the same database.&lt;/p&gt;

&lt;p&gt;Keep the real env files out of git. They hold secrets, and your future self will thank you.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;command&lt;/code&gt; overrides what a container runs on start, and it's what lets one image do different jobs.&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;dev_app&lt;/code&gt; and &lt;code&gt;test_app&lt;/code&gt; use the plain &lt;code&gt;node&lt;/code&gt; image with the source code mounted in. No Dockerfile, no custom image to rebuild. The only difference is the command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dev_app&lt;/code&gt; runs &lt;code&gt;npm ci &amp;amp;&amp;amp; npm run start&lt;/code&gt; and keeps the server running.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test_app&lt;/code&gt; runs &lt;code&gt;npm ci &amp;amp;&amp;amp; npm test&lt;/code&gt;, then exits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two small things matter here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, not &lt;code&gt;;&lt;/code&gt;.&lt;/strong&gt; With &lt;code&gt;npm ci; npm test&lt;/code&gt;, the tests still run after a failed install and fail with a confusing error. &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; stops at the first failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--exit-code-from test_app&lt;/code&gt;&lt;/strong&gt; stops the containers when the tests finish (it doesn't remove them) and returns the tests' exit code. Your terminal (or CI) gets a clear pass or fail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, &lt;code&gt;depends_on&lt;/code&gt; only controls the start order. It doesn't wait until Postgres is actually ready to accept connections. In practice &lt;code&gt;npm ci&lt;/code&gt; is slow enough that Postgres is ready long before it finishes (finally, a use for slow installs). For a bulletproof setup, add a Postgres &lt;code&gt;healthcheck&lt;/code&gt; and use &lt;code&gt;condition: service_healthy&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Take any Node.js project with &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; scripts in &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add the four files from The full setup, and add &lt;code&gt;.env.dev&lt;/code&gt; and &lt;code&gt;.env.test&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Start development:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.dev &lt;span class="nt"&gt;--profile&lt;/span&gt; dev up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your app is on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, and every email it sends shows up at &lt;a href="http://localhost:8025" rel="noopener noreferrer"&gt;http://localhost:8025&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the tests:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.test &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;up &lt;span class="nt"&gt;--exit-code-from&lt;/span&gt; test_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clean up when you're done:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.dev &lt;span class="nt"&gt;--profile&lt;/span&gt; dev &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A full working example lives in my repo: &lt;a href="https://github.com/kot-1999/flowers_shop_be" rel="noopener noreferrer"&gt;kot-1999/flowers_shop_be&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Copy-paste is still allowed. Just not for your infrastructure. 😉&lt;/p&gt;

&lt;p&gt;How do you handle multiple environments with Docker Compose? Let me know in the comments.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>docker</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Product Maintainability - design principles and practices</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Sat, 24 May 2025 11:38:37 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/maintainability-45c8</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/maintainability-45c8</guid>
      <description>&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Main 3 Design Principles

&lt;ul&gt;
&lt;li&gt;Operability&lt;/li&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;Evolvability&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Additional Maintainability Practices

&lt;ul&gt;
&lt;li&gt;Code Readability&lt;/li&gt;
&lt;li&gt;Testing &amp;amp; Automation&lt;/li&gt;
&lt;li&gt;Decoupling Components&lt;/li&gt;
&lt;li&gt;Continuous Refactoring&lt;/li&gt;
&lt;li&gt;Monitoring &amp;amp; Logging&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Most of the total cost of software development and ownership is tied not to the initial build but to its maintenance. In fact, multiple industry studies, including those by IEEE and Gartner, indicate that &lt;strong&gt;60–80%&lt;/strong&gt; of a software system’s total lifecycle cost is spent on maintaining and evolving it. These costs encompass fixing bugs, enhancing functionality, adapting to new requirements, updating dependencies, and ensuring security compliance.&lt;/p&gt;

&lt;p&gt;A well-maintained software system is easier to operate, understand, and extend over time. This not only boosts productivity but also improves developer morale and reduces turnover. &lt;strong&gt;Software maintainability&lt;/strong&gt; is a key metric in software quality, and ensuring it requires a deliberate and thoughtful approach throughout the development lifecycle—from design to deployment.&lt;/p&gt;

&lt;p&gt;So let's check what can increase maintainability of our product!!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Main 3 Design Principles &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Operability &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Operability refers to how well the system supports day-to-day operations such as deployment, monitoring, and troubleshooting. A highly operable system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrates with monitoring tools (e.g., Prometheus, Datadog, Sentry)&lt;/li&gt;
&lt;li&gt;Has built-in health checks and metrics&lt;/li&gt;
&lt;li&gt;Supports automated recovery and graceful failure handling&lt;/li&gt;
&lt;li&gt;Enables fast incident diagnosis and resolution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Improving operability leads to lower Mean Time to Recovery (MTTR) and better system uptime, both of which are crucial for business continuity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplicity &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Simplicity aims to eliminate unnecessary complexity. Systems that are simpler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have clear responsibilities and minimal side effects&lt;/li&gt;
&lt;li&gt;Are easier to test, reason about, and modify&lt;/li&gt;
&lt;li&gt;Encourage consistent coding styles and patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As per software engineering research, &lt;strong&gt;complexity is the primary factor behind bugs and delayed development&lt;/strong&gt;. Tools like static analyzers, linters, and code review checklists can help enforce simplicity at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best tool for removing complexity is abstraction&lt;/strong&gt;. By encapsulating intricate logic behind well-defined interfaces, abstraction helps reduce cognitive load, prevent errors, and improve reusability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evolvability &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Evolvability ensures the system is ready to change and grow with new requirements. Key practices include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modular design and domain-driven boundaries&lt;/li&gt;
&lt;li&gt;Clear, stable APIs with versioning&lt;/li&gt;
&lt;li&gt;Backward compatibility and migration support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOTE: Except of backward compatibility there is forward compatibility, but it's implementation require very high skills and knowledge of the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Maintainability Practices &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Code Readability &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Readable code is easier to debug and extend. It involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear naming conventions&lt;/li&gt;
&lt;li&gt;Consistent formatting (e.g., via Prettier or Black)&lt;/li&gt;
&lt;li&gt;Logical structure and separation of concerns&lt;/li&gt;
&lt;li&gt;Inline comments and documentation for complex logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Surveys show that &lt;strong&gt;developers spend over 70% of their time understanding existing code&lt;/strong&gt;. Readable code is not a luxury—it's a necessity for long-term maintainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing &amp;amp; Automation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Automated tests form the backbone of a reliable system. Key strategies include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit tests to validate business logic&lt;/li&gt;
&lt;li&gt;Integration tests to catch cross-module bugs&lt;/li&gt;
&lt;li&gt;End-to-end tests for user-facing flows&lt;/li&gt;
&lt;li&gt;CI/CD pipelines for fast, reliable delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;According to Capers Jones, &lt;strong&gt;defect rates drop by 60–90%&lt;/strong&gt; in systems with strong test coverage and automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoupling Components &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Reducing interdependencies makes systems easier to change. Strategies include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applying microservice, service-oriented, or hexagonal architecture&lt;/li&gt;
&lt;li&gt;Using message queues or APIs for communication&lt;/li&gt;
&lt;li&gt;Defining clear interfaces and contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Organizations that adopt &lt;strong&gt;modular and decoupled architectures&lt;/strong&gt; report higher deployment frequencies and lower change failure rates, as seen in the State of DevOps reports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous Refactoring &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Refactoring is essential to maintain code health. Benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduction of technical debt&lt;/li&gt;
&lt;li&gt;Improved performance and maintainability&lt;/li&gt;
&lt;li&gt;Easier onboarding of new developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unchecked technical debt can reduce development speed by &lt;strong&gt;15–20% annually&lt;/strong&gt;, compounding into major delays over time. Scheduled refactoring sprints or “engineering health” time allocations are vital.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring &amp;amp; Logging &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Visibility into system behavior is critical for proactive maintenance. Good observability includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structured logging with correlation IDs&lt;/li&gt;
&lt;li&gt;Metrics collection and dashboards&lt;/li&gt;
&lt;li&gt;Distributed tracing&lt;/li&gt;
&lt;li&gt;Real-time alerts and anomaly detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Teams that invest in observability tools report a &lt;strong&gt;30%+ improvement in reliability and resolution times&lt;/strong&gt;, according to research by Honeycomb and Google SRE practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Building maintainable software is not a one-time effort but a continuous commitment. By adhering to foundational design principles — &lt;strong&gt;operability&lt;/strong&gt;, &lt;strong&gt;simplicity&lt;/strong&gt;, and &lt;strong&gt;evolvability&lt;/strong&gt; — and reinforcing them with proven best practices like &lt;strong&gt;code readability, testing, decoupling, refactoring, and monitoring&lt;/strong&gt;, teams can ensure that their systems remain robust, adaptable, and cost-effective.&lt;/p&gt;

&lt;p&gt;Ultimately, &lt;strong&gt;maintainability is a force multiplier&lt;/strong&gt; — it enhances productivity, reduces risk, and positions software to evolve in harmony with business needs. Prioritizing it from day one is one of the most impactful investments in long-term software success.&lt;/p&gt;

</description>
      <category>product</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>management</category>
    </item>
    <item>
      <title>Scalability in Data-Intensive applications - Fan-Out, Throughput, Twitter problem, Percentile</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Tue, 25 Feb 2025 10:18:43 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/scalability-in-data-intensive-applications-fan-out-throughput-twitter-problem-percentile-1c8c</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/scalability-in-data-intensive-applications-fan-out-throughput-twitter-problem-percentile-1c8c</guid>
      <description>&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Identifying Bottlenecks&lt;/li&gt;
&lt;li&gt;The Twitter Problem&lt;/li&gt;
&lt;li&gt;Measuring Response Time Effectively&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;As applications grow, they need to handle more users, more data, and more requests efficiently. Scalability is a term used to describe a system's ability to cope with an increasing load.  But how do we ensure that a system scales well? Let's explore some key concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Identifying Bottlenecks &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To scale a system effectively, it's essential to analyze its load parameters. Different systems have different constraints, and finding bottlenecks helps in optimizing performance. Here are several key factors to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fan-out&lt;/strong&gt;: It's a term which describes the number of requests a service or endpoint makes to other services in order to serve a single incoming call. A high fan-out can lead to increased latency and system overload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Throughput&lt;/strong&gt;: In batch processing systems like Hadoop, the focus is on records processed per second rather than individual response times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Response Time Distribution&lt;/strong&gt;: Measuring response time is not just about average values but understanding the distribution of values.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Twitter Problem &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A classic example of scalability challenges is Twitter's timeline system. There are two endpoints, one to create a new post and another to fetch newest 20 posts.&lt;/p&gt;

&lt;p&gt;A naive approach would be to query the database every time a user requests their home timeline. This results in expensive read operations and high latency.&lt;/p&gt;

&lt;p&gt;Instead, Twitter solves this problem by maintaining a cache for each user's homepage. As cache memory is very expensive, there can't be stored all data needed for response, but it's possible to easily store IDs of last 20 posts in the timeline. This approach increases write complexity (It will be necessary to maintain both posts in a database and cache storage), but significantly improves GET request performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring Response Time Effectively &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Response time can vary significantly depending on system load. One of the best ways to analyze it is through percentiles, rather than averages.&lt;/p&gt;

&lt;p&gt;99.9th percentile is often used to track performance (Some companies, like AWS AWS for example use 99.99th percentile). The reasoning behind this is that the top 0.1% of users are usually the most valuable customers, often transferring the most data or making the most critical requests.&lt;/p&gt;

&lt;p&gt;Example: Sentry Monitoring: In observability tools like Sentry, response time percentiles help identify slowest transactions affecting real users, allowing engineers to optimize performance accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Scaling a system is not just about handling more traffic but ensuring efficiency, and optimal resource allocation. &lt;/p&gt;

&lt;p&gt;Scalability is essential for handling growing demands in data-intensive applications. Identifying bottlenecks like fan-out, throughput, and response time distribution helps optimize performance. Finally, using percentiles instead of averages ensures a more accurate measure of system performance, helping engineers focus on critical optimizations.&lt;/p&gt;

</description>
      <category>scalability</category>
      <category>webdev</category>
      <category>devops</category>
      <category>development</category>
    </item>
    <item>
      <title>🚀 Ever wondered why some systems never fail while others crash at the worst moments?</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Sun, 16 Feb 2025 16:23:38 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/ever-wondered-why-some-systems-never-fail-while-others-crash-at-the-worst-moments-discover-1lb9</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/ever-wondered-why-some-systems-never-fail-while-others-crash-at-the-worst-moments-discover-1lb9</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" class="crayons-story__hidden-navigation-link"&gt;Reliability in Data-Intensive Applications&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="/oleksandr_kashytskyi_a630" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg" alt="oleksandr_kashytskyi_a630 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/oleksandr_kashytskyi_a630" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Oleksandr Kashytskyi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Oleksandr Kashytskyi
                
                
              
              &lt;div id="story-author-preview-content-2282377" 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="/oleksandr_kashytskyi_a630" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Oleksandr Kashytskyi&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/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 16 '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/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" id="article-link-2282377"&gt;
          Reliability in Data-Intensive Applications
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/bigdata"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;bigdata&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/software"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;software&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/computing"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;computing&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/fault"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;fault&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/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;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;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>bigdata</category>
      <category>software</category>
      <category>computing</category>
      <category>fault</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Sun, 16 Feb 2025 16:21:53 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/-d3e</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/-d3e</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" class="crayons-story__hidden-navigation-link"&gt;Reliability in Data-Intensive Applications&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="/oleksandr_kashytskyi_a630" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg" alt="oleksandr_kashytskyi_a630 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/oleksandr_kashytskyi_a630" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Oleksandr Kashytskyi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Oleksandr Kashytskyi
                
                
              
              &lt;div id="story-author-preview-content-2282377" 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="/oleksandr_kashytskyi_a630" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2681070%2Fb35a3f41-23f5-49a1-b5a6-d43b1ce90e84.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Oleksandr Kashytskyi&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/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 16 '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/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" id="article-link-2282377"&gt;
          Reliability in Data-Intensive Applications
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/bigdata"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;bigdata&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/software"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;software&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/computing"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;computing&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/fault"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;fault&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/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;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;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>bigdata</category>
      <category>software</category>
      <category>computing</category>
      <category>fault</category>
    </item>
    <item>
      <title>Reliability in Data-Intensive Applications</title>
      <dc:creator>Oleksandr Kashytskyi</dc:creator>
      <pubDate>Sun, 16 Feb 2025 16:21:12 +0000</pubDate>
      <link>https://dev.to/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6</link>
      <guid>https://dev.to/oleksandr_kashytskyi_a630/reliability-in-data-intensive-applications-23l6</guid>
      <description>&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What is Reliability?&lt;/li&gt;
&lt;li&gt;
Types of Faults in Data-Intensive Systems

&lt;ul&gt;
&lt;li&gt;Hardware Faults&lt;/li&gt;
&lt;li&gt;Software Errors&lt;/li&gt;
&lt;li&gt;Human Errors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Visualizing Reliability in Systems

&lt;ul&gt;
&lt;li&gt;Fault Isolation&lt;/li&gt;
&lt;li&gt;Observability Framework&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Data-intensive applications differ from compute-intensive ones by relying heavily on data storage, processing, and retrieval rather than raw computational power. These applications are typically built from standard building blocks, such as databases, caches, messaging systems, and distributed storage.&lt;/p&gt;

&lt;p&gt;Beyond databases, maintaining a data-intensive system requires a suite of other tools to ensure reliability, performance, and fault tolerance.&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%2Fca64wefsg8fudkoj8yws.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.amazonaws.com%2Fuploads%2Farticles%2Fca64wefsg8fudkoj8yws.jpg" alt="image 1" width="600" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Reliability? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A system is considered reliable if it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performs its intended function correctly as expected by the user.&lt;/li&gt;
&lt;li&gt;Can tolerate user mistakes without severe failures.&lt;/li&gt;
&lt;li&gt;Maintains good enough performance for the required use case.&lt;/li&gt;
&lt;li&gt;Prevents unauthorized access to sensitive data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reliability is closely related to &lt;strong&gt;fault tolerance&lt;/strong&gt; — the system’s ability to continue functioning despite faults.&lt;/p&gt;

&lt;p&gt;Fault ≠ Failure&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;fault&lt;/strong&gt; occurs when a component stops working (e.g., a database node crashes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;failure&lt;/strong&gt; happens when the system as a whole can no longer function correctly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Types of Faults in Data-Intensive Systems &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hardware Faults &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hardware failures include disk crashes, memory corruption, and power outages.&lt;/p&gt;

&lt;p&gt;Modern distributed systems can tolerate hardware faults through redundancy and failover mechanisms (RAID for storage, replication for databases e.t.c.).&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Errors &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Software errors are trickier to handle than hardware faults. They can be caused by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crashes due to bad input or unhandled edge cases.&lt;/li&gt;
&lt;li&gt;A runaway process consuming all system resources.&lt;/li&gt;
&lt;li&gt;Failures in external services that the system depends on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cascading failures&lt;/strong&gt;, where a small failure triggers larger system-wide outages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To mitigate software errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement robust error handling and graceful degradation.&lt;/li&gt;
&lt;li&gt;Use circuit breakers and retry mechanisms.&lt;/li&gt;
&lt;li&gt;Employ canary releases and feature flags to minimize blast radius.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Human Errors &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Studies show that only 10-25% of outages are due to server or network faults, meaning human errors are a major contributor to system failures.&lt;/p&gt;

&lt;p&gt;Strategies to reduce human-induced faults:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design for resilience&lt;/strong&gt; – Make critical operations harder to break.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decouple risky operations&lt;/strong&gt; – Separate places where humans interact most.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thorough testing&lt;/strong&gt; – Include unit, integration, and system-level tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick and easy recovery&lt;/strong&gt; – Provide rollback mechanisms and automated recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed monitoring and alerting&lt;/strong&gt; – Detect anomalies early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Training and process improvement&lt;/strong&gt; – Foster good management practices and continuous learning.&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%2Fzkgry5aeokss7d0nm4cg.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.amazonaws.com%2Fuploads%2Farticles%2Fzkgry5aeokss7d0nm4cg.jpg" alt="image 2" width="430" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualizing Reliability in Systems &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fault Isolation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A well-architected system uses fault isolation to prevent one failing component from bringing down the entire system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load balancer ensures traffic is distributed evenly.&lt;/li&gt;
&lt;li&gt;Circuit breakers prevent overload from failed services.&lt;/li&gt;
&lt;li&gt;Caching layers reduce direct dependencies on databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observability Framework &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A good monitoring and alerting system is essential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs, metrics, and tracing should be unified for quick debugging.&lt;/li&gt;
&lt;li&gt;Real-time dashboards help detect anomalies.&lt;/li&gt;
&lt;li&gt;Automated alerts ensure rapid response to incidents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Reliability is a key aspect of data-intensive applications. Achieving it requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understanding and mitigating different types of faults&lt;/strong&gt; (hardware, software, and human errors).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Designing systems with resilience in mind&lt;/strong&gt; (e.g., fault isolation, circuit breakers, failover strategies).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementing strong observability tools&lt;/strong&gt; (Sentry, AWS CloudWatch) to detect and resolve issues quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these principles, data-intensive applications can achieve high availability, fault tolerance, and consistent performance, ensuring a smooth experience for users.&lt;/p&gt;

</description>
      <category>bigdata</category>
      <category>software</category>
      <category>computing</category>
      <category>fault</category>
    </item>
  </channel>
</rss>
