<?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: Jose Maria Cabeza Rodriguez</title>
    <description>The latest articles on DEV Community by Jose Maria Cabeza Rodriguez (@chemacabeza).</description>
    <link>https://dev.to/chemacabeza</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%2F1638071%2Ff532bbb9-1eeb-4ef2-9a8e-bd216d448113.jpg</url>
      <title>DEV Community: Jose Maria Cabeza Rodriguez</title>
      <link>https://dev.to/chemacabeza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chemacabeza"/>
    <language>en</language>
    <item>
      <title>Domain-Driven Design: The Feynman Explanation</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 06:58:03 +0000</pubDate>
      <link>https://dev.to/chemacabeza/domain-driven-design-the-feynman-explanation-3m30</link>
      <guid>https://dev.to/chemacabeza/domain-driven-design-the-feynman-explanation-3m30</guid>
      <description>&lt;p&gt;If you've been in software engineering long enough, you've likely encountered a codebase that feels impossible to understand. A simple feature request—like adding an urgent tag to an order—ends up breaking the shipping module and corrupting the billing records.&lt;/p&gt;

&lt;p&gt;Why does this happen? Usually, it's because the software was built without deeply understanding the real-world business it was supposed to solve. Developers focused on database tables and APIs instead of focusing on the &lt;em&gt;domain&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Domain-Driven Design (DDD)&lt;/strong&gt;. Coined by Eric Evans in his seminal 2003 book, it is an approach to software development that centers the project on the core business domain.&lt;/p&gt;

&lt;p&gt;Let's break down this famously dense topic using the Richard Feynman technique—simplifying complex ideas with everyday analogies.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Big Picture: Strategic vs. Tactical
&lt;/h2&gt;

&lt;p&gt;Domain-Driven Design is broadly divided into two distinct halves: &lt;strong&gt;Strategic Design&lt;/strong&gt; and &lt;strong&gt;Tactical Design&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl9a034qech9938cvztp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl9a034qech9938cvztp5.png" alt="Domain-Driven Design: The Big Picture" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The interplay between Strategic (the "What" and "Why") and Tactical (the "How") design.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Strategic Design&lt;/strong&gt; is for architects and business leaders. It's about deciding &lt;em&gt;what&lt;/em&gt; to build, identifying what is truly important, and establishing clear boundaries so teams don't step on each other's toes. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Tactical Design&lt;/strong&gt; is for the developers in the trenches. It provides specific coding patterns (like Entities, Value Objects, and Aggregates) to build complex business logic cleanly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You cannot have a successful DDD project using only Tactical patterns—that's just writing clean code for the wrong problem. You must start with Strategy.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Strategic Design: The Restaurant Analogy
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of code, you must distill the large problem domain into smaller, manageable chunks called &lt;strong&gt;Subdomains&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Imagine you are building the software for a massive, global Restaurant Chain. The entire operation is your &lt;strong&gt;Business Domain&lt;/strong&gt;. But you can't build it all at once, and not all parts are equally important.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnj1symzbs7pyqkjcinga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnj1symzbs7pyqkjcinga.png" alt="DDD Subdomains: The Restaurant Analogy" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Focus your best engineers on your core competitive advantage.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;According to DDD, there are three types of subdomains:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Core Subdomain (The Secret Recipe):&lt;/strong&gt; This is your competitive advantage. It's what makes the business unique. For a highly innovative restaurant, it's the recipe creation and menu optimization. The business &lt;em&gt;must&lt;/em&gt; build this in-house with its best developers because it dictates their success.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Supporting Subdomain (The Reservation System):&lt;/strong&gt; This is necessary for the business to function, but it doesn't give you a competitive edge. Your reservation system needs to work perfectly, but nobody chooses to eat at your restaurant &lt;em&gt;because&lt;/em&gt; of the reservation software. You dedicate fewer resources here, or perhaps outsource it.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Generic Subdomain (Accounting &amp;amp; Payroll):&lt;/strong&gt; This is a complex problem, but it's the exact same problem every other company has. You do not gain a competitive advantage by inventing your own payroll software. You simply buy an off-the-shelf solution.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Resolving the Tower of Babel: Ubiquitous Language
&lt;/h2&gt;

&lt;p&gt;The number one reason software projects fail isn't technology; it's miscommunication between the people building the software and the people using it. &lt;/p&gt;

&lt;p&gt;Developers talk about "Rows," "Foreign Keys," and "DTOs." Business experts talk about "Policyholders," "Claims," and "Underwriting." &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv22l1t1oq7allxox2xds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv22l1t1oq7allxox2xds.png" alt="Ubiquitous Language: Speaking the Same Language" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Eradicating translation layers through a shared language.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;DDD forces both sides to agree on a &lt;strong&gt;Ubiquitous Language&lt;/strong&gt;. This is a strict, shared vocabulary. If the business expert calls it a "Guest," the developer cannot create a database table called &lt;code&gt;Users&lt;/code&gt;. The code must reflect the business language perfectly. If a new developer reads the code, it should read like a manual for the business.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Setting Fences: Bounded Contexts
&lt;/h2&gt;

&lt;p&gt;As a company grows, the Ubiquitous Language hits a wall. Different departments use the &lt;em&gt;exact same word&lt;/em&gt; to mean completely different things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnu12yb9lpl83548d6tmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnu12yb9lpl83548d6tmd.png" alt="Bounded Contexts: Same Word, Different Worlds" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A word is only meaningful within a specific boundary.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Take the word &lt;strong&gt;Customer&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  To the &lt;strong&gt;Sales Team&lt;/strong&gt;, a Customer is a lead—someone they are trying to convert. They care about email open rates and sales funnels.&lt;/li&gt;
&lt;li&gt;  To the &lt;strong&gt;Shipping Team&lt;/strong&gt;, a Customer is a physical address and a box dimension.&lt;/li&gt;
&lt;li&gt;  To the &lt;strong&gt;Customer Support Team&lt;/strong&gt;, a Customer is a ticket history and an SLA (Service Level Agreement).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try to build one giant &lt;code&gt;Customer&lt;/code&gt; class in your code that satisfies all three departments, you will create a monstrous, fragile "Big Ball of Mud." &lt;/p&gt;

&lt;p&gt;Instead, DDD tells us to create &lt;strong&gt;Bounded Contexts&lt;/strong&gt;. A Bounded Context is a strict boundary (usually a separate microservice) where a specific model applies. Inside the "Shipping Context," the word Customer strictly means a shipping profile. Inside the "Sales Context," it strictly means a lead. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Context Map
&lt;/h3&gt;

&lt;p&gt;Because these Bounded Contexts eventually need to talk to each other to form a working business, architects draw a &lt;strong&gt;Context Map&lt;/strong&gt; to define their relationships.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjzglapgt62qz5izmgpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjzglapgt62qz5izmgpk.png" alt="Context Map: How Bounded Contexts Relate" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Defining the political and technical integration between teams.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For instance, if the Shipping Context relies on a shady third-party logistics API, you build an &lt;strong&gt;Anti-Corruption Layer (ACL)&lt;/strong&gt; between them, so the messy third-party code doesn't infect your pristine internal model.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Tactical Design: The Solar System of Aggregates
&lt;/h2&gt;

&lt;p&gt;Once the strategy is set, we move to the code. Complex business logic involves objects updating each other. If any object can update any other object directly, your database becomes a tangled web of inconsistencies. &lt;/p&gt;

&lt;p&gt;To solve this, DDD introduces the concept of an &lt;strong&gt;Aggregate&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa7o91l88ai0rc2sn19up.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa7o91l88ai0rc2sn19up.png" alt="Aggregates: The Solar System of DDD" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Aggregates act as the strict gatekeepers of consistency.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of an Aggregate like a &lt;strong&gt;Solar System&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The Sun (Aggregate Root):&lt;/strong&gt; There is one main object at the center, like an &lt;code&gt;Order&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Planets (Entities and Value Objects):&lt;/strong&gt; Other objects orbit it, like &lt;code&gt;OrderLines&lt;/code&gt; (the items bought) or the &lt;code&gt;ShippingAddress&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The strict rule of DDD is that &lt;strong&gt;nothing outside the solar system is allowed to touch the planets directly.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If the payment service wants to change an &lt;code&gt;OrderLine&lt;/code&gt;, it cannot just reach in and update it. It must go to the Sun (the &lt;code&gt;Order&lt;/code&gt; Aggregate Root) and ask it to make the change. The &lt;code&gt;Order&lt;/code&gt; will then check all the business rules (e.g., "Is the order already shipped?") and only then modify the &lt;code&gt;OrderLine&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;By forcing everything through the Aggregate Root, you guarantee that your business rules are never bypassed and your data is always perfectly consistent.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;Domain-Driven Design is not easy. It requires an upfront investment in time, communication, and architectural planning that many teams are too impatient to make. &lt;/p&gt;

&lt;p&gt;However, when you are building complex enterprise software, DDD provides a vocabulary and a roadmap to prevent your codebase from degenerating into a chaotic mess. It reminds us that our primary job isn't to write algorithms—it's to capture business knowledge and turn it into working software.&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;This guide synthesizes principles and concepts from the following definitive texts on the subject:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Domain-Driven Design: Tackling Complexity in the Heart of Software&lt;/em&gt; by Eric Evans (The "Blue Book")&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy&lt;/em&gt; by Vladik Khononov&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Domain-Driven Design: A Pragmatic Approach&lt;/em&gt; by Eduard Ghergu&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Domain-Driven Design: The First 15 Years (Essays from the DDD Community)&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-ddd" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-ddd&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>domaindrivendesign</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>The Feynman Guide to Co-Intelligence</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 06:58:01 +0000</pubDate>
      <link>https://dev.to/chemacabeza/the-feynman-guide-to-co-intelligence-14mi</link>
      <guid>https://dev.to/chemacabeza/the-feynman-guide-to-co-intelligence-14mi</guid>
      <description>&lt;p&gt;Imagine walking into a library where the books have literally read themselves. They’ve absorbed every word, every comma, and every rhythmic cadence of human thought. &lt;/p&gt;

&lt;p&gt;But there’s a catch: the library doesn’t have a librarian. It just has a very, very talented &lt;strong&gt;parrot&lt;/strong&gt;.&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%2Fchemacabeza.dev%2Fimages%2Fwriting%2Fllm-parrot.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%2Fchemacabeza.dev%2Fimages%2Fwriting%2Fllm-parrot.png" alt="The Scholarly Parrot in the Library" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the world of Large Language Models (LLMs). To master them, we have to understand the difference between &lt;strong&gt;mimicry&lt;/strong&gt; and &lt;strong&gt;meaning&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Talented Parrot (Statistical Mimicry)
&lt;/h2&gt;

&lt;p&gt;Richard Feynman once said, &lt;em&gt;"Knowing the name of something isn't the same as knowing the thing."&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;LLMs are the ultimate "name-knowers." At their heart, they are statistical engines. When you ask an LLM a question, it isn't "thinking" in the biological sense. It is calculating a &lt;strong&gt;probability distribution&lt;/strong&gt; over the next possible token (a word or piece of a word).&lt;/p&gt;

&lt;p&gt;Using a mathematical function called &lt;strong&gt;Softmax&lt;/strong&gt;, the model looks at the context you've provided and predicts which word is most likely to follow. If I say, &lt;em&gt;"The cat sat on the..."&lt;/em&gt;, the model doesn't "see" a mat. It sees that in billions of lines of text, the token "mat" follows that sequence with 98% probability.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaway&lt;/strong&gt;: LLMs are "Stochastic Parrots." they are incredibly good at mimicking the &lt;em&gt;structure&lt;/em&gt; of human knowledge without necessarily possessing a &lt;em&gt;model&lt;/em&gt; of the world.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. The Common Sense Gap
&lt;/h2&gt;

&lt;p&gt;As Gary Marcus argues in &lt;em&gt;Rebooting AI&lt;/em&gt;, statistical models have a "Common Sense Gap." They can write a beautiful poem about a glass of water, but they might not realize that if you flip the glass, the water will fall.&lt;/p&gt;

&lt;p&gt;Because they learn from text, not from physical interaction, they lack a &lt;strong&gt;World Model&lt;/strong&gt;. They understand symbols, but not the grounded reality behind them. This is why an LLM can provide a perfect medical diagnosis in one breath and hallucinate a non-existent law in the next. They are playing a game of "infinite word-association."&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%2Fchemacabeza.dev%2Fimages%2Fwriting%2Fai-bridge.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%2Fchemacabeza.dev%2Fimages%2Fwriting%2Fai-bridge.png" alt="The Bridge of Digital Glue" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Digital Butler (Autonomous Agents)
&lt;/h2&gt;

&lt;p&gt;How do we fix a parrot that doesn't understand the world? We give it a &lt;strong&gt;Librarian&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In modern engineering, we call these &lt;strong&gt;AI Agents&lt;/strong&gt;. An Agent is an LLM wrapped in a "reasoning loop" (like ReAct: Reason + Act). Instead of just answering you, the Agent can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Search&lt;/strong&gt; for real-time data (RAG - Retrieval Augmented Generation).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Use Tools&lt;/strong&gt; (Calculators, APIs, Python interpreters).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Reflect&lt;/strong&gt; on its own errors and try again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By connecting the "brain" (the LLM) to "hands" (APIs), we bridge the gap between theory and action. The Agent doesn't just &lt;em&gt;talk&lt;/em&gt; about the library; it goes to the shelf, grabs the right book, and checks the facts.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Co-Intelligence: The Partnership Era
&lt;/h2&gt;

&lt;p&gt;The final shift isn't technical—it's psychological. Ethan Mollick, in &lt;em&gt;Co-Intelligence&lt;/em&gt;, suggests we are moving past the era of "AI as a tool" and into the era of "AI as a partner."&lt;/p&gt;

&lt;p&gt;Think of it like a &lt;strong&gt;Handshake&lt;/strong&gt;. You bring the human intent, the moral compass, and the common sense. The AI brings the vast, statistical scale, the tireless processing, and the creative spark. &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%2Fchemacabeza.dev%2Fimages%2Fwriting%2Fai-partnership.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%2Fchemacabeza.dev%2Fimages%2Fwriting%2Fai-partnership.png" alt="The Handshake of Co-Intelligence" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When these two meet, you don't just get a better search engine. You get &lt;strong&gt;Co-Intelligence&lt;/strong&gt;—a collaborative intelligence that is greater than the sum of its parts.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 References &amp;amp; Further Reading
&lt;/h2&gt;

&lt;p&gt;This post was synthesized from the foundational concepts found in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Raschka, Sebastian.&lt;/strong&gt; &lt;em&gt;Build a Large Language Model (From Scratch)&lt;/em&gt;. Manning Publications. (Structural mechanics of transformers).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Marcus, Gary &amp;amp; Davis, Ernest.&lt;/strong&gt; &lt;em&gt;Rebooting AI: Building Artificial Intelligence We Can Trust&lt;/em&gt;. Pantheon. (The Common Sense Gap).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Mollick, Ethan.&lt;/strong&gt; &lt;em&gt;Co-Intelligence: Living and Working with AI&lt;/em&gt;. Portfolio. (The partnership framework).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lanham, Michael.&lt;/strong&gt; &lt;em&gt;AI Agents in Action&lt;/em&gt;. Manning Publications. (Agentic design patterns).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Alammar, Jay.&lt;/strong&gt; &lt;em&gt;Hands-On Large Language Models&lt;/em&gt;. O'Reilly Media. (Visualizing the attention mechanism).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Master the deepest functional layers of modern AI—from the foundational next-token prediction to the high-level orchestration of agentic systems.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-co-intelligence" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-co-intelligence&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llms</category>
      <category>aiagents</category>
      <category>cointelligence</category>
      <category>feynmantechnique</category>
    </item>
    <item>
      <title>Modular monolith vs microservices: a practical guide</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:54:26 +0000</pubDate>
      <link>https://dev.to/chemacabeza/modular-monolith-vs-microservices-a-practical-guide-4bk3</link>
      <guid>https://dev.to/chemacabeza/modular-monolith-vs-microservices-a-practical-guide-4bk3</guid>
      <description>&lt;h1&gt;
  
  
  Modular monolith vs microservices: a practical guide
&lt;/h1&gt;

&lt;p&gt;The debate usually goes like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We should move to microservices. Monoliths don't scale."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or the backlash:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We should go back to a monolith. Microservices are overengineered."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both positions are wrong because they are categorical. They treat architecture as theology rather than engineering.&lt;/p&gt;

&lt;p&gt;The right question is not &lt;em&gt;which is better&lt;/em&gt;. The right question is &lt;em&gt;which is appropriate for our current constraints, team size, and growth trajectory&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let me give you a practical framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a modular monolith actually is
&lt;/h2&gt;

&lt;p&gt;A modular monolith is not a big ball of mud. It is a single deployable unit where the code is organised into well-defined modules with explicit boundaries, enforced through code rather than network.&lt;/p&gt;

&lt;p&gt;Think of it as microservices at the code level instead of the infrastructure level. Each module owns its domain logic. No cross-module access to internals. Communication happens through defined interfaces.&lt;/p&gt;

&lt;p&gt;The boundary is a Java package, a Python module, a TypeScript namespace — not an HTTP endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  The advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simpler operations&lt;/strong&gt;: one thing to deploy, one thing to monitor, one database to care about&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower latency&lt;/strong&gt;: in-process calls instead of network calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier refactoring&lt;/strong&gt;: moving code across module boundaries is cheaper than re-designing service contracts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic transactions&lt;/strong&gt;: you can use ACID transactions across domain boundaries trivially&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster onboarding&lt;/strong&gt;: new engineers can understand the system by reading the code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scaling is all-or-nothing&lt;/strong&gt;: you can't scale your hot module independently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology lock-in&lt;/strong&gt;: the whole app runs on one tech stack&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment coupling&lt;/strong&gt;: a bug in one module can take down everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team coordination&lt;/strong&gt;: merge conflicts and PR reviews cross module boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What microservices actually buy you
&lt;/h2&gt;

&lt;p&gt;Microservices are not about scalability. Or rather, they are, but not in the way most people think.&lt;/p&gt;

&lt;p&gt;The real value of microservices is &lt;strong&gt;independent deployability&lt;/strong&gt;. The ability for one team to change, test, and ship their service without coordinating with any other team. That is the primary reason to reach for them.&lt;/p&gt;

&lt;p&gt;As a consequence of independent deployability, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent scaling — you can allocate resources where the load is&lt;/li&gt;
&lt;li&gt;Technology flexibility — each service can use the right tool for the job&lt;/li&gt;
&lt;li&gt;Blast radius reduction — a failing service can be isolated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But you also inherit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distributed systems complexity&lt;/strong&gt;: network partitions, partial failures, eventual consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational overhead&lt;/strong&gt;: service discovery, load balancing, distributed tracing, per-service CI/CD&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data management complexity&lt;/strong&gt;: cross-service joins, sagas, event sourcing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organisational prerequisites&lt;/strong&gt;: you need Conway-aligned teams to make this work&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A decision framework
&lt;/h2&gt;

&lt;p&gt;Here is how I think about the choice:&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with a modular monolith if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You are building something new (0→1)&lt;/li&gt;
&lt;li&gt;Your team is smaller than ~20 engineers&lt;/li&gt;
&lt;li&gt;You have not yet found product-market fit&lt;/li&gt;
&lt;li&gt;You cannot invest in serious platform infrastructure&lt;/li&gt;
&lt;li&gt;Your main scaling concern is code complexity, not infrastructure throughput&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The modular monolith keeps you fast. You can iterate quickly, refactor aggressively, and you do not need a DevOps team to manage your deployment topology.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extract services when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A specific module has demonstrably different scaling requirements&lt;/li&gt;
&lt;li&gt;A specific team needs completely autonomous deployment velocity&lt;/li&gt;
&lt;li&gt;A module has such a different availability requirement that it needs independent SLOs&lt;/li&gt;
&lt;li&gt;You are adding a fundamentally different technology that cannot co-exist in the current stack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice the emphasis on &lt;em&gt;specific&lt;/em&gt;. Not "let's carve out services in advance" but "this module, right now, has a concrete need that only a service boundary solves."&lt;/p&gt;

&lt;h2&gt;
  
  
  The migration path
&lt;/h2&gt;

&lt;p&gt;If you're starting a modular monolith today, design it with a service extraction path in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enforce module boundaries from day one&lt;/strong&gt; — use linting or architecture tests to prevent cross-module coupling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design module APIs as if they were service APIs&lt;/strong&gt; — explicit inputs, explicit outputs, no shared state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use domain events internally&lt;/strong&gt; — even within the monolith, emit business events that other modules consume asynchronously&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Own your data per module&lt;/strong&gt; — even if it's the same database, keep tables namespaced to their owning module&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the time comes to extract a service, you lift the module out. The API is already defined. The data ownership is already clear. You change the transport layer from function calls to HTTP/events.&lt;/p&gt;

&lt;p&gt;That is the strangler fig pattern applied intentionally from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;The best codebase I have ever worked on was a well-structured modular monolith serving 10M users. The worst distributed system I have ever inherited was an over-engineered microservices mesh with 60 services and a team of 8 engineers who could not deploy anything without breaking three other things.&lt;/p&gt;

&lt;p&gt;Architecture is a trade-off, not a verdict. Use the right tool for your current moment — and build with the next moment in mind.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/monolith-vs-microservices" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/monolith-vs-microservices&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Performance is a product feature</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:53:51 +0000</pubDate>
      <link>https://dev.to/chemacabeza/performance-is-a-product-feature-4egm</link>
      <guid>https://dev.to/chemacabeza/performance-is-a-product-feature-4egm</guid>
      <description>&lt;h1&gt;
  
  
  Performance is a product feature
&lt;/h1&gt;

&lt;p&gt;There is a mental model that corrupts how most engineering teams think about performance:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Functional requirements first. Non-functional requirements later."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Performance gets put in the "nice to have" box. It is addressed retroactively, after the feature is shipped, after users are complaining, after the performance regression has baked into the architecture.&lt;/p&gt;

&lt;p&gt;This is exactly backwards.&lt;/p&gt;

&lt;p&gt;Performance is not a technical constraint. It is a product experience. And like any product experience, the later you address it, the more expensive it becomes to fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data is not ambiguous
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A 100ms improvement in page load time correlates with +1% revenue for e-commerce (Amazon, 2012)&lt;/li&gt;
&lt;li&gt;53% of mobile users abandon sites that take more than 3 seconds to load (Google)&lt;/li&gt;
&lt;li&gt;Pinterest reduced page load time by 40% and saw a 15% increase in SEO traffic&lt;/li&gt;
&lt;li&gt;A 1-second delay in response time results in 7% reduction in conversions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These figures are old. The bar has gotten higher, not lower. Users have been conditioned by the best-performing apps in the world. Slack, Linear, Figma — perception of speed is now a key differentiator.&lt;/p&gt;

&lt;p&gt;The slow app is the bad app. Even if it has more features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance as user experience
&lt;/h2&gt;

&lt;p&gt;Think about what it feels like to use a slow product.&lt;/p&gt;

&lt;p&gt;You click something. There's a delay. You wonder if it registered. You hover. You click again. Now you've done it twice. The UI catches up with a double-action. You feel friction. You feel mild anxiety. Over 100 sessions, that anxiety accumulates into a general negative perception of the product.&lt;/p&gt;

&lt;p&gt;Fast software feels &lt;em&gt;respected&lt;/em&gt;. It says: we value your time. Every interaction affirms that the product was built with care.&lt;/p&gt;

&lt;p&gt;Slow software communicates the opposite: we didn't think about you.&lt;/p&gt;

&lt;p&gt;Performance is not about benchmarks. It is about the emotional texture of using a product.&lt;/p&gt;

&lt;h2&gt;
  
  
  It compounds in both directions
&lt;/h2&gt;

&lt;p&gt;The dangerous thing about performance regressions is that they compound.&lt;/p&gt;

&lt;p&gt;Each feature ships with a marginal performance cost. Database query that doesn't have an index. Synchronous call that could be async. One extra round trip to validate something that could be cached.&lt;/p&gt;

&lt;p&gt;Individually, invisible. Cumulatively, devastating.&lt;/p&gt;

&lt;p&gt;After 18 months, the fast startup app that could load in 400ms now takes 2.3 seconds. The team does not know when it happened. Bisecting the git history reveals dozens of commits each contributed 20ms. No single villain. Death by a thousand cuts.&lt;/p&gt;

&lt;p&gt;The inverse is also true. Systematic performance hygiene compounds into product excellence. Every engineer who thinks about the cost of what they ship creates a culture where performance is maintained, not recovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  What systematic performance culture looks like
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Measure what matters.&lt;/strong&gt; Set SLOs on user-facing latency (P50, P95, P99 — not just average). Track bundle size. Track Core Web Vitals. Make regressions visible on every PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat performance budgets like test coverage.&lt;/strong&gt; Would you merge a PR that drops test coverage by 20%? Then why merge one that increases bundle size by 40KB with no justification?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design for performance.&lt;/strong&gt; The most impactful performance work happens in the design phase, not the optimization phase. The right data model, the right caching strategy, the right API contract — these decisions are made before a line of code is written.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Celebrate performance wins publicly.&lt;/strong&gt; When an engineer reduces P95 by 40%, that is a product improvement. Treat it like one. Put it in the changelog. Mention it in the all-hands. Signal that this work is valued.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make it easy to understand performance.&lt;/strong&gt; Every engineer should have access to production latency dashboards, flame graphs, and query plans. Observability is the prerequisite for performance culture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The engineering manager's responsibility
&lt;/h2&gt;

&lt;p&gt;If you are an engineering manager, you are ultimately responsible for the performance culture of your team.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Including performance criteria in your definition of done for every feature&lt;/li&gt;
&lt;li&gt;Refusing to accept "we'll fix it later" as an answer for known performance issues&lt;/li&gt;
&lt;li&gt;Prioritising performance work in your roadmap before it becomes critical&lt;/li&gt;
&lt;li&gt;Praising and rewarding the engineers who do the unsexy work of making things faster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get the culture you tolerate. If you tolerate slow, you get slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Close
&lt;/h2&gt;

&lt;p&gt;The next time you hear "we'll optimize after the feature is shipped" — that is a red flag.&lt;/p&gt;

&lt;p&gt;Performance is not something you bolt on. It is something you design in. It is the difference between a product that feels like a pleasure to use and one that feels like a chore.&lt;/p&gt;

&lt;p&gt;Ship fast code. Your users will know the difference, even if they can't articulate why.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/performance-is-a-product-feature" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/performance-is-a-product-feature&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>product</category>
      <category>backendsystems</category>
    </item>
    <item>
      <title>Microservices vs Monoliths: The Feynman Explanation</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:53:50 +0000</pubDate>
      <link>https://dev.to/chemacabeza/microservices-vs-monoliths-the-feynman-explanation-1c64</link>
      <guid>https://dev.to/chemacabeza/microservices-vs-monoliths-the-feynman-explanation-1c64</guid>
      <description>&lt;p&gt;If you spend enough time around software engineers, you'll eventually hear a heated debate about &lt;strong&gt;Monoliths&lt;/strong&gt; versus &lt;strong&gt;Microservices&lt;/strong&gt;. People argue about them as if choosing the wrong one will doom a company forever.&lt;/p&gt;

&lt;p&gt;But what do these terms actually mean? If we cut out the jargon and the buzzwords, how do they actually work? &lt;/p&gt;

&lt;p&gt;Let's use the Richard Feynman technique—simplifying complex concepts using everyday analogies—to break down this massive debate. We'll also layer in some deep insights from industry giants I've been studying, like Sam Newman and Mark Richards.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Monolith: The Giant Swiss Army Knife
&lt;/h2&gt;

&lt;p&gt;Imagine you are going camping. You decide to buy a survival tool. You buy an enormous, 150-tool Swiss Army Knife. It has a knife, a saw, a magnifying glass, a compass, a spoon, a laser pointer—everything you could possibly need, all built into a single, cohesive handle.&lt;/p&gt;

&lt;p&gt;This is exactly what a &lt;strong&gt;Monolithic Architecture&lt;/strong&gt; is. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnagqcdotlj3to9gh582z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnagqcdotlj3to9gh582z.png" alt="The Monolith Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A monolithic architecture is like a massive, deeply interconnected machine. Everything runs together in one place.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In software, a monolith is an application where all the code—the part that handles user login, the part that processes credit cards, the part that sends emails—is packed into one single program. It all deploys together, runs together, and lives together.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why the Monolith is Great
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It's simple to build:&lt;/strong&gt; When you start a company, you don't need a complex factory. You just need a tool that works. Development is fast because all the code is right there in one place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's easy to test and deploy:&lt;/strong&gt; To put it on the internet, you just copy one big folder to a server and hit "run."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything communicates instantly:&lt;/strong&gt; Because all the tools are in the same handle, the user login system can directly "talk" to the email system with virtually zero delay (in-memory calls).&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  When the Monolith Fails
&lt;/h4&gt;

&lt;p&gt;Eventually, your company grows. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You hire 500 engineers, and they are all trying to update the same single app at the same time. It's like 500 people trying to sharpen different tools on the same Swiss Army Knife simultaneously. People bump elbows. Things break. (We call this &lt;em&gt;deployment coupling&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;If the "credit card processor" part of the app crashes because of a bug, it brings the &lt;em&gt;entire&lt;/em&gt; app down. The single handle breaks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Microservices: The Workshop of Experts
&lt;/h2&gt;

&lt;p&gt;Because the giant Swiss Army knife got too heavy and kept jamming, you decide to change your strategy. &lt;/p&gt;

&lt;p&gt;Instead of one tool that does everything, you build a workshop. You hire a master chef who only cooks. You hire a master lumberjack who only cuts wood. You hire an expert navigator who only reads compasses. They each have their own independent, specialized tools and they work in separate rooms. &lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;Microservices Architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw1eqoy2r0wdth4ei08gr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw1eqoy2r0wdth4ei08gr.png" alt="The Microservices Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A microservices architecture functions like a constellation of specialized, flying drones. They operate independently but talk to each other over a network.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In software, you chop your giant Monolith into dozens (or hundreds) of tiny, independent programs. One program &lt;em&gt;only&lt;/em&gt; handles login. Another &lt;em&gt;only&lt;/em&gt; processes payments. They communicate with each other by sending messages over the network (like the chef calling out an order to the lumberjack).&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Microservices are Great
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Independent Teams:&lt;/strong&gt; You can have 10 engineers working on the "Payment Service" and 10 working on the "Email Service." They don't step on each other's toes because they are working in entirely separate codebases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent Scaling:&lt;/strong&gt; If it's Black Friday and the payment service is getting hammered, you can just duplicate the "Payment" expert 50 times without needing to duplicate the rest of the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blast Radius:&lt;/strong&gt; If the email service crashes, the rest of the app (like logging in or buying things) can stay alive. &lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  When Microservices Fail
&lt;/h4&gt;

&lt;p&gt;Microservices are heavily romanticized, but they introduce a terrifying new type of complexity. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The network is unreliable:&lt;/strong&gt; In the monolith, changing data was instant. Now, your services have to yell at each other over the internet. What if a message gets lost? &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data is scattered:&lt;/strong&gt; You no longer have one giant database. You have 50 small databases. Trying to put together a single "Order History" requires asking five different services for pieces of the puzzle. This violates the simplicity of absolute truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging is a nightmare:&lt;/strong&gt; When a user clicks a button and gets an error, that request might have bounced through 15 different microservices. Finding out &lt;em&gt;which&lt;/em&gt; one failed is like finding a needle in a haystack.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Insights from the Masters
&lt;/h2&gt;

&lt;p&gt;If we look at the heavyweights in System Design, they all agree on one thing: &lt;strong&gt;There are no silver bullets, only trade-offs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;, Neal Ford and Mark Richards emphasize that breaking apart a monolith isn't just about code—it's about managing data. Once you split the database, achieving consistency (making sure all the systems agree on the truth) becomes incredibly difficult. They coined the phrase: "Architecture is the stuff you can't google."&lt;/p&gt;

&lt;p&gt;Martin Kleppmann, in &lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt;, points out that distributed systems (like microservices) force you to deal with partial failures. You have to assume that at any given moment, &lt;em&gt;something&lt;/em&gt; is broken, and build your system to tolerate it.&lt;/p&gt;

&lt;p&gt;And Sam Newman, author of &lt;em&gt;Monolith to Microservices&lt;/em&gt;, has a stark warning for the industry: &lt;strong&gt;Start with a monolith.&lt;/strong&gt; He advises against building microservices from day one. You should only adopt them when the monolith becomes too painful for your organization to scale. Microservices primarily solve organizational problems (too many developers stepping on each other), not necessarily technical problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;If you are a startup or a small team, build a Monolith. Keep the Swiss Army Knife. It is fast, efficient, and reliable. Understand your domain first.&lt;/p&gt;

&lt;p&gt;If you are Netflix, Amazon, or a massive organization with hundreds of engineering teams, you need Microservices. You need the specialized workshop, even if it means paying a massive "distributed systems tax" in complexity.&lt;/p&gt;

&lt;p&gt;Architecture is not about finding the "best" pattern. It's about finding the pattern that fits the problems you have &lt;em&gt;right now&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-microservices" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-microservices&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>microservices</category>
      <category>monoliths</category>
    </item>
    <item>
      <title>Serverless Computing: The Feynman Explanation</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:53:15 +0000</pubDate>
      <link>https://dev.to/chemacabeza/serverless-computing-the-feynman-explanation-kpj</link>
      <guid>https://dev.to/chemacabeza/serverless-computing-the-feynman-explanation-kpj</guid>
      <description>&lt;p&gt;Serverless is one of those buzzwords that gets thrown around constantly in modern software engineering. If you read the marketing materials, it sounds like some kind of magic that eliminates all your infrastructure problems. On the other hand, if you read internet forums, it sounds like an overcomplicated, overpriced nightmare.&lt;/p&gt;

&lt;p&gt;But what does "Serverless" &lt;em&gt;actually&lt;/em&gt; mean?&lt;/p&gt;

&lt;p&gt;Let's use the Richard Feynman technique—simplifying a complex concept by breaking it down into everyday analogies—to understand what Serverless really is, where it came from, and why it matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Evolution of Hosting: From Bedrooms to the Cloud
&lt;/h2&gt;

&lt;p&gt;To understand Serverless, we first have to understand what came before it. Let's look at the evolution of how we host software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzfpwqooxlw6w1tzlaqut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzfpwqooxlw6w1tzlaqut.png" alt="The Evolution to Serverless" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;From physical hardware to invisible utility computing.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Physical Servers:&lt;/strong&gt; In the beginning, you literally owned a computer. You bought it, plugged it in, and connected it to the internet. If the power went out, your site went down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colocation:&lt;/strong&gt; You realized your bedroom wasn't a great place for a server, so you started renting space in a professional data center. You still bought the server, but they provided reliable power and internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtualization / Cloud:&lt;/strong&gt; Instead of buying physical hardware, you rented "virtual" computers (Virtual Machines) from companies like Amazon or Google. You could get a new server in minutes instead of weeks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform as a Service (PaaS):&lt;/strong&gt; Companies started offering platforms where you just upload your code, and they handle the virtual machines and web servers for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless:&lt;/strong&gt; The final evolution. The servers become entirely invisible. You just write small functions, and the cloud provider runs them, scales them, and manages everything automatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;(Wait, so there are still servers in Serverless? Yes! The "-less" in Serverless doesn't mean "without servers." It means "servers are invisible to you." Just like "wireless" internet still uses wires, it's just that *your&lt;/em&gt; device doesn't have a wire plugged into it.)*&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Restaurant vs. The Food Truck
&lt;/h2&gt;

&lt;p&gt;The best way to understand the core benefit of Serverless is billing and utilization.&lt;/p&gt;

&lt;p&gt;Imagine you want to start selling burgers. &lt;/p&gt;

&lt;p&gt;You rent a traditional restaurant building. You hire a chef. You pay for electricity, water, and rent. &lt;br&gt;
During the lunch rush, you are slammed. But at 3:00 AM? Your restaurant is completely empty. Your chef is sitting there, bored. The lights are on. &lt;strong&gt;You are burning money.&lt;/strong&gt; You pay rent whether you have 100 customers or zero.&lt;/p&gt;

&lt;p&gt;This is exactly how traditional servers work. You rent a server, and you pay for it 24/7, even when no one is visiting your website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpsjicn74aorj7khh67vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpsjicn74aorj7khh67vg.png" alt="Serverless Food Truck Analogy" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;With Serverless, you only pay exactly for what you consume.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, imagine a magical &lt;strong&gt;Food Truck on Demand&lt;/strong&gt;. &lt;br&gt;
When a customer walks up and asks for a burger, the truck pops into existence, cooks the burger, hands it over, and then vanishes. This is &lt;strong&gt;Serverless&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With Serverless, you don't pay "rent" for an idling server. You only pay for the exact milliseconds that your code is actually running. If nobody visits your website for a month, your hosting bill is exactly $0.00. &lt;/p&gt;




&lt;h2&gt;
  
  
  3. How a Serverless Function Actually Works
&lt;/h2&gt;

&lt;p&gt;In a Serverless architecture, you don't build one giant application. Instead, you write tiny snippets of code called &lt;strong&gt;Functions&lt;/strong&gt; (like AWS Lambda). &lt;/p&gt;

&lt;p&gt;These functions are designed to do exactly one thing, and they only wake up when something explicitly &lt;em&gt;triggers&lt;/em&gt; them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmtmrwdfeg12hey85q0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmtmrwdfeg12hey85q0t.png" alt="How a Serverless Function Works" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A function wakes up, does its job, and goes back to sleep.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the lifecycle of a Serverless function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Trigger (Event):&lt;/strong&gt; Something happens. A user clicks a button, a file is uploaded, or a scheduled timer goes off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Wake Up:&lt;/strong&gt; The cloud provider spins up a tiny, invisible container for your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Execution:&lt;/strong&gt; Your code runs. It might read from a database, process some data, or return a JSON response. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Sleep:&lt;/strong&gt; Once the function finishes returning the response, the container is destroyed. You stop paying.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. The Event-Driven Workshop
&lt;/h2&gt;

&lt;p&gt;Because everything in Serverless is built out of these tiny, temporary functions, the architecture looks very different from a traditional system. &lt;/p&gt;

&lt;p&gt;It becomes an &lt;strong&gt;Event-Driven Architecture&lt;/strong&gt;. Instead of one central program giving orders, you have a giant nervous system where different services react to events as they happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7jd0yckqrx3tg578sl0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7jd0yckqrx3tg578sl0.png" alt="Event-Driven Serverless Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;In an event-driven system, functions react seamlessly to changes, working together like a symphony.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of it like a chain reaction factory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A user uploads an image to cloud storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event!&lt;/strong&gt; The storage bucket yells, "I got a new file!"&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ImageResizer&lt;/code&gt; function hears this, wakes up, compresses the image, and saves it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event!&lt;/strong&gt; The &lt;code&gt;ImageResizer&lt;/code&gt; yells, "I made a smaller image!"&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;DatabaseUpdater&lt;/code&gt; function hears this, wakes up, and records the new image URL in the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a deeply uncoupled, highly scalable way to build software. If 10,000 users upload an image at the exact same second, the cloud provider simply wakes up 10,000 copies of your &lt;code&gt;ImageResizer&lt;/code&gt; function simultaneously. No servers crash, no systems slow down.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The Trade-offs: The Cold Start Problem
&lt;/h2&gt;

&lt;p&gt;If Serverless is so amazing, why doesn't everyone use it for everything? &lt;/p&gt;

&lt;p&gt;Remember earlier when we mentioned the "magical food truck" that pops into existence? Well, popping into existence takes a tiny bit of time. &lt;/p&gt;

&lt;p&gt;If a function hasn't been used recently, the cloud provider will tear down its container to save resources. When the next request comes in, the system has to find an empty server, download your code, configure the environment, and load your program into memory before it can actually run. &lt;/p&gt;

&lt;p&gt;This is called a &lt;strong&gt;Cold Start&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq6sjmqzsd6fu2cgo1oi2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq6sjmqzsd6fu2cgo1oi2.png" alt="The Serverless Cold Start Problem" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Cold starts add latency to your first request.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your car is already running (a Warm Start), hitting the gas makes you move instantly.&lt;br&gt;
If your car is cold in the garage, it takes time to open the door, turn the key, let the engine catch, and finally shift into drive. &lt;/p&gt;

&lt;p&gt;For many applications, a cold start delay of a few hundred milliseconds is completely unnoticeable. But if you are building an ultra-low-latency high-frequency trading platform, or a fast-action multiplayer game, that slight hesitation can be a dealbreaker.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;Serverless represents a monumental shift in how we think about computing. By giving up control over the physical infrastructure, engineers gain the ability to scale infinitely without actively managing servers, and businesses gain a pricing model that perfectly matches their actual usage.&lt;/p&gt;

&lt;p&gt;Just like moving from physical servers to the Cloud, Serverless isn't just a different way to host code—it's a fundamentally different way to design and build systems.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-serverless" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-serverless&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>serverless</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Large Language Models: The Feynman Guide</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:53:12 +0000</pubDate>
      <link>https://dev.to/chemacabeza/large-language-models-the-feynman-guide-2e6a</link>
      <guid>https://dev.to/chemacabeza/large-language-models-the-feynman-guide-2e6a</guid>
      <description>&lt;p&gt;Have you ever wondered how ChatGPT or Claude seems to "understand" you? To many, it feels like magic. To others, it's just "fancy autocomplete." &lt;/p&gt;

&lt;p&gt;But if we peel back the layers and look at the actual engineering—the same stuff I've been studying in books by pioneers like Sebastian Raschka and Jay Alammar—we find something far more fascinating than magic. &lt;/p&gt;

&lt;p&gt;Let's use the Richard Feynman technique—simplifying complex systems using everyday analogies—to understand how Large Language Models (LLMs) actually work.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Tokenization: The Lego Bricks of Language
&lt;/h2&gt;

&lt;p&gt;Computers don't actually read words like "Elephant" or "Hydrogen." They only understand numbers. So, how do we bridge the gap?&lt;/p&gt;

&lt;p&gt;Imagine you have a massive box of &lt;strong&gt;Legos&lt;/strong&gt;. Every word in the human language is built from smaller, reusable blocks. Instead of having a single block for "unhappy," we might have a block for "un" and a block for "happy."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu9qq5k7arw280gcaeuzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu9qq5k7arw280gcaeuzz.png" alt="Tokenization: Building with Lego Bricks" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Tokenization is the process of breaking language into subword units. It allows the model to understand words it has never seen before by looking at their pieces.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;Tokenization&lt;/strong&gt;. Most modern LLMs use a technique called Byte Pair Encoding (BPE). It breaks words down into the most efficient "bricks" possible. This is why an LLM can understand "Antidisestablishmentarianism"—it doesn't need to know the whole word; it just snaps together the pieces it already knows.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Attention: The Spotlight in the Library
&lt;/h2&gt;

&lt;p&gt;Once the model has the Lego bricks, it needs to figure out what they mean in context. This is where the &lt;strong&gt;Transformer&lt;/strong&gt; architecture comes in, and its secret weapon is called "Self-Attention."&lt;/p&gt;

&lt;p&gt;Imagine you are in a pitch-black library with a single &lt;strong&gt;spotlight&lt;/strong&gt;. You are trying to figure out what the word "it" refers to in the sentence: &lt;em&gt;"The bank was closed because it was a holiday."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Does "it" refer to the bank? Or the holiday? &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqwi7e8lg232hymage0am.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqwi7e8lg232hymage0am.png" alt="Attention: The Model's Spotlight" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Attention mechanism acts like a spotlight, allowing the model to focus on the most relevant words in a sentence to determine context.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The model uses its spotlight to scan the entire sentence at once (not left-to-right, like a human). It shines the light on "bank" and then on "holiday." It calculates which word has the strongest "relationship" to the word it's currently looking at. In this case, the spotlight lingers on "holiday" to explain the "why." This mathematical spotlight is what allows AI to "understand" nuance.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Training: The Self-Reading Student &amp;amp; The Teacher
&lt;/h2&gt;

&lt;p&gt;How does the model learn where to shine the spotlight? It goes through two main phases of school.&lt;/p&gt;

&lt;h4&gt;
  
  
  Phase 1: Pre-training (The Self-Reading Student)
&lt;/h4&gt;

&lt;p&gt;The model is given the entire internet. It plays a game of "Guess the Next Word" billions of times. It's like a student who reads 100,000 libraries but has no teacher. It learns the &lt;em&gt;patterns&lt;/em&gt; of language, but it doesn't always learn how to be &lt;em&gt;helpful&lt;/em&gt;. It might learn how to write a poem, but also how to argue or be rude.&lt;/p&gt;

&lt;h4&gt;
  
  
  Phase 2: RLHF (The Teacher's Feedback)
&lt;/h4&gt;

&lt;p&gt;To turn that raw "pattern-matcher" into a helpful assistant, we use &lt;strong&gt;Reinforcement Learning from Human Feedback (RLHF)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F115wqg6lpr6bsiuox725.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F115wqg6lpr6bsiuox725.png" alt="RLHF: Refined by Humans" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Human "teachers" review the model's outputs and give it a thumbs up or thumbs down. Over time, the model "grows" into a helpful and safe assistant.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of it like watering a plant. We "water" the responses that are helpful, honest, and harmless, and we "prune" the ones that are confusing or dangerous. This is how we get from a chaotic text-guesser to a tool like ChatGPT.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. RAG: The Open-Book Exam
&lt;/h2&gt;

&lt;p&gt;One big problem with LLMs is that they have a "knowledge cutoff." They only know what they read during their initial school years. If you ask them about news from yesterday, they might guess (or "hallucinate").&lt;/p&gt;

&lt;p&gt;To fix this, we use &lt;strong&gt;Retrieval Augmented Generation (RAG)&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Imagine you are taking a history exam. You are a smart student with a great memory, but your teacher lets you use a &lt;strong&gt;library&lt;/strong&gt; during the test. When you get a question you aren't 100% sure about, you don't guess—you walk to the shelf, grab the right book, and read the answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fouf4lxckk55y2z1oydl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fouf4lxckk55y2z1oydl3.png" alt="RAG: The Open-Book Exam" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;RAG allows the model to look up real-time, factual information from a secure "Vector Database" before answering, drastically reducing errors.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is why modern AI "Agents" are so powerful. They don't just "know" things; they know how to find things.&lt;/p&gt;




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

&lt;p&gt;This post was synthesized from the foundational concepts found in these exceptional engineering resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Build a Large Language Model (From Scratch)&lt;/strong&gt; by Sebastian Raschka. (Essential for understanding the Transformer architecture and Attention).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;LLM Engineer’s Handbook&lt;/strong&gt; by Paul Iusztin &amp;amp; Maxime Labonne. (Great for RAG and Production patterns).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hands-On Large Language Models&lt;/strong&gt; by Jay Alammar &amp;amp; Maarten Grootendorst. (The gold standard for visual explanations of NLP).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Building LLMs for Production&lt;/strong&gt; by Louis-François Bouchard. (Deep dive into reliability and evaluation).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;LLMs aren't thinking beings—they are massive, incredibly sophisticated pattern-matching engines. They break language into bricks, use spotlights to find context, learn from human teachers, and pass open-book exams using databases.&lt;/p&gt;

&lt;p&gt;By understanding these simple components, we can stop seeing AI as a "black box" and start seeing it for what it truly is: &lt;strong&gt;The most powerful language tool humanity has ever built.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-llms" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-llms&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llms</category>
      <category>machinelearning</category>
      <category>nlp</category>
    </item>
    <item>
      <title>Why most microservices architectures fail</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:52:01 +0000</pubDate>
      <link>https://dev.to/chemacabeza/why-most-microservices-architectures-fail-2807</link>
      <guid>https://dev.to/chemacabeza/why-most-microservices-architectures-fail-2807</guid>
      <description>&lt;p&gt;You have almost certainly worked in a codebase that someone called a "microservices architecture" — and you have almost certainly thought: &lt;em&gt;this is worse than a monolith&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You are not wrong. Most microservices implementations are worse than the monolith they replaced. The promise was independence, speed, and resilience. The delivery was a distributed mess of HTTP calls, a shared database with 12 owners, and log files scattered across 30 services.&lt;/p&gt;

&lt;p&gt;Let me explain why this keeps happening — and what the engineers who get it right have in common. I am going to use the Richard Feynman technique: if I cannot explain it simply enough for a 12-year-old to understand the core idea, I do not understand it well enough myself.&lt;/p&gt;

&lt;p&gt;The material here synthesizes insights from the most important books in the field: Sam Newman's &lt;em&gt;Monolith to Microservices&lt;/em&gt;, Neal Ford and Mark Richards' &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;, Martin Kleppmann's &lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt;, and Adam Bellemare's &lt;em&gt;Building Event-Driven Microservices&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Feynman Foundation: What is a Microservice, Really?
&lt;/h2&gt;

&lt;p&gt;Before we talk about failure, let us make sure we agree on what the thing actually is.&lt;/p&gt;

&lt;p&gt;Imagine a pizza restaurant. In a &lt;strong&gt;monolith&lt;/strong&gt;, one person does everything: takes the order, makes the dough, adds the toppings, cooks the pizza, delivers it to the table, and processes the payment. Everything is in one place. Easy to understand. Easy to debug. If that one person gets sick, everything stops.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;microservices architecture&lt;/strong&gt;, you hire specialists. One person takes orders. One chef makes dough. One manages toppings. One operates the oven. One delivers. Each person can be replaced independently. You can hire two oven operators on a busy Saturday without hiring two of everyone else. That is independent scaling.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sounds great, right?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is where the analogy breaks down — and where most real implementations go wrong. Those specialists still need to &lt;strong&gt;communicate&lt;/strong&gt;. They need to coordinate orders. They need to share information about which pizzas are ready. And crucially, they need &lt;strong&gt;someone to be in charge of knowing the state of every order&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In software, that coordination problem is everything. Most teams solve the technical decomposition (splitting the code) but completely ignore the coordination problem (splitting the data and managing consistency). That is the root of every failure mode we will discuss.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 1: The Distributed Monolith
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwlmh4p13ho7nsim0btv8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwlmh4p13ho7nsim0btv8.png" alt="The Distributed Monolith Anti-Pattern" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Six services, six teams — one shared database. This is not microservices. This is a monolith you made more expensive to operate.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the single most common failure, and it is almost poetic in its irony.&lt;/p&gt;

&lt;p&gt;A team splits their application into six services. The &lt;code&gt;OrderService&lt;/code&gt;, &lt;code&gt;UserService&lt;/code&gt;, &lt;code&gt;PaymentService&lt;/code&gt;, and three others. They deploy them on separate pods. Different Git repositories. Different CI pipelines. &lt;em&gt;It feels like microservices.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But all six services connect to the &lt;strong&gt;same PostgreSQL database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is what Neal Ford and Mark Richards call the core problem in &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;: the database is the real contract between services. When &lt;code&gt;OrderService&lt;/code&gt; reads from the &lt;code&gt;users&lt;/code&gt; table that &lt;code&gt;UserService&lt;/code&gt; owns, you have created a silent coupling that no amount of separate deployments can fix. Change the schema in &lt;code&gt;UserService&lt;/code&gt;, and you silently break &lt;code&gt;OrderService&lt;/code&gt;. You cannot deploy independently. You are back to a monolith — but now you also have network calls instead of in-process calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Feynman version:&lt;/strong&gt; Imagine our pizza restaurant where all six specialists write their notes in the &lt;em&gt;same shared notebook&lt;/em&gt;. If the order-taker changes the format of her entry, the chef misreads the toppings. You have not made the restaurant more efficient; you have made the notebook a single point of failure that everyone has to negotiate around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt; from Sam Newman is unambiguous: each service must own its data storage entirely. Cross-service data access flows through APIs or events. Never through a shared database. Period.&lt;/p&gt;


&lt;h2&gt;
  
  
  Failure Mode 2: Synchronous Everything — The Cascade of Death
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwxvmhfscrb5xi8ecggih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwxvmhfscrb5xi8ecggih.png" alt="The Synchronous Call Chain Cascade Failure" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A chain of six synchronous HTTP calls. One slow service at the end turns into a 503 for the entire system.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is a call pattern I find in nearly every struggling microservices codebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
  → Gateway (REST)
    → OrderService (REST)
      → PaymentService (REST)
        → InventoryService (REST)
          → NotificationService (REST)  ← 500ms timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every call is synchronous. Every service waits for the next one. The chain is six hops long.&lt;/p&gt;

&lt;p&gt;Martin Kleppmann dedicates a significant section of &lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt; to what he calls &lt;strong&gt;partial failures&lt;/strong&gt; — a property unique to distributed systems and completely absent from monoliths. In a monolith, a function either succeeds or throws an exception. In a distributed system, a remote service can be slow, partially available, or return a stale response without any clear signal about which it is.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;NotificationService&lt;/code&gt; takes 500ms to respond, &lt;code&gt;InventoryService&lt;/code&gt; is blocked waiting. That means &lt;code&gt;PaymentService&lt;/code&gt; is blocked waiting for &lt;code&gt;InventoryService&lt;/code&gt;. That means &lt;code&gt;OrderService&lt;/code&gt; is blocked waiting for &lt;code&gt;PaymentService&lt;/code&gt;. The user's request now takes 3 seconds just from waiting, before even adding the actual processing time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Feynman version:&lt;/strong&gt; Imagine our pizza specialists forming a line where each one has to wait for the next before doing anything. The pizza-delivery specialist stands still until the oven operator is done. The oven operator stands still until the topping specialist finishes. One slow step blocks the entire kitchen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt; is to default to asynchronous, event-driven communication. If &lt;code&gt;NotificationService&lt;/code&gt; is not in the critical path (does the user &lt;em&gt;need&lt;/em&gt; the email confirmation before their order is confirmed?), publish an event to a message broker. &lt;code&gt;NotificationService&lt;/code&gt; consumes it when it is ready. The user's order goes through in 50ms. The email arrives slightly later. The system as a whole is far more resilient.&lt;/p&gt;

&lt;p&gt;Adam Bellemare's &lt;em&gt;Building Event-Driven Microservices&lt;/em&gt; makes this case with industrial-scale examples: organisations that truly decouple their services through events stop having cascading failures. The blast radius of a single service failure is contained because nothing is waiting synchronously upstream.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 3: The Wrong Decomposition — Services Along Technical Layers
&lt;/h2&gt;

&lt;p&gt;This failure mode is less dramatic but deeply debilitating. It happens when engineers decompose their system by &lt;strong&gt;technical concern&lt;/strong&gt; rather than &lt;strong&gt;business capability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I have seen this more times than I can count:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FrontendService&lt;/code&gt; owns all the React code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BackendService&lt;/code&gt; owns all the Java code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DatabaseService&lt;/code&gt; manages the data layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three "services." None of them independently deployable in any meaningful way. Adding a new business feature — say, a user preference panel — requires changing all three simultaneously, coordinating three deployments, and testing the integration between all three.&lt;/p&gt;

&lt;p&gt;Mark Richards and Neal Ford describe this as a failure to understand &lt;strong&gt;bounded contexts&lt;/strong&gt;, drawn from Domain-Driven Design. A bounded context is the natural language boundary of a domain. Inside it, every term has a single, unambiguous meaning. The &lt;code&gt;Customer&lt;/code&gt; in the &lt;code&gt;Billing&lt;/code&gt; context might be entirely different from the &lt;code&gt;Customer&lt;/code&gt; in the &lt;code&gt;Support&lt;/code&gt; context. Trying to merge them into a single &lt;code&gt;CustomerService&lt;/code&gt; owned by three teams is a recipe for infinite coordination overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Feynman version:&lt;/strong&gt; Imagine our restaurant decided to specialise by &lt;em&gt;ingredient type&lt;/em&gt; rather than &lt;em&gt;role&lt;/em&gt;. One specialist handles everything involving tomatoes. One handles everything involving cheese. One handles everything involving dough. To make a Margherita pizza, all three have to coordinate work at the same time. You have not made the kitchen more independent; you have forced three people to tightly collaborate on every single pizza.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt; is to decompose around business capabilities: &lt;code&gt;OrderManagement&lt;/code&gt;, &lt;code&gt;CustomerNotifications&lt;/code&gt;, &lt;code&gt;InventoryControl&lt;/code&gt;. Each one maps to a team, owns its own data, and can be deployed, scaled, and rewritten independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 4: Conway's Law Violated
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5v4x4cy3r9iu4d7sfa4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5v4x4cy3r9iu4d7sfa4v.png" alt="Conway's Law: Architecture Mirrors the Org Chart" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;When the organisation is structured around technical layers, the architecture it produces will be a technically-layered distributed monolith.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Melvin Conway observed in 1967 that "organisations which design systems are constrained to produce designs which are copies of the communication structures of those organisations." This was a sociological observation, not a technical one. But it is one of the most powerful lenses for understanding why microservices fail.&lt;/p&gt;

&lt;p&gt;If your organisation has a separate &lt;strong&gt;Frontend Team&lt;/strong&gt;, &lt;strong&gt;Backend Team&lt;/strong&gt;, and &lt;strong&gt;DBA Team&lt;/strong&gt; — your microservices will be a &lt;code&gt;FrontendService&lt;/code&gt;, &lt;code&gt;BackendService&lt;/code&gt;, and a shared database. Not because engineers made bad technical decisions, but because teams naturally build systems that mirror how they communicate.&lt;/p&gt;

&lt;p&gt;Neal Ford and Mark Richards are explicit about this in &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;: you cannot fix an architectural problem without fixing the organisational problem first. If the org chart forces two teams to own the same service, or one team to own five services that need to change together — no architectural pattern will save you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Feynman version:&lt;/strong&gt; Imagine a kitchen where the chefs report to one manager, the waiters to another manager, and the kitchen cleaners to a third. Every decision about how to improve service requires all three managers to agree. The kitchen will reflect that friction — slow handoffs, unclear ownership, constant coordination overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt; — what Spotify famously called "squads" and what Sam Newman calls "stream-aligned teams" — is to structure your teams around business outcomes, not technical functions. Each team owns a full slice of the system from end to end.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 5: No Observability
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftg9cwzhtf1eocql3rliy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftg9cwzhtf1eocql3rliy.png" alt="The Observability Gap in Microservices" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;In a monolith, debugging is simple. In microservices without distributed tracing, a production bug is a ghost in a machine with 30 compartments.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is a scenario that will be uncomfortably familiar to many engineers.&lt;/p&gt;

&lt;p&gt;A user reports that their checkout process sometimes fails. In a monolith, you grep the log file. You find the exception. You fix it. Twenty minutes of work.&lt;/p&gt;

&lt;p&gt;In a microservices system with 15 services and no distributed tracing: you look at the API Gateway logs. No error there. You check &lt;code&gt;OrderService&lt;/code&gt;. No error. You check &lt;code&gt;PaymentService&lt;/code&gt;. A warning, but it resolved. &lt;code&gt;InventoryService&lt;/code&gt;? &lt;code&gt;NotificationService&lt;/code&gt;? You are now in hour three, SSH-ing into different container logs, trying to find one failed request among millions.&lt;/p&gt;

&lt;p&gt;This is the observability gap. Ian Gorton, in &lt;em&gt;Foundations of Scalable Systems&lt;/em&gt;, describes distributed systems observability as a &lt;strong&gt;first-class architectural concern&lt;/strong&gt; — not a post-launch operational task. Without three things — &lt;strong&gt;structured logging with correlated trace IDs&lt;/strong&gt;, &lt;strong&gt;distributed tracing (OpenTelemetry)&lt;/strong&gt;, and &lt;strong&gt;meaningful SLIs and SLOs&lt;/strong&gt; — debugging a microservices system at production scale is functionally impossible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Feynman version:&lt;/strong&gt; Imagine 30 pilots flying in formation, and your dashboard in the control tower shows you... nothing. No altimeters. No fuel gauges. No radio. If any pilot deviates, you will not know until they crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt; is non-negotiable: every service ships with structured JSON logs that carry a &lt;code&gt;traceId&lt;/code&gt; on every log line. Every service emits distributed traces using OpenTelemetry. You never add a service without adding its observability layer first.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Right Way: Extract, Don't Prematurly Decompose
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg06py4d628caxjksv3dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg06py4d628caxjksv3dg.png" alt="When Should You Split?" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The decision to extract a service should be driven by demonstrated organisational or scale pain — not architectural ambition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sam Newman's &lt;em&gt;Monolith to Microservices&lt;/em&gt; offers what I consider the most honest advice in the field: &lt;strong&gt;start with a monolith&lt;/strong&gt;. Build your understanding of the domain first. Let the bounded contexts emerge from real usage. Then, when specific, demonstrable pain appears — a team that cannot deploy independently, a component that needs a different scaling profile — extract that component surgically.&lt;/p&gt;

&lt;p&gt;The organisations I have studied that run microservices well share a set of traits that the failing ones do not:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Trait&lt;/th&gt;
&lt;th&gt;Failing Organisations&lt;/th&gt;
&lt;th&gt;Successful Organisations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Starting point&lt;/td&gt;
&lt;td&gt;Greenfield microservices&lt;/td&gt;
&lt;td&gt;Well-understood monolith&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decomposition driver&lt;/td&gt;
&lt;td&gt;Tech blog posts&lt;/td&gt;
&lt;td&gt;Demonstrated team friction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data ownership&lt;/td&gt;
&lt;td&gt;Shared database&lt;/td&gt;
&lt;td&gt;Strict per-service data isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Communication style&lt;/td&gt;
&lt;td&gt;Synchronous REST chains&lt;/td&gt;
&lt;td&gt;Async events by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability&lt;/td&gt;
&lt;td&gt;Logs in production&lt;/td&gt;
&lt;td&gt;OpenTelemetry from day one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team structure&lt;/td&gt;
&lt;td&gt;Functional (Frontend/Backend)&lt;/td&gt;
&lt;td&gt;Stream-aligned (business domain)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The key insight from &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt; is that every architectural decision is actually a &lt;strong&gt;trade-off analysis&lt;/strong&gt;. Microservices give you independent deployability and scale — they cost you network complexity, data consistency challenges, and operational overhead. That trade is worth it when you have large teams with clear bounded contexts. It is catastrophically expensive when you do not.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Uncomfortable Conclusion
&lt;/h2&gt;

&lt;p&gt;Microservices are not a technology decision. They are an &lt;strong&gt;organisational design&lt;/strong&gt; decision that happens to have technical implications.&lt;/p&gt;

&lt;p&gt;If your organisational structure cannot support independent team ownership, if your engineers have not internalized eventual consistency, if your operations team cannot instrument distributed traces — microservices will not fix those problems. They will amplify them.&lt;/p&gt;

&lt;p&gt;The engineers who laugh at microservices are usually the ones who were handed a distributed monolith and told it was a success. The engineers who swear by them are usually the ones who had the discipline to establish bounded contexts, event-driven communication, and observability &lt;em&gt;before&lt;/em&gt; decomposing.&lt;/p&gt;

&lt;p&gt;The architecture is never the problem. The maturity to execute it is.&lt;/p&gt;







&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;This guide synthesizes principles and concepts from the following definitive texts on distributed systems and software architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Monolith to Microservices: Evolutionary Patterns to Transform Your Monolith&lt;/em&gt; by Sam Newman&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Software Architecture: The Hard Parts — Modern Trade-Off Analyses for Distributed Architectures&lt;/em&gt; by Neal Ford, Mark Richards, Pramod Sadalage &amp;amp; Zhamak Dehghani&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt; by Martin Kleppmann&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Building Event-Driven Microservices: Leveraging Organizational Data at Scale&lt;/em&gt; by Adam Bellemare&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Foundations of Scalable Systems: Designing Distributed Architectures&lt;/em&gt; by Ian Gorton&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/why-microservices-fail" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/why-microservices-fail&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>The Feynman Guide to Software Architecture</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:51:58 +0000</pubDate>
      <link>https://dev.to/chemacabeza/the-feynman-guide-to-software-architecture-7e3</link>
      <guid>https://dev.to/chemacabeza/the-feynman-guide-to-software-architecture-7e3</guid>
      <description>&lt;p&gt;Software Architecture often sounds like a mystical art practiced by gray-bearded wizards in ivory towers. In reality, it's just about making the hard decisions—the ones that are difficult to change later. &lt;/p&gt;

&lt;p&gt;To demystify these concepts, I've applied the &lt;strong&gt;Richard Feynman Technique&lt;/strong&gt;: taking complex ideas from the incredible O'Reilly 2024 Software Architecture collection and explaining them using simple, relatable analogies. &lt;/p&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Architect Elevator
&lt;/h2&gt;

&lt;p&gt;In &lt;em&gt;The Software Architect Elevator&lt;/em&gt;, Gregor Hohpe explains that a modern architect isn't just a technical genius; they are a communicator. &lt;/p&gt;

&lt;p&gt;Imagine a massive corporate skyscraper. At the top, in the luxurious penthouse boardroom, business executives are plotting the company's strategic goals. At the very bottom, in the noisy, bustling engine room (the data center or development floor), engineers are wiring cables and writing code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnow74lsv9hlegijyga3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnow74lsv9hlegijyga3f.png" alt="The Architect Elevator" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Architect Elevator connects the penthouse strategy to the engine room execution.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; The architect is the person riding the elevator. They must be able to speak the language of business ("ROI," "Time to Market") in the penthouse, and then ride the elevator down to the engine room and translate that into technical reality ("Latency," "Database Sharding," "Microservices"). If the elevator is broken, the strategy never becomes reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The First Law of Architecture: "It Depends"
&lt;/h2&gt;

&lt;p&gt;If you ask an architect a question, the answer is almost always: &lt;em&gt;"It depends."&lt;/em&gt; Neal Ford and Mark Richards emphasize this in &lt;em&gt;Fundamentals of Software Architecture&lt;/em&gt; and &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Think of architecture like designing a car. Do you want a Formula 1 race car or a Volvo station wagon? You can't have both. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fht534mgzfbwrjpcpu05i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fht534mgzfbwrjpcpu05i.png" alt="Architecture Trade-offs" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Balancing the scales: Speed and Agility vs. Security and Stability.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; In software, there are no perfect solutions, only &lt;strong&gt;trade-offs&lt;/strong&gt;. You are constantly balancing "-ilities":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Scalability&lt;/strong&gt; (handling more users) often costs &lt;strong&gt;Money&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Security&lt;/strong&gt; (locking things down) often reduces &lt;strong&gt;Usability&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Agility&lt;/strong&gt; (moving fast) can sometimes threaten &lt;strong&gt;Stability&lt;/strong&gt;.
An architect's job isn't to find the "right" answer; it's to find the trade-off that best fits the business goal.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Breaking the Monolith: Lego Blocks vs. A Ball of Yarn
&lt;/h2&gt;

&lt;p&gt;Sam Newman's books (&lt;em&gt;Building Microservices&lt;/em&gt; and &lt;em&gt;Monolith to Microservices&lt;/em&gt;) tackle one of the biggest trends of the last decade: breaking apart massive applications.&lt;/p&gt;

&lt;p&gt;Imagine your software is a giant, tangled ball of multicolored yarn (a &lt;strong&gt;Monolith&lt;/strong&gt;). If you pull one red string on the left side, a blue string on the right side tightens. Everything is connected. Changing one thing might break something completely unrelated. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9psy3nk6axl52qy3qtd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9psy3nk6axl52qy3qtd4.png" alt="Monolith vs Microservices" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A tangled ball of yarn (Monolith) vs. neatly organized Lego blocks (Microservices).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; &lt;strong&gt;Microservices&lt;/strong&gt; are like playing with Lego blocks. You break the giant ball of yarn into small, independent pieces. If you want to replace a red 2x4 Lego brick with a blue one, you can do it without destroying the whole castle. However, managing 1,000 separate Lego blocks comes with its own massive operational headache (the "Distributed Monolith" trap).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Domain-Driven Design (DDD): The Shared Dictionary
&lt;/h2&gt;

&lt;p&gt;Before you write a single line of code, you need to understand what you are building. This is the core of Vlad Khononov's &lt;em&gt;Learning Domain-Driven Design&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a group of French chefs trying to build a house with Japanese carpenters, but neither speaks the other's language. The chefs ask for a "soufflé station," and the carpenters build a "tatami room." Disaster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmvecyyd5o4nruw5cbph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmvecyyd5o4nruw5cbph.png" alt="Domain-Driven Design" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Building a 'Ubiquitous Language' bridge between business and engineering.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; The most important part of DDD is the &lt;strong&gt;Ubiquitous Language&lt;/strong&gt;. Business experts and software developers must sit down and create a shared dictionary. If the business calls a customer a "Guest," the code shouldn't call them a "User." The code must strictly reflect the actual business domain. Code is just the physical manifestation of business rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Evolutionary Architecture: Buildings That Expect Change
&lt;/h2&gt;

&lt;p&gt;Historically, software architecture was like building a concrete bridge. Once it's built, changing it is incredibly painful. But the business world changes daily. Neal Ford, Rebecca Parsons, and Patrick Kua explore a different approach in &lt;em&gt;Building Evolutionary Architectures&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Imagine building a skyscraper not with concrete, but with massive, modular shipping containers. As the company grows, a giant crane can lift out an old container and slot a new, upgraded one right into its place without the building falling down.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4yo3p1ecwd6jc6n8gs15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4yo3p1ecwd6jc6n8gs15.png" alt="Evolutionary Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A building designed for constant upgrades and interchangeable modules.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; &lt;strong&gt;Evolutionary Architecture&lt;/strong&gt; assumes that change is the only constant. Instead of trying to predict the future, architects build systems that are &lt;em&gt;designed&lt;/em&gt; to be easily modified. They use "fitness functions" (like automated architectural tests) to ensure that as the system evolves, it doesn't degrade in performance or security.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;Software Architecture is less about coding and more about &lt;strong&gt;communication, balancing trade-offs, and predicting where things might go wrong&lt;/strong&gt;. By using the Feynman Technique to understand the underlying principles—elevators, scales, Legos, dictionaries, and modular buildings—we can strip away the jargon and focus on what really matters: solving human problems with technology.&lt;/p&gt;




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

&lt;p&gt;This post is a synthesis of the following excellent resources from the O'Reilly 2024 Software Architecture collection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The Software Architect Elevator&lt;/strong&gt; by Gregor Hohpe&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fundamentals of Software Architecture&lt;/strong&gt; by Mark Richards and Neal Ford&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Software Architecture: The Hard Parts&lt;/strong&gt; by Neal Ford, Mark Richards, Pramod Sadalage, and Zhamak Dehghani&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Building Microservices (2nd Edition)&lt;/strong&gt; by Sam Newman&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Monolith to Microservices&lt;/strong&gt; by Sam Newman&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Learning Domain-Driven Design&lt;/strong&gt; by Vlad Khononov&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Building Evolutionary Architectures (2nd Edition)&lt;/strong&gt; by Neal Ford, Rebecca Parsons, and Patrick Kua&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-software-architecture" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-software-architecture&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>microservices</category>
      <category>ddd</category>
    </item>
    <item>
      <title>How System Design Fails: A Visual Guide</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:51:23 +0000</pubDate>
      <link>https://dev.to/chemacabeza/how-system-design-fails-a-visual-guide-8a6</link>
      <guid>https://dev.to/chemacabeza/how-system-design-fails-a-visual-guide-8a6</guid>
      <description>&lt;p&gt;System Design isn't just about drawing boxes and arrows on a whiteboard. It's about predicting how things will inevitably break and engineering around those failures. &lt;/p&gt;

&lt;p&gt;When you scale from a single server to a distributed network of thousands of machines, failure is no longer a possibility—it is a mathematical certainty. Drawing upon the foundational concepts from textbooks like &lt;em&gt;Designing Data-Intensive Applications (DDIA)&lt;/em&gt;, &lt;em&gt;System Design Interview&lt;/em&gt;, and &lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;, let's explore how systems actually fail in the real world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl1j0qibmvf26ezdnycjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl1j0qibmvf26ezdnycjg.png" alt="System Failure" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;When one node goes down, how does the rest of the cluster respond?&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Single Point of Failure (SPOF)
&lt;/h2&gt;

&lt;p&gt;The most basic, yet most devastating, failure mode is the &lt;strong&gt;Single Point of Failure (SPOF)&lt;/strong&gt;. This happens when an entire system's availability relies on one specific component. &lt;/p&gt;

&lt;p&gt;Imagine a massive highway (your network traffic) that suddenly merges into a single, one-lane toll booth (your single server). It doesn't matter how fast the cars are driving; the toll booth becomes an insurmountable bottleneck.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4zfvwakre12udy8f22zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4zfvwakre12udy8f22zz.png" alt="SPOF Bottleneck" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Traffic bottlenecking at a critical, un-replicated node.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; In system design, any piece of architecture without redundancy is a SPOF. This could be a primary database without a replica, a load balancer without a failover, or even a single domain name registrar. The solution? &lt;strong&gt;Redundancy&lt;/strong&gt;. We scale horizontally, deploying multiple instances behind a load balancer so that if one dies, traffic effortlessly routes to the survivors.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Network Partitions &amp;amp; The Split-Brain Problem
&lt;/h2&gt;

&lt;p&gt;When we talk about distributed systems, we must acknowledge the "Fallacies of Distributed Computing." The biggest fallacy? That the network is reliable.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;Designing Data-Intensive Applications (DDIA)&lt;/em&gt;, Martin Kleppmann highlights the danger of &lt;strong&gt;Network Partitions&lt;/strong&gt;. A partition occurs when the network connecting two halves of your system simply drops.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flyo4emmzkc76trx8md05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flyo4emmzkc76trx8md05.png" alt="Network Partition" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A digital fault line severing communication between two database clusters.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; Imagine two managers running a busy restaurant, communicating via walkie-talkie. If their walkie-talkies break (network partition), they can no longer synchronize. If Manager A accepts a reservation for Table 5, and Manager B accepts a reservation for the exact same table, you have a conflict.&lt;/p&gt;

&lt;p&gt;In a database, this is the &lt;strong&gt;Split-Brain Problem&lt;/strong&gt;. The CAP Theorem dictates that during a network partition, you must choose between &lt;strong&gt;Consistency&lt;/strong&gt; (refusing to accept new writes until the network heals) or &lt;strong&gt;Availability&lt;/strong&gt; (accepting writes on both sides and risking conflicting data). &lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Danger of Clock Skew
&lt;/h2&gt;

&lt;p&gt;Another hard lesson from DDIA: &lt;strong&gt;You cannot trust time&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In a distributed system, every server has its own internal quartz clock. Due to temperature changes and minor hardware differences, these clocks drift apart. One server might think it's 12:00:01, while another thinks it's 12:00:05.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; If Server A writes a record at 12:00:02 (according to its clock), and Server B writes an update at 12:00:01 (according to its slower clock), the database might process Server B's write as the "newer" one and silently overwrite Server A's data, even though Server A's write actually happened later in the physical world! This is why distributed systems rely on logical clocks (like Vector Clocks) instead of wall-clock time to determine the strict ordering of events.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Microservice Trap: The Distributed Monolith
&lt;/h2&gt;

&lt;p&gt;Sam Newman (&lt;em&gt;Monolith to Microservices&lt;/em&gt;) and Neal Ford (&lt;em&gt;Software Architecture: The Hard Parts&lt;/em&gt;) frequently warn about the dangers of splitting architectures too aggressively.&lt;/p&gt;

&lt;p&gt;Microservices promise agility, but if you split your domains incorrectly, you don't get independent services. Instead, you create a tangled, highly-coupled mess called a &lt;strong&gt;Distributed Monolith&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8d7ynwx7enhj9fhfdkqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8d7ynwx7enhj9fhfdkqi.png" alt="Microservice Trap" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A tangled web of synchronous microservice dependencies.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; If Service A cannot complete a user request without synchronously calling Service B, which calls Service C, which calls Service D... you haven't decoupled anything. You've simply taken in-memory function calls and replaced them with slow, unreliable network calls. If Service D fails, the entire chain collapses. This is why asynchronous event-driven architectures (like Kafka) and careful Domain-Driven Design (DDD) boundaries are critical to surviving microservices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Designing for Failure
&lt;/h2&gt;

&lt;p&gt;Systems don't fail because engineers are careless; they fail because complexity scales exponentially. The mark of a senior architect isn't building a system that never fails—it's building a system that &lt;strong&gt;fails gracefully&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;By anticipating SPOFs, respecting network partitions, doubting system clocks, and managing microservice boundaries, we move from writing code to truly engineering systems. &lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/how-system-design-fails" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/how-system-design-fails&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>ddia</category>
      <category>microservices</category>
    </item>
    <item>
      <title>The Feynman Guide to Content Delivery Networks</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:51:21 +0000</pubDate>
      <link>https://dev.to/chemacabeza/the-feynman-guide-to-content-delivery-networks-1ec2</link>
      <guid>https://dev.to/chemacabeza/the-feynman-guide-to-content-delivery-networks-1ec2</guid>
      <description>&lt;p&gt;Every time you load a webpage, stream a movie on Netflix, or scroll through your social media feed, there is a silent, invisible system working behind the scenes to make it feel instant. Without it, the internet would feel like dial-up in the 90s—agonizingly slow, constantly buffering, and perpetually frustrating.&lt;/p&gt;

&lt;p&gt;This system is called a &lt;strong&gt;Content Delivery Network&lt;/strong&gt;, or &lt;strong&gt;CDN&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Despite being the backbone of the modern internet, most engineers have only a vague, hand-wavy understanding of how CDNs actually work. Let's fix that using the &lt;strong&gt;Richard Feynman Technique&lt;/strong&gt;—breaking down the complex engineering of CDNs into simple, everyday analogies that anyone can understand.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Problem: Why One Server Isn't Enough
&lt;/h2&gt;

&lt;p&gt;Imagine you open a single pizza restaurant in Madrid. Your pizza is legendary. Word gets out, and suddenly people in Tokyo, São Paulo, Sydney, and New York want to order your pizza.&lt;/p&gt;

&lt;p&gt;There's a problem. Every single order has to be fulfilled from your single kitchen in Madrid. A customer in Tokyo places an order—the pizza has to travel 10,000 km. By the time it arrives, it's cold. The customer in Sydney? Even worse. And during peak hours, your single kitchen is overwhelmed with thousands of global orders at once.&lt;/p&gt;

&lt;p&gt;This is exactly what happens when a website runs on a single origin server. A user in Australia requesting a webpage hosted in Virginia, USA, has to send a request across the Pacific Ocean, wait for the server to process it, and then wait for the response to travel all the way back. Every millisecond of that round trip is called &lt;strong&gt;latency&lt;/strong&gt;, and it's the number one enemy of user experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fklwya0yvmzwq40q3mq2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fklwya0yvmzwq40q3mq2l.png" alt="CDN Global Network" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A CDN distributes copies of your content to edge servers across the globe, dramatically reducing the distance between the user and the data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; A Content Delivery Network solves this by placing copies of your content on hundreds or thousands of servers distributed across the globe. These servers are called &lt;strong&gt;Edge Servers&lt;/strong&gt; or &lt;strong&gt;Points of Presence (PoPs)&lt;/strong&gt;. When a user requests your website, the CDN routes them to the nearest edge server instead of the faraway origin. The data travels a few hundred kilometers instead of ten thousand.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Pizza Chain Analogy: Edge Caching
&lt;/h2&gt;

&lt;p&gt;The solution to our pizza problem isn't to build a faster oven in Madrid. It's to open &lt;strong&gt;franchise locations&lt;/strong&gt; in every major city. Each franchise pre-stocks the most popular pizzas. When a customer in Tokyo orders a Margherita, the local Tokyo franchise serves it instantly from its own supply—no need to call Madrid at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg5rekgo128dfrr0rvxa0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg5rekgo128dfrr0rvxa0.png" alt="CDN Pizza Analogy" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Instead of every request traveling to the distant origin server, CDN edge servers cache content locally, serving it to nearby users in milliseconds.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;Edge Caching&lt;/strong&gt;, and it is the fundamental mechanism of every CDN. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First Request (Cache Miss):&lt;/strong&gt; The first customer in Tokyo requests your homepage. The Tokyo edge server doesn't have it yet, so it fetches it from the origin server in Madrid, serves it to the user, and &lt;strong&gt;stores a copy&lt;/strong&gt; in its local cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subsequent Requests (Cache Hit):&lt;/strong&gt; The next hundred customers in Tokyo request the same homepage. The edge server already has the copy. It serves it directly—without ever touching the origin server. Response time drops from 300ms to 20ms.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The origin server is now relaxed. It only gets contacted when the cache expires or a genuinely new piece of content is requested. This concept—reducing the load on the origin while speeding up delivery—is the beating heart of a CDN.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Smart Receptionist: DNS-Based Routing
&lt;/h2&gt;

&lt;p&gt;So how does the CDN know &lt;em&gt;which&lt;/em&gt; edge server to send a user to? The answer lies in the &lt;strong&gt;Domain Name System (DNS)&lt;/strong&gt;—the internet's phonebook.&lt;/p&gt;

&lt;p&gt;When you type &lt;code&gt;www.example.com&lt;/code&gt; into your browser, your computer doesn't know where that is. It asks a DNS server: "What is the IP address of &lt;code&gt;www.example.com&lt;/code&gt;?" Normally, the DNS returns the IP of the origin server. But with a CDN, something smarter happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6v4o1gtr2v2qejnxsj4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6v4o1gtr2v2qejnxsj4z.png" alt="CDN DNS Routing" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The CDN's intelligent DNS server acts like a smart receptionist, directing each user to their nearest and healthiest edge server.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The CDN operates its own &lt;strong&gt;Intelligent DNS Server&lt;/strong&gt;. When a user's DNS query arrives, the CDN doesn't just blindly return an IP. It considers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Geographic proximity:&lt;/strong&gt; Where is this user located? Route them to the nearest edge server.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Server health:&lt;/strong&gt; Is the nearest edge server overloaded or down? Route to the next best one.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Network conditions:&lt;/strong&gt; Is there congestion on a particular path? Route around it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This entire decision happens in microseconds, and the user never knows it occurred. They simply experience a fast-loading page.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Cache Hit vs. Cache Miss: The Hot Kitchen
&lt;/h2&gt;

&lt;p&gt;Understanding the difference between a &lt;strong&gt;Cache Hit&lt;/strong&gt; and a &lt;strong&gt;Cache Miss&lt;/strong&gt; is crucial to understanding CDN performance.&lt;/p&gt;

&lt;p&gt;Think of the edge server as a kitchen with a warming shelf. If a dish is already on the shelf (a &lt;strong&gt;Cache Hit&lt;/strong&gt;), the waiter grabs it and serves it in seconds. If the dish isn't on the shelf (a &lt;strong&gt;Cache Miss&lt;/strong&gt;), the kitchen has to cook it from scratch—the waiter walks to the back, fires up the stove, waits for it to cook, puts a copy on the warming shelf for next time, and then serves it. Much slower.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F696y9317vzwzpxogpdir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F696y9317vzwzpxogpdir.png" alt="CDN Cache Hit vs Miss" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A Cache Hit is served instantly from the edge. A Cache Miss requires a round trip to the origin server, adding significant latency.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The performance of a CDN is often measured by its &lt;strong&gt;Cache Hit Ratio&lt;/strong&gt;—the percentage of requests served directly from the edge cache without touching the origin. A well-configured CDN achieves a hit ratio of &lt;strong&gt;95-99%&lt;/strong&gt;, meaning only 1-5% of requests ever reach the origin server.&lt;/p&gt;

&lt;p&gt;Key factors that affect the cache hit ratio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;TTL (Time to Live):&lt;/strong&gt; How long the CDN keeps a cached copy before considering it stale. A longer TTL means more cache hits but potentially stale content.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cache Keys:&lt;/strong&gt; The CDN uses the URL (and sometimes headers, cookies, or query strings) to identify unique content. Misconfigured cache keys can destroy your hit ratio.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Content type:&lt;/strong&gt; Static assets (images, CSS, JavaScript) cache beautifully. Dynamic, personalized content (user dashboards, shopping carts) is much harder to cache.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Beyond Speed: The Shield
&lt;/h2&gt;

&lt;p&gt;Most people think CDNs are only about speed. But one of the most powerful—and least understood—benefits of a CDN is &lt;strong&gt;security&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Remember our pizza franchise model? Now imagine a rival sends a flash mob of 100,000 fake customers to your original Madrid restaurant to overwhelm it. Your single kitchen collapses under the load. This is a &lt;strong&gt;Distributed Denial of Service (DDoS) attack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43526uq0lvgbar47wmoy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43526uq0lvgbar47wmoy.png" alt="CDN DDoS Protection" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A CDN absorbs massive attack traffic across its distributed edge network, shielding the origin server from being overwhelmed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But with your franchise model (CDN), that attack is automatically distributed across hundreds of locations worldwide. No single location is overwhelmed. The CDN's edge servers absorb the attack traffic like a sponge, and the origin server remains calm and protected behind the shield.&lt;/p&gt;

&lt;p&gt;Modern CDNs like Cloudflare, Akamai, and AWS CloudFront provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;DDoS Mitigation:&lt;/strong&gt; Absorbing terabits of malicious traffic per second.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Web Application Firewall (WAF):&lt;/strong&gt; Filtering SQL injection, XSS, and other application-layer attacks at the edge.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;TLS/SSL Termination:&lt;/strong&gt; Handling the computational cost of encryption at the edge, offloading it from the origin.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Bot Management:&lt;/strong&gt; Distinguishing legitimate users from malicious bots before traffic ever reaches your infrastructure.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;A Content Delivery Network is not just a performance optimization—it is a fundamental architectural layer of the modern internet. By distributing content to the edge of the network, CDNs transform the laws of physics from a problem into a non-issue. Users get faster pages, origin servers get less load, and the entire system becomes more resilient against both traffic spikes and malicious attacks.&lt;/p&gt;

&lt;p&gt;The next time a webpage loads instantly, remember: it's not magic. It's a CDN edge server, sitting quietly in a data center near you, serving a cached copy of that content before you even finished blinking.&lt;/p&gt;




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

&lt;p&gt;This post synthesizes concepts from the core literature on content delivery networking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Content Delivery Networks: Fundamentals, Design, and Evolution&lt;/strong&gt; by Dom Robinson.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Content Delivery Networks: Web Switching for Security, Availability, and Speed&lt;/strong&gt; by Scott Hull.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Content Distribution Networks: An Engineering Approach&lt;/strong&gt; by Dinesh C. Verma.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;A Practical Guide to Content Delivery Networks (2nd Edition)&lt;/strong&gt; by Gilbert Held.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-cdns" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-cdns&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cdn</category>
      <category>systemdesign</category>
      <category>networking</category>
      <category>performance</category>
    </item>
    <item>
      <title>The Feynman Guide to Java Modules</title>
      <dc:creator>Jose Maria Cabeza Rodriguez</dc:creator>
      <pubDate>Tue, 21 Jul 2026 04:50:45 +0000</pubDate>
      <link>https://dev.to/chemacabeza/the-feynman-guide-to-java-modules-3e6n</link>
      <guid>https://dev.to/chemacabeza/the-feynman-guide-to-java-modules-3e6n</guid>
      <description>&lt;p&gt;For over two decades, Java developers lived with a dirty secret. The language that championed encapsulation with &lt;code&gt;private&lt;/code&gt;, &lt;code&gt;protected&lt;/code&gt;, and &lt;code&gt;public&lt;/code&gt; had a gaping hole at the architectural level: &lt;strong&gt;there was no way to hide a package from the outside world&lt;/strong&gt;. If you made a class &lt;code&gt;public&lt;/code&gt;, it was public to &lt;em&gt;everyone&lt;/em&gt;—not just your intended consumers, but every single JAR on the classpath.&lt;/p&gt;

&lt;p&gt;This led to a phenomenon so painful it earned its own name: &lt;strong&gt;Classpath Hell&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Java 9, the platform finally got its fix: the &lt;strong&gt;Java Platform Module System (JPMS)&lt;/strong&gt;, codenamed Project Jigsaw. But what exactly are modules, and why should every Java developer understand them?&lt;/p&gt;

&lt;p&gt;Let's use the &lt;strong&gt;Richard Feynman Technique&lt;/strong&gt;—breaking complex ideas into simple, everyday analogies—to understand Java Modules from the ground up.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Classpath Hell: The Problem Modules Solve
&lt;/h2&gt;

&lt;p&gt;Before Java 9, your entire application was a flat pile of JAR files thrown onto the &lt;strong&gt;classpath&lt;/strong&gt;. The JVM would search through this pile to find classes at runtime. It sounds simple, but it created catastrophic problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;No versioning:&lt;/strong&gt; If two JARs contained the same class (e.g., different versions of a library), the JVM would silently pick one at random. Your program would crash with mysterious &lt;code&gt;NoSuchMethodError&lt;/code&gt; exceptions, and you'd have no idea why.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;No encapsulation:&lt;/strong&gt; Every &lt;code&gt;public&lt;/code&gt; class in every JAR was accessible to every other JAR. Internal implementation classes that were never meant to be used externally (like &lt;code&gt;sun.misc.Unsafe&lt;/code&gt;) were used by half the ecosystem.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;No explicit dependencies:&lt;/strong&gt; There was no way to declare "this JAR requires that JAR." If a dependency was missing, you'd only find out at runtime, when your application exploded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp40174okxbjtsjs2040g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp40174okxbjtsjs2040g.png" alt="Classpath Hell vs Java Modules" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Before modules: a tangled mess of JARs with no boundaries. After modules: clean, explicitly connected components with enforced encapsulation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of the old classpath like a building with &lt;strong&gt;no walls, no doors, and no locks&lt;/strong&gt;. Every room is open to every visitor. Someone can walk into the CEO's office, rummage through confidential files, and leave—and the building has no mechanism to stop them.&lt;/p&gt;

&lt;p&gt;Modules add the walls, the doors, and the locks.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The City Analogy: Modules as Districts
&lt;/h2&gt;

&lt;p&gt;The best way to understand the Java Module System is to think of a well-planned city.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzck0z8fm0c09hmdct608.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzck0z8fm0c09hmdct608.png" alt="Java Modules City Analogy" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each module is a self-contained district with walls, controlled entry points, and explicit connections to other districts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine a modern city divided into &lt;strong&gt;districts&lt;/strong&gt; (modules). Each district has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Walls:&lt;/strong&gt; A hard boundary that separates its internal buildings (packages) from the outside world.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Public-facing shops:&lt;/strong&gt; Some buildings are deliberately placed at the district's entrance, visible and accessible to visitors (these are &lt;strong&gt;exported packages&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Private facilities:&lt;/strong&gt; Other buildings—warehouses, utility rooms, staff quarters—are hidden behind the walls, invisible to outsiders (these are &lt;strong&gt;internal packages&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Bridges with guards:&lt;/strong&gt; To travel between districts, you must cross a controlled bridge. The guard checks if your district has a &lt;strong&gt;permit&lt;/strong&gt; (&lt;code&gt;requires&lt;/code&gt;) to access the destination district. No permit? No entry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;em&gt;exactly&lt;/em&gt; how Java modules work. A module is a named, self-describing collection of packages that explicitly declares:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What it needs&lt;/strong&gt; (&lt;code&gt;requires&lt;/code&gt;) — which other modules it depends on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it shares&lt;/strong&gt; (&lt;code&gt;exports&lt;/code&gt;) — which of its packages are accessible to other modules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it hides&lt;/strong&gt; — everything not exported is completely invisible, even if the classes are &lt;code&gt;public&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. The Module Descriptor: Your Blueprint
&lt;/h2&gt;

&lt;p&gt;Every module has a single file that acts as its identity card and access policy: &lt;code&gt;module-info.java&lt;/code&gt;. This file sits at the root of your module's source tree, and the compiler enforces every rule declared in it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqmbb6y2812lo5tmq10v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqmbb6y2812lo5tmq10v3.png" alt="Module Descriptor Anatomy" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The module-info.java file is the control center of every module, declaring its dependencies, exports, and service bindings.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's what each clause does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;requires&lt;/code&gt;&lt;/strong&gt; — "I depend on this module." The compiler and JVM will verify that the required module is present. If it's missing, your program won't even compile—no more runtime surprises.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;exports&lt;/code&gt;&lt;/strong&gt; — "I'm making this package available to the world." Only exported packages can be accessed by other modules. Everything else is locked down.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;requires transitive&lt;/code&gt;&lt;/strong&gt; — "I depend on this module, and so should anyone who depends on me." This forwards a dependency through the chain, so consumers don't have to manually list every transitive dependency.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;opens&lt;/code&gt;&lt;/strong&gt; — "I'm allowing runtime reflection access to this package." This is critical for frameworks like Spring and Hibernate that rely on reflection to inspect and instantiate classes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;provides ... with&lt;/code&gt;&lt;/strong&gt; — "I implement this service interface with this concrete class." This enables the &lt;code&gt;ServiceLoader&lt;/code&gt; pattern for pluggable architectures.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;uses&lt;/code&gt;&lt;/strong&gt; — "I consume this service interface." The counterpart to &lt;code&gt;provides&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple module descriptor looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;billing&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;common&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;exports&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;billing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;opens&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;billing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;model&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;google&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gson&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reads naturally: "The billing module needs &lt;code&gt;java.sql&lt;/code&gt; and the common module. It exposes its API package to the world. It allows Gson to reflect into its model package for JSON serialization."&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Dependency Graph: No More Surprises
&lt;/h2&gt;

&lt;p&gt;One of the most powerful consequences of the module system is the &lt;strong&gt;dependency graph&lt;/strong&gt;. Because every module explicitly declares what it requires, the JVM can build a complete picture of your application's dependency tree &lt;em&gt;before&lt;/em&gt; a single line of code runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr6c9padwifre6o8prfse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr6c9padwifre6o8prfse.png" alt="Module Dependency Graph" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Modules form a clear, layered dependency graph. The &lt;code&gt;requires transitive&lt;/code&gt; keyword forwards dependencies through the chain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This solves the three nightmares of Classpath Hell:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Missing dependencies are caught at startup.&lt;/strong&gt; If module A requires module B, and B isn't on the module path, the JVM refuses to start. No more &lt;code&gt;ClassNotFoundException&lt;/code&gt; after 3 hours of production runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate modules are forbidden.&lt;/strong&gt; The module system enforces that each module appears exactly once. No more silent conflicts between JAR versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circular dependencies are illegal.&lt;/strong&gt; If module A requires B, and B requires A, the compiler rejects it. This forces you into clean, layered architectures.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every module implicitly depends on &lt;code&gt;java.base&lt;/code&gt;—the foundational module containing &lt;code&gt;java.lang&lt;/code&gt;, &lt;code&gt;java.util&lt;/code&gt;, &lt;code&gt;java.io&lt;/code&gt;, and other core packages. You never need to write &lt;code&gt;requires java.base&lt;/code&gt;; it's always there.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Custom Runtimes: Shipping Only What You Need
&lt;/h2&gt;

&lt;p&gt;Here's where modules deliver perhaps their most dramatic practical benefit. Before Java 9, deploying a Java application meant shipping the &lt;strong&gt;entire JRE&lt;/strong&gt;—a ~300MB behemoth containing CORBA, Swing, JavaFX, JNDI, and dozens of other APIs your application never touched.&lt;/p&gt;

&lt;p&gt;With modules, the JDK itself is modularized into ~70 platform modules. And Java provides a tool called &lt;strong&gt;&lt;code&gt;jlink&lt;/code&gt;&lt;/strong&gt; that lets you assemble a custom runtime image containing &lt;em&gt;only&lt;/em&gt; the modules your application actually uses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F97o28qc8xvxqc8tto48x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F97o28qc8xvxqc8tto48x.png" alt="jlink Custom Runtime" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;jlink strips the JDK down to only the modules your application needs, reducing deployment size by up to 90%.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A microservice that only uses &lt;code&gt;java.base&lt;/code&gt; and &lt;code&gt;java.sql&lt;/code&gt; can be packaged into a self-contained runtime of &lt;strong&gt;~30MB&lt;/strong&gt; instead of 300MB. This is transformative for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Container deployments:&lt;/strong&gt; Smaller Docker images mean faster pulls, faster scaling, and lower storage costs.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Serverless functions:&lt;/strong&gt; Smaller cold-start times when the runtime footprint is minimal.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Edge devices and IoT:&lt;/strong&gt; Java can now run in memory-constrained environments where the full JRE was simply too large.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jlink &lt;span class="nt"&gt;--module-path&lt;/span&gt; &lt;span class="nv"&gt;$JAVA_HOME&lt;/span&gt;/jmods:myapp.jar &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--add-modules&lt;/span&gt; com.myapp &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--output&lt;/span&gt; custom-runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces a complete, self-contained runtime directory that you can ship without requiring Java to be installed on the target machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;The Java Platform Module System represents the most significant architectural change to Java since generics. By introducing explicit boundaries, enforced dependencies, and strong encapsulation at the module level, JPMS finally gives Java the tools to build large-scale systems that are maintainable, secure, and efficient.&lt;/p&gt;

&lt;p&gt;Classpath Hell isn't just an inconvenience—it's an architectural cancer that silently degrades reliability as systems grow. Modules are the cure. They force you to think about your architecture explicitly, declare your boundaries clearly, and ship only what you need.&lt;/p&gt;

&lt;p&gt;The walls, doors, and locks are now built into the language itself.&lt;/p&gt;




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

&lt;p&gt;This post synthesizes concepts from the core Java literature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Modern Java in Action&lt;/strong&gt; by Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft — Chapter 14: The Java Module System.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Java: The Complete Reference (12th Edition)&lt;/strong&gt; by Herbert Schildt — Chapter 16: Modules.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Core Java, Volume I: Fundamentals&lt;/strong&gt; by Cay S. Horstmann — Chapter 12: The Java Platform Module System.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Effective Java (3rd Edition)&lt;/strong&gt; by Joshua Bloch.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://chemacabeza.dev/writing/the-feynman-guide-to-java-modules" rel="noopener noreferrer"&gt;https://chemacabeza.dev/writing/the-feynman-guide-to-java-modules&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>jpms</category>
      <category>systemdesign</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
