<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Architecture - Tag - My Personal Corner</title>
        <link>https://fde.cat/en/tags/architecture/</link>
        <description>Architecture - Tag - My Personal Corner</description>
        <generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 15 Feb 2024 00:00:00 &#43;0000</lastBuildDate><atom:link href="https://fde.cat/en/tags/architecture/" rel="self" type="application/rss+xml" /><item>
    <title>Simplicity in Complex Systems</title>
    <link>https://fde.cat/en/essays/simplicity-in-complex-systems/</link>
    <pubDate>Thu, 15 Feb 2024 00:00:00 &#43;0000</pubDate>
    <author>fde.cat</author>
    <guid>https://fde.cat/en/essays/simplicity-in-complex-systems/</guid>
    <description><![CDATA[<p>After nearly two decades working with distributed systems, I&rsquo;ve reached a conclusion that seems counterintuitive: complexity is the real enemy, not bugs.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<h2 id="the-paradox-of-complexity">The Paradox of Complexity</h2>
<p>When we start building systems, adding features seems free. A microservice here, a message queue there, a cache layer to speed things up. Each decision seems reasonable in isolation.</p>
<blockquote class="quote-block">
  <div class="quote-content">
    A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system.
  </div><footer class="quote-footer">
      <cite><span class="quote-author">John Gall</span>,<span class="quote-source">Systemantics: How Systems Work and Especially How They Fail</span></cite>
    </footer></blockquote>

<p>But complexity isn&rsquo;t additive; it&rsquo;s multiplicative. Each new component doesn&rsquo;t just add its own complexity—it multiplies the possible interactions with all other components.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<h2 id="the-hidden-costs">The Hidden Costs</h2>
<p>Complexity has costs that rarely appear in budgets:</p>
<ol>
<li><strong>Diagnosis time</strong> — Every incident takes longer to investigate</li>
<li><strong>Onboarding</strong> — New engineers need months to understand the system</li>
<li><strong>Design decisions</strong> — Every change requires considering more implications</li>
<li><strong>Testing</strong> — The matrix of possible interactions grows exponentially</li>
</ol>
<h3 id="a-real-example">A Real Example</h3>
<p>Years ago, I worked on a payment processing system that had grown organically over a decade. It had:</p>
<ul>
<li>47 microservices</li>
<li>12 different databases</li>
<li>8 message queues</li>
<li>3 caching systems</li>
<li>Approximately 150 external integrations</li>
</ul>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-plaintext">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="Copy to clipboard"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line"><span class="cl">┌─────────────────────────────────────────────────────┐
</span></span><span class="line"><span class="cl">│                    COMPLEXITY                        │
</span></span><span class="line"><span class="cl">├─────────────────────────────────────────────────────┤
</span></span><span class="line"><span class="cl">│  Components: O(n)                                    │
</span></span><span class="line"><span class="cl">│  Interactions: O(n²)                                 │
</span></span><span class="line"><span class="cl">│  Failure modes: O(2ⁿ)                                │
</span></span><span class="line"><span class="cl">└─────────────────────────────────────────────────────┘</span></span></code></pre></div></div>
<p>The mean time to resolution for incidents had gone from minutes to hours. Not because the engineers were less capable, but because understanding what was happening required navigating an increasingly dense web of dependencies.</p>
<h2 id="deliberate-simplicity">Deliberate Simplicity</h2>
<p>Simplicity is not the absence of functionality; it&rsquo;s the absence of unnecessary complexity. It&rsquo;s the result of conscious and often painful decisions.</p>
<blockquote class="quote-block">
  <div class="quote-content">
    Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
  </div><footer class="quote-footer">
      <cite><span class="quote-author">Antoine de Saint-Exupéry</span></cite>
    </footer></blockquote>

<h3 id="practical-principles">Practical Principles</h3>
<p>I&rsquo;ve learned to apply some principles:</p>
<p><strong>1. Prefer monolith first</strong></p>
<p>Start with the simplest system that can work. Only split when you have clear evidence that splitting will solve a real problem.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
<p><strong>2. Measure before optimizing</strong></p>
<p>Complexity added for &ldquo;performance&rdquo; often doesn&rsquo;t provide measurable improvements. Even worse, it can add latency due to the overhead of communication between components.</p>
<p><strong>3. Document decisions, not just code</strong></p>
<p>Every architectural decision should have an ADR (Architecture Decision Record) that explains:</p>
<ul>
<li>The context</li>
<li>The alternatives considered</li>
<li>The decision made</li>
<li>The expected consequences</li>
</ul>
<p><strong>4. Review complexity periodically</strong></p>
<p>What made sense two years ago might not make sense now. Schedule regular architecture reviews with the question: &ldquo;Is this still providing value?&rdquo;</p>
<h2 id="conclusion">Conclusion</h2>
<p>Simplicity is a discipline, not a natural state. It requires constant effort, difficult decisions, and the willingness to say &ldquo;no&rdquo; to features that seem attractive but add unnecessary complexity.</p>
<p>The best systems I&rsquo;ve seen aren&rsquo;t the most sophisticated; they&rsquo;re the ones that do one thing, do it well, and are simple enough that any team member can understand them in an afternoon.</p>
<hr>
<p><em>This is the first entry in a series about lessons learned after nearly two decades in SRE. The next entry will cover observability and why &ldquo;more metrics&rdquo; isn&rsquo;t always better.</em></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This doesn&rsquo;t mean bugs don&rsquo;t matter. Obviously it matters when things fail. But complexity is the source from which most hard-to-diagnose bugs are born.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>If you have <em>n</em> components, you potentially have <em>n(n-1)/2</em> interactions between pairs of components. In practice, not all interactions exist, but growth is still superlinear.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Martin Fowler writes extensively about this in his article &ldquo;<a href="https://martinfowler.com/bliki/MonolithFirst.html" target="_blank" rel="noopener noreffer ">Monolith First</a>&rdquo;.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]></description>
</item>
</channel>
</rss>
