<?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: Ujjwal Raj</title>
    <description>The latest articles on DEV Community by Ujjwal Raj (@ujjwall-r).</description>
    <link>https://dev.to/ujjwall-r</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1115771%2F9bf148aa-7cdc-4de5-a7b5-35acfce87de9.jpeg</url>
      <title>DEV Community: Ujjwal Raj</title>
      <link>https://dev.to/ujjwall-r</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ujjwall-r"/>
    <language>en</language>
    <item>
      <title>Distributed Systems: Raft Algorithm for Leader Election</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sat, 21 Feb 2026 10:34:27 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/distributed-systems-raft-algorithm-for-leader-election-1k2n</link>
      <guid>https://dev.to/ujjwall-r/distributed-systems-raft-algorithm-for-leader-election-1k2n</guid>
      <description>&lt;p&gt;Welcome to another article in the distributed systems series. We will discuss the Raft algorithm and how a leader is elected in a replicated system when the leader goes down and followers become candidates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety and Liveness
&lt;/h2&gt;

&lt;p&gt;In a replicated system, safety means that at any time there is at most one leader. Liveness ensures that during failure, a leader is re-elected.&lt;/p&gt;

&lt;h2&gt;
  
  
  States of the Machine
&lt;/h2&gt;

&lt;p&gt;Any process, at a given time, is in one of three states — leader, follower, or candidate. Every election is identified by a term value, which is simply an integer.&lt;/p&gt;

&lt;p&gt;When the system starts up, all processes are in the follower state.&lt;/p&gt;

&lt;p&gt;Ideally, every follower must receive heartbeats from the current leader containing the election term information. If a heartbeat is not received and a timeout occurs, the follower concludes that the leader is dead. At that point, the follower starts a new election by incrementing the current term and transitioning to the candidate state. It then votes for itself and sends a request to all processes in the system to vote for it, stamping the request with the current election term.&lt;/p&gt;

&lt;p&gt;From here, three things can happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The process wins the election:&lt;/strong&gt; This happens if a majority of other processes vote for the candidate. It then transitions into the leader state and starts sending requests to other processes. Note that other processes vote for at most one candidate on a first-come, first-served basis for a given term.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Another process wins the election:&lt;/strong&gt; If the candidate receives a heartbeat from any other process having a term greater than or equal to the current term, it accepts the other process as the leader. It then transitions back to the follower state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A period of time passes with no winner:&lt;/strong&gt; This rarely happens, but if no candidate receives a majority vote, a re-election is conducted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The Raft algorithm ensures reliable leader election in a replicated system by using terms, heartbeats, and majority voting. It guarantees safety by allowing only one leader at a time and ensures liveness by electing a new leader when the current one fails. This makes Raft simple, predictable, and suitable for building fault-tolerant distributed systems.&lt;/p&gt;

&lt;p&gt;Follow for more articles on distributed systems and computer science.&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>Part II : Building My First Large Language Model from Scratch</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sat, 01 Nov 2025 12:07:49 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/part-ii-building-my-first-large-language-model-from-scratch-46ii</link>
      <guid>https://dev.to/ujjwall-r/part-ii-building-my-first-large-language-model-from-scratch-46ii</guid>
      <description>&lt;p&gt;Welcome to another article on building an LLM from scratch.&lt;/p&gt;

&lt;p&gt;There’s been a little delay in bringing you the second part of this series, as I took some time off to enjoy my Diwali vacations - a much-needed break filled with lights to dive back into building LLMs from scratch.&lt;/p&gt;

&lt;p&gt;If you haven’t read the first one, it’s a quick read - you can go ahead and check it out: &lt;a href="https://dev.to/ujjwall-r/building-my-first-large-language-model-from-scratch-p48"&gt;Building My First Large Language Model from Scratch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Till this point, we have coded the multi-headed attention mechanism.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnf1lg3w4ndudi1u5qjq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnf1lg3w4ndudi1u5qjq5.png" alt=" " width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Building LLM Architecture
&lt;/h2&gt;

&lt;p&gt;We will start building the LLM architecture now. After the multi-head mechanism, we get a tensor which we will process through different deep learning neural network layers. The weights of these layers are collectively called &lt;em&gt;parameters&lt;/em&gt; in the context of LLMs.&lt;br&gt;
You must have heard that GPT-2 Small has 124M parameters - that’s the total number of connected node pairs.&lt;/p&gt;

&lt;p&gt;We used the same values as GPT as our model’s basis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;GPT_CONFIG_124M&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vocab_size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50257&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# vocab size of tiktoken
&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context_length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# maximum input tokens handled by positional embedding layer (see previous blog)
&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;emb_dim&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;786&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;# each token is converted into a 786-dimensional vector
&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;n_heads&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# number of heads in the attention mechanism (see previous blog)
&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;n_layers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;# number of transformer blocks in the model
&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;drop_rates&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# dropout rate for masking
&lt;/span&gt;      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qkv_bias&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;       &lt;span class="c1"&gt;# Query-Key-Value bias in attention mechanism
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the above config, a 12-layer transformer block is built. Let’s start building a single layer of such a transformer model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Applying Layer Normalization
&lt;/h2&gt;

&lt;p&gt;Training deep learning neural networks with multiple layers can sometimes be challenging due to problems like vanishing or exploding gradients. The learning process may struggle to minimize the loss function during backpropagation.&lt;/p&gt;

&lt;p&gt;We use &lt;strong&gt;layer normalization&lt;/strong&gt; to improve the stability and efficiency of neural network training. The idea is to have a mean of 0 and a variance of 1 (unit variance) for the output of a layer. In GPT-2, layer normalization is applied before and after the multi-head attention module.&lt;/p&gt;

&lt;p&gt;You can learn more about layer normalization and its implementation here: &lt;a href="https://medium.com/@sujathamudadla1213/layer-normalization-48ee115a14a4" rel="noopener noreferrer"&gt;https://medium.com/@sujathamudadla1213/layer-normalization-48ee115a14a4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like in GPT-2, layer normalization is chosen over batch normalization for greater flexibility and stability. It is also beneficial in distributed training.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementing the Activation Function (GELU) in Feedforward Network
&lt;/h2&gt;

&lt;p&gt;A cheaper approximation version of GELU is used as the activation function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ogrc7h6dtpay873f4bv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ogrc7h6dtpay873f4bv.png" alt=" " width="800" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The smoothness of GELU leads to better optimization during training than ReLU (as shown in the figure below).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqdc5rpv4nqsd7t5aqmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqdc5rpv4nqsd7t5aqmw.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ReLU has a sharper corner near zero, which makes optimization harder during training, as it outputs zero for any negative value. In contrast, with GELU, neurons that receive negative input still contribute to the learning process to a small extent.&lt;/p&gt;




&lt;h3&gt;
  
  
  A Feedforward Layer Architecture
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruk7poi5j0u8e84362sm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruk7poi5j0u8e84362sm.png" alt=" " width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above figure shows how a feedforward layer looks. It contains three layers - a linear layer, followed by a non-linear GELU normalization layer, and then another linear layer. The GELU layer has a dimension four times that of the linear layer. So the embedding dimensions are first expanded by four times and then reduced back by four times. Doing this provides a better representation space.&lt;/p&gt;




&lt;h3&gt;
  
  
  Shortcut Connection
&lt;/h3&gt;

&lt;p&gt;We provide an alternate path that skips the feedforward layer. This is achieved by adding the output of one layer to the output of a later layer (as shown in the figure). This helps prevent gradient vanishing problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujfvswfxfvdat0bzqcdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujfvswfxfvdat0bzqcdm.png" alt=" " width="800" height="1910"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Assembling the Transformer Block
&lt;/h2&gt;

&lt;p&gt;Now we will assemble one unit of the transformer block. This will be repeated 12 times in the final LLM architecture.&lt;/p&gt;

&lt;p&gt;After the dropout layer, a layer normalization layer is added, followed by a feedforward layer and another dropout layer. The shortcut connection is created as shown in the figure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyua47ol6tkjzlt6wwpqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyua47ol6tkjzlt6wwpqq.png" alt=" " width="800" height="1808"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea is that the attention mechanism identifies and analyzes the relationships between elements in the input sequence, while the feedforward network modifies the data individually at each position. This way, the model is enhanced to handle complex patterns.&lt;/p&gt;

&lt;p&gt;The dropout layer helps prevent overfitting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generating Text: Greedy Decoding
&lt;/h2&gt;

&lt;p&gt;The LLM is assembled as shown in the figure below.&lt;br&gt;
The final output normalization is done, followed by a linear layer that converts each token vector (786-dim) to a vocabulary-sized vector (~50k-dim). This output vector is called &lt;em&gt;logits&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now we’ll understand how the final tensor is used to compute the next token, which forms the LLM’s response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdivny22y8uf37wlxal1q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdivny22y8uf37wlxal1q.png" alt=" " width="800" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To compute the next generated token, we generate a logits vector. The logits vector has a dimension equal to the vocabulary size (~50k in our case). It represents the probability of occurrence of each token.&lt;br&gt;
For example, if index 2 of the logits vector has a value of 0.12, it means the probability of the 2nd token ID being next is 0.12. So, we simply select the token ID with the highest value as the next generated token.&lt;/p&gt;

&lt;p&gt;The following figure from Towards AI helps illustrate the flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnos5h0i4fd19qce4o9p8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnos5h0i4fd19qce4o9p8.png" alt=" " width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;softmax function&lt;/strong&gt; is used to convert the logits into a probability distribution. Since softmax is a monotonic function, you can take the maximum of the logits directly. The idea remains the same - pick the most probable next token.&lt;/p&gt;

&lt;p&gt;A typical logits tensor will have the shape:&lt;br&gt;
&lt;code&gt;(batch size, sequence size, vocab size)&lt;/code&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.amazonaws.com%2Fuploads%2Farticles%2Fcf7q75g3bn9gyt1jx6at.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf7q75g3bn9gyt1jx6at.png" alt=" " width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above figure shows how each logits vector is generated iteratively, and each token is produced in every iteration.&lt;/p&gt;




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

&lt;p&gt;With this, we’ve laid the foundation for how individual transformer blocks come together to form a complete LLM.&lt;/p&gt;

&lt;p&gt;Next, we’ll explore how we label an LLM based on its parameters, how weights can be reused in input and output layers, and the most interesting part - pretraining the whole architecture.&lt;/p&gt;

&lt;p&gt;Till then, stay tuned.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>llm</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Building My First Large Language Model from Scratch</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Fri, 03 Oct 2025 07:39:39 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/building-my-first-large-language-model-from-scratch-p48</link>
      <guid>https://dev.to/ujjwall-r/building-my-first-large-language-model-from-scratch-p48</guid>
      <description>&lt;p&gt;Welcome everyone. I would like to share my experience of building my own LLM from scratch. In this article, you will come across the details of LLM architecture. I followed a great book: &lt;em&gt;Building Large Language Models (From Scratch)&lt;/em&gt; by Sebastian Raschka.&lt;/p&gt;

&lt;p&gt;The whole point is that I built the GPT architecture piece by piece, layer by layer. Once done, it was impossible to train on the CPU/GPU I have locally, so I loaded the weights of GPT-2, which are publicly available from OpenAI. As the last part of the process, I also fine-tuned the model to solve classification problems like spam detection. The series will contain 2-3 articles - from building the GPT architecture to pre-training to fine-tuning.&lt;/p&gt;

&lt;p&gt;The whole experience enriched my understanding of the deep inner workings of Large Language Models.&lt;/p&gt;

&lt;p&gt;I will be adding some code snippets, which are just a glimpse of some aspects covered. You can skip those if not needed. They are optional and only serve to deepen understanding.&lt;/p&gt;




&lt;h2&gt;
  
  
  LLMs use a Decoder to predict the next word
&lt;/h2&gt;

&lt;p&gt;Broadly speaking, the GPT architecture predicts the next word, which happens repeatedly. This iterative process generates entire new sentences, paragraphs, and even pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndst9s6yx125ic7o36js.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndst9s6yx125ic7o36js.png" alt=" " width="800" height="772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GPT-2 is an autoregressive, decoder-only model. Autoregressive models incorporate their previous outputs as inputs for future predictions.&lt;br&gt;
&lt;strong&gt;How does it predict?&lt;/strong&gt; The architecture will be explained step by step in the next sections.&lt;/p&gt;


&lt;h1&gt;
  
  
  Building the model
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Building text tokenisation
&lt;/h2&gt;

&lt;p&gt;This layer maps discrete objects (here, texts) to points in a continuous vector space.&lt;/p&gt;

&lt;p&gt;Tiktoken has a public dataset with token values for all the vocabulary in GPT-2. This was used to create the tokenising layer. Tokenisation is simply converting every vocabulary item into an ID, which is an integer number. A total of 50,257 tokens are used in GPT-2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31bo4jtxxlh9ab3xleec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31bo4jtxxlh9ab3xleec.png" alt=" " width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can learn more about how byte-pair encoding is used to generate token IDs here: &lt;a href="https://www.geeksforgeeks.org/nlp/byte-pair-encoding-bpe-in-nlp/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/nlp/byte-pair-encoding-bpe-in-nlp/&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Building text embeddings
&lt;/h2&gt;

&lt;p&gt;An embedding layer is created which converts the tokens into embeddings, each of 768 dimensions. The layer corresponds to two steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; A torch embedding layer is created with the input dimension equal to vocabulary size and output size of 768 (for GPT-2 small). This neural network layer is trained during pre-training (via backpropagation).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feldxloookqgiiaospgjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feldxloookqgiiaospgjf.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; A positional embedding is calculated and added to the token embedding to get the final vector embedding. The positional embedding has the same dimension as the token embedding. This is calculated by taking values [0,1,2,3…] and embedding them using a torch embedding layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;token_embedding_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;positional_embedding_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;positional_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;positional_embedding_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_len&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Calculating vector embedding
&lt;/span&gt;&lt;span class="n"&gt;input_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token_embedding&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;positional_embedding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob5mw0q94wgfz87mudjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob5mw0q94wgfz87mudjm.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Building the Attention Mechanism to get the context vector
&lt;/h1&gt;

&lt;p&gt;The attention mechanism is very important in LLMs. It allows each position in the input to consider the relevance of all other positions in a sequence.&lt;/p&gt;

&lt;p&gt;You can learn more about attention mechanism basics here: &lt;a href="https://www.ibm.com/think/topics/attention-mechanism" rel="noopener noreferrer"&gt;https://www.ibm.com/think/topics/attention-mechanism&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this implementation, a multi-head attention mechanism is coded. Multiple instances of self-attention are created, each with its own set of weights. The outputs are then combined. Multi-head attention is computationally expensive but very important for recognizing complex patterns.&lt;/p&gt;

&lt;p&gt;Multi-head attention is also called &lt;strong&gt;Scaled Dot-Product Attention&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.amazonaws.com%2Fuploads%2Farticles%2F3qf1v3bd37rtauryq5mv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qf1v3bd37rtauryq5mv.png" alt=" " width="800" height="703"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Multi-head attention mechanism implementation
&lt;/h2&gt;

&lt;p&gt;You can read more about multi-head attention here: &lt;a href="https://www.geeksforgeeks.org/nlp/multi-head-attention-mechanism/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/nlp/multi-head-attention-mechanism/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In GPT-2 small, there are 12 attention heads. So each output vector of a head has a dimension of &lt;code&gt;output_dim (768) / num_heads (12)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The three weights—&lt;code&gt;W_query&lt;/code&gt;, &lt;code&gt;W_key&lt;/code&gt;, and &lt;code&gt;W_value&lt;/code&gt;—are trained later via backpropagation.&lt;/p&gt;

&lt;p&gt;Keys, queries, and values are obtained by splitting the input embeddings (which already include positional embeddings) into multiple heads. Then, the dot product is calculated for each head. Masking is applied before calculating the attention scores. Finally, the outputs of all heads are concatenated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2f1gp7nhgxr1imuw39y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2f1gp7nhgxr1imuw39y.png" alt=" " width="523" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the above diagram, you can see that future attention scores are masked, allowing the model to generate new, accurate, and sensible tokens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf2vrf51qcnlh4uxnn90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf2vrf51qcnlh4uxnn90.png" alt=" " width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following softmax function is used for calculating attention scores:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mh3hvha5an9pepltgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mh3hvha5an9pepltgb.png" alt=" " width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how each attention score is calculated for each head:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7vvgw8mp5p37fi8vj46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7vvgw8mp5p37fi8vj46.png" alt=" " width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later, all the heads are concatenated to obtain the final query vector.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We have now created the multi-head attention mechanism. This is a core part of the GPT model.&lt;/p&gt;

&lt;p&gt;In the next article, we will implement the transformer block and output layers before attempting to pre-train the model.&lt;/p&gt;

&lt;p&gt;Here’s a summary of what we’ve done so far and what’s upcoming:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdnu0thyzf90yte6zsr4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdnu0thyzf90yte6zsr4.png" alt=" " width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See you in the next article.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>deeplearning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>The System Design Series</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Tue, 12 Aug 2025 17:45:30 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/the-system-design-series-3ik7</link>
      <guid>https://dev.to/ujjwall-r/the-system-design-series-3ik7</guid>
      <description>&lt;p&gt;Welcome! This series is your gateway to understanding system design through the lens of volatility-based decomposition. Whether you’re just exploring architecture or already designing large-scale systems, you’ll find clear explanations, practical framework, and examples that make the concepts easy to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Series Overview
&lt;/h2&gt;

&lt;p&gt;This series covers fundamental and advanced concepts in system design using THE METHOD. It covers all the rules and explanations along with the framework and examples. It is based on the book Righting Software by Juval Löwy. It's designed for learners looking to build their foundations as well as professionals deepening their expertise. Some programming background is helpful, but I recommend starting from the beginning if you’re new.&lt;/p&gt;

&lt;h4&gt;
  
  
  About Me
&lt;/h4&gt;

&lt;p&gt;I’ve worked across the spectrum—from fast-paced startups to Fortune 500 Big Tech companies - building systems that handle millions of users, designing intelligent, data-driven solutions, and tackling challenges in security and distributed systems.&lt;/p&gt;

&lt;p&gt;I draw insights not just from my own experiences, but also from collaborating with talented, highly experienced engineers, as well as from the wisdom I gain from books. My writing brings all of these influences together so the community can grow along with me.&lt;/p&gt;

&lt;p&gt;Feel free to connect with me at &lt;a href="mailto:ujjwal.dev.to@gmail.com"&gt;ujjwal.dev.to@gmail.com&lt;/a&gt; - I love engaging with my readers and I’m always up for exchanging ideas and learning together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explore the Series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62"&gt;Principles of Volatility-Based Decomposition in System Design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Template for System Design Using ‘The Method’&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/design-donts-in-system-design-with-the-method-2jcf"&gt;Design Don’ts in System Design with ‘The Method’&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-isnt-about-requirements-its-about-change-2h70"&gt;System Design Isn’t About Requirements — It’s About Change&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-example-using-the-method-j6g"&gt;System Design Example using 'The Method'&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Navigate
&lt;/h2&gt;

&lt;p&gt;Most articles are standalone, while some build on previous topics. If you’re new, start from the top and progress sequentially.&lt;/p&gt;

&lt;p&gt;Have questions or requests? Let me know in the comments or email me at &lt;a href="//ujjwal.dev.to@gmail.com"&gt;mailto:ujjwal.dev.to@gmail.com&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Stay Connected
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bookmark this post for quick access to every article in the series.&lt;/li&gt;
&lt;li&gt;Follow me on dev.to for the latest content.&lt;/li&gt;
&lt;li&gt;Share with friends or colleagues who could benefit!&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Distributed Systems Series: Your One-Stop Guide</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Tue, 12 Aug 2025 10:46:14 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/distributed-systems-series-your-one-stop-guide-499b</link>
      <guid>https://dev.to/ujjwall-r/distributed-systems-series-your-one-stop-guide-499b</guid>
      <description>&lt;p&gt;Welcome! This post is your central hub to navigate the series on distributed systems. Whether you’re a beginner or a practicing engineer, you’ll find clear explanations, practical guides, and deep dives into key topics—all in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Series Overview
&lt;/h2&gt;

&lt;p&gt;This series covers fundamental and advanced concepts in distributed systems, including consistency models,networking , partitioning, practicality of eventual consistency, and much more. It's designed for learners looking to build their foundations as well as professionals deepening their expertise. Some programming and networking background is helpful, but I recommend starting from the beginning if you’re new.&lt;/p&gt;

&lt;h4&gt;
  
  
  About the Author:
&lt;/h4&gt;

&lt;p&gt;I’ve worked across the spectrum—from fast-paced startups to Fortune 500 Big Tech companies - building systems that handle millions of users, designing intelligent, data-driven solutions, and tackling challenges in security and distributed systems.&lt;/p&gt;

&lt;p&gt;I draw insights not just from my own experiences, but also from collaborating with talented, highly experienced engineers, as well as from the wisdom I gain from books. My writing brings all of these influences together so the community can grow along with me.&lt;/p&gt;

&lt;p&gt;Feel free to connect with me at &lt;a href="mailto:ujjwal.dev.to@gmail.com"&gt;ujjwal.dev.to@gmail.com&lt;/a&gt; - I love engaging with my readers and I’m always up for exchanging ideas and learning together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explore the Series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/building-resilient-applications-insights-into-scalability-and-distributed-systems-4pj3"&gt;Building Resilient Applications: Insights into Scalability and Distributed Systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/understanding-server-connections-in-distributed-systems-no4"&gt;Understanding Server Connections in Distributed Systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/how-are-your-connections-with-web-secure-and-integral-254a"&gt;Understanding Server Connections in Distributed Systems&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/understanding-system-models-in-distributed-system-582o"&gt;Understanding System Models in Distributed system&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/ping-heartbeat-in-distributed-systems-40hp"&gt;Ping &amp;amp; Heartbeat in distributed systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/behind-the-scenes-of-online-collaboration-time-management-in-distributed-systems-59nc"&gt;How Real-Time Editing Works: Understanding Event Ordering in Distributed Systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/high-availability-for-social-media-platforms-leader-follower-architecture-and-leader-election-2f42"&gt;High Availability for Social Media Platforms: Leader-Follower Architecture and Leader Election&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/acid-properties-in-single-transactions-explained-2ko"&gt;ACID Properties in Single Transactions Explained&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/how-is-concurrency-control-maintained-to-ensure-isolation-2i9e"&gt;How is Concurrency Control Maintained to Ensure Isolation?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/ensuring-atomicity-in-modern-databases-2e97"&gt;Ensuring Atomicity in Modern Databases&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/http-caching-in-distributed-systems-1j4"&gt;HTTP Caching in Distributed Systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/asynchronous-transaction-in-distributed-system-31ij"&gt;Asynchronous transaction in distributed system&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/cdns-in-distributed-systems-beyond-caching-for-better-performance-fo0"&gt;CDNs in Distributed Systems: Beyond Caching for Better Performance&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/distributed-file-storage-architecture-eg-amazon-s3-azure-storage-1gg4"&gt;Distributed File Storage Architecture (eg. Amazon S3, Azure Storage)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/understanding-data-partitioning-for-scalable-distributed-systems-4k65"&gt;Understanding Data Partitioning for Scalable Distributed Systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/network-load-balancing-in-distributed-systems-24fg"&gt;Network Load Balancing in Distributed systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/scalable-database-solutions-from-replication-to-nosql-and-newsql-1o1a"&gt;Scalable Database Solutions: From Replication to NoSQL and NewSQL&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/ujjwall-r/microservices-and-api-gateway-in-distributed-systems-5ekk"&gt;Microservices and API Gateway in Distributed Systems&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Navigate
&lt;/h2&gt;

&lt;p&gt;Most articles are standalone, while some build on previous topics. If you’re new, start from the top and progress sequentially. New articles are sometimes updated in case I find something missing in the series in future.&lt;/p&gt;

&lt;p&gt;Have questions or requests? Let me know in the comments or email me at &lt;a href="//ujjwal.dev.to@gmail.com"&gt;mailto:ujjwal.dev.to@gmail.com&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Stay Connected
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bookmark this post for quick access to every article in the series.&lt;/li&gt;
&lt;li&gt;Follow me on dev.to for the latest content.&lt;/li&gt;
&lt;li&gt;Share with friends or colleagues who could benefit!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>distributedsystems</category>
      <category>learning</category>
      <category>systemdesign</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>System Design Example using 'The Method'</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sun, 20 Jul 2025 07:46:11 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/system-design-example-using-the-method-j6g</link>
      <guid>https://dev.to/ujjwall-r/system-design-example-using-the-method-j6g</guid>
      <description>&lt;p&gt;Welcome to another article on system design on another Sunday. Every Sunday we have been discussing on how to design a good software system. This is going to be end of the series. Don't worry if you have not read the previous ones. We are carrying forward with us the rules that we keep on our finger tips. &lt;/p&gt;

&lt;p&gt;The motive is to show that system design is not tech but an engineering art. The series is based on the Book Righting Software by Juval Lowey. I would be taking the same example in chapter 5 of the book in this article. &lt;/p&gt;

&lt;p&gt;Here are the rules to follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers? What are different use cases?
&lt;em&gt;(Remember: Almost always, these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;layers given in the template should correspond to 4 question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client : &lt;strong&gt;Who&lt;/strong&gt; interacts withe system&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers : &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Engines : &lt;strong&gt;How&lt;/strong&gt; system performs the business logic&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;ResourceAccess : &lt;strong&gt;How&lt;/strong&gt; system access the resources &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Resource : &lt;strong&gt;Where&lt;/strong&gt; is the system state&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Validate if your design follows the &lt;strong&gt;golden ratio (Manager:Engine)&lt;/strong&gt;. Some valid ratios: 1:(0/1), 2:1, 3:2, 5:3.&lt;br&gt;&lt;br&gt;
More than 5 Managers? You’re likely going wrong.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volatility decreases&lt;/strong&gt; from top to bottom, while &lt;strong&gt;reusability increases&lt;/strong&gt; from top to bottom.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Slices are subsystems. &lt;strong&gt;No more than 3 Managers in a subsystem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design iteratively, build incrementally.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design with the smallest set of reusable components needed to support core use cases. A good architecture integrates ~10–20 components to support them composably. Features are outcomes of integration, not implementation.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Design Don'ts&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;A Client should not call multiple Managers for a single use case.&lt;/li&gt;
&lt;li&gt;A Client must not call Engines.&lt;/li&gt;
&lt;li&gt;Managers must not queue calls to more than one Manager in the same use case.
The need to have two (or more) Managers respond to a queued call is a strong indication that more Managers (and maybe all of them) would need to respond — so you should use a Pub/Sub Utility service instead.&lt;/li&gt;
&lt;li&gt;Engines and &lt;code&gt;ResourceAccess&lt;/code&gt; services do not receive queued calls.&lt;/li&gt;
&lt;li&gt;Clients, Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, or &lt;code&gt;Resource&lt;/code&gt; components do not publish events.&lt;/li&gt;
&lt;li&gt;Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, and &lt;code&gt;Resources&lt;/code&gt; do not subscribe to events. This must be done in a Client or a Manager.&lt;/li&gt;
&lt;li&gt;Engines never call each other.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ResourceAccess&lt;/code&gt; services never call each other.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  System Design Example
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TradeMe&lt;/strong&gt; is a platform that connects &lt;strong&gt;independent tradesmen&lt;/strong&gt; (like plumbers, electricians, carpenters, etc.) with &lt;strong&gt;contractors&lt;/strong&gt; who need skilled labor for construction projects. Tradesmen can list their &lt;strong&gt;skills, availability, location, and expected rate&lt;/strong&gt;, while contractors can post &lt;strong&gt;project requirements, locations, desired skills, and budgets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Matching System&lt;/strong&gt;: Facilitates dynamic matching of contractors and tradesmen based on skills, timing, and rates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market-Driven Pricing&lt;/strong&gt;: Rates are influenced by discipline, skill level, experience, location, project type, supply-demand, risk, weather, and certification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Flexibility&lt;/strong&gt;: Tradesmen may be hired for varying durations, often joining and leaving projects at different times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment &amp;amp; Compliance&lt;/strong&gt;: TradeMe handles payments, logs hours, manages regulatory compliance, and prevents direct contractor-tradesman arrangements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revenue Model&lt;/strong&gt;: Earns through a &lt;strong&gt;rate spread&lt;/strong&gt; and &lt;strong&gt;annual membership fees&lt;/strong&gt; from both contractors and tradesmen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Call Centers&lt;/strong&gt;: Nine localized centers with reps manage project-tradesman assignments based on local laws and codes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competition&lt;/strong&gt;: A rival app focusing on &lt;strong&gt;cheaper labor&lt;/strong&gt; is gaining traction, appealing to cost-focused contractors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Core Use Case
&lt;/h2&gt;

&lt;p&gt;There is only one core use case - TradeMe is a system for matching &lt;br&gt;
tradesmen to contractors and projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Anti Design Effort
&lt;/h2&gt;

&lt;p&gt;The following figure is the anti design which needs to be avoided at any cost. This is merely based on functional decomposition.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx11tenjnrui3nr539b58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx11tenjnrui3nr539b58.png" alt=" " width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Who&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tradesmen&lt;/strong&gt;: Independent, self-employed workers with specialized skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contractors&lt;/strong&gt;: General contractors who hire tradesmen for specific tasks on construction projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TradeMe Reps&lt;/strong&gt;: Account representatives who manage matching and scheduling via call centers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Education Centers&lt;/strong&gt;: Institutions providing certification and continuing education for tradesmen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background Processes&lt;/strong&gt;: Automated system functions like payment scheduling and regulatory reporting.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Membership&lt;/strong&gt;: Both tradesmen and contractors register and pay to use the platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marketplace&lt;/strong&gt;: A digital platform where contractors post projects and tradesmen offer services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certificates &amp;amp; Training&lt;/strong&gt;: Tracks qualifications and ongoing training requirements for tradesmen.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Searching&lt;/strong&gt;: Tradesmen and contractors use the platform to find each other based on skills, availability, and rates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regulatory Compliance&lt;/strong&gt;: Ensures wages, taxes, certifications, and safety standards are met.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access to Resources&lt;/strong&gt;: Provides tools for scheduling, reporting, and payment handling.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Where&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Database&lt;/strong&gt;: Stores regional data specific to each call center’s jurisdiction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud&lt;/strong&gt;: Hosts centralized application logic, user data, and scheduling algorithms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other Systems&lt;/strong&gt;: Interfaces with regulatory bodies, educational institutions, and financial systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Areas of Volatility
&lt;/h1&gt;

&lt;p&gt;The core idea behind decomposition is to identify &lt;strong&gt;areas of volatility&lt;/strong&gt; — parts of the system likely to change — and encapsulate them to reduce the impact of change. The TradeMe design team carefully analyzed these volatilities and mapped them to specific architectural components. Here's a summary:&lt;/p&gt;




&lt;h3&gt;
  
  
  🧩 &lt;strong&gt;Key Observations from Volatility Analysis&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Volatility ≠ Variability&lt;/strong&gt;: For example, &lt;em&gt;tradesman attributes&lt;/em&gt; may vary (e.g., adding skills) but do not impact architecture significantly, so it's not volatile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volatility Requires Clarity&lt;/strong&gt;: Each candidate must be examined to determine &lt;em&gt;why&lt;/em&gt; it's volatile and &lt;em&gt;what risk&lt;/em&gt; it introduces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some volatilities are external&lt;/strong&gt;: For instance, payments may change frequently, but since TradeMe doesn’t implement its own payment system, it's treated as an external &lt;strong&gt;Resource&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧱 &lt;strong&gt;Identified Areas of Volatility and Their Encapsulation&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Volatile Area&lt;/th&gt;
&lt;th&gt;Encapsulated In&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client Applications&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Client Application&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Different UI tech, devices, access methods; volatile interfaces.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Membership Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Membership Manager&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Adding/removing users, benefits; varies by locale.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fees and Revenue Models&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Market Manager&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;How the system makes money is changeable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Project Definitions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Market Manager&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Size and scope impact workflows; central to matching logic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dispute Resolution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Membership Manager&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Must handle fraud and misunderstandings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Matching and Approvals&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Search Engine &amp;amp; Market Manager&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Matching logic and search criteria both volatile.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Education Workflow&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Education Manager&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Scheduling, searching for training; certification required.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Certifications &amp;amp; Regulations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Regulation Engine&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Rules change frequently by region or over time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reports &amp;amp; Auditing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Regulation Engine&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Compliance-driven volatility.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Localization (Language, UI)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Client Applications &amp;amp; Regulation Engine&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Can affect UI and regulatory compliance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;External Resources (e.g., Payments)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Resources&lt;/em&gt; and &lt;em&gt;ResourceAccess&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Store data and connect to systems with volatile access tech.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment Strategies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Message Bus &amp;amp; Subsystems&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Geographic, cloud/on-premise, and modular deployment needs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication &amp;amp; Authorization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Security Utility&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Flexible and diverse in real-world scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  📌 Design Insight
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Not all volatile aspects deserve their own component; grouping them logically (like in a &lt;em&gt;Manager&lt;/em&gt;) avoids architectural complexity.&lt;/li&gt;
&lt;li&gt;If a proposed decomposition leads to a tangled system or asymmetry, it’s a sign of poor design.&lt;/li&gt;
&lt;li&gt;Volatility-based decomposition aligns the system with business risk and adaptability.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This approach ensures that changes in business needs or external conditions have a localized impact, preserving the system’s stability and maintainability.&lt;/p&gt;

&lt;h1&gt;
  
  
  Static Architecture
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhalypjfoggmerwt39la5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhalypjfoggmerwt39la5.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some components dependency diagrams
&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.amazonaws.com%2Fuploads%2Farticles%2F1f69ewmnw2pn7swz40im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f69ewmnw2pn7swz40im.png" alt=" " width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  The Add Tradesman/Contractor call chain
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frthb6j60qm48pi8yoxn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frthb6j60qm48pi8yoxn0.png" alt=" " width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Request Tradesman call chains (until matching)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t5ci72sfpsrniaogwc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t5ci72sfpsrniaogwc2.png" alt=" " width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Call chains for the Match Tradesman use case
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfn80kndjsx84hk5xiw8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfn80kndjsx84hk5xiw8.png" alt=" " width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Call chains for the Assign Tradesman use case
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2muedanttlvpqoqath9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2muedanttlvpqoqath9l.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Call chains for the Terminate Tradesman use case
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7i61fqd49m688w0vp1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7i61fqd49m688w0vp1v.png" alt=" " width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Call chains for the Pay Tradesman use case
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faq9l4nsgjassdubmjlqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faq9l4nsgjassdubmjlqv.png" alt=" " width="670" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Call chains for the Create Project use case
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd335yqs78oeuz339tp3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd335yqs78oeuz339tp3w.png" alt=" " width="568" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Call chains for the Close Project use case
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyl0yz9t31sku5xqvenm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyl0yz9t31sku5xqvenm1.png" alt=" " width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;System design is not merely an academic exercise or a diagramming ritual — it's the art of managing &lt;strong&gt;change&lt;/strong&gt;. Through this series, we’ve consistently reinforced one truth: &lt;strong&gt;volatility is the compass of good architecture&lt;/strong&gt;. By identifying and encapsulating the parts of a system most likely to change, we build not only for functionality today, but for adaptability tomorrow.&lt;/p&gt;

&lt;p&gt;Using &lt;em&gt;TradeMe&lt;/em&gt; as a running example, we’ve explored how to decompose a system based on business-driven change vectors, not arbitrary technical boundaries. We've learned to avoid the traps of functional decomposition and instead think in terms of &lt;strong&gt;clients, managers, engines, and resources&lt;/strong&gt;, each aligned to a specific responsibility in the system.&lt;/p&gt;

&lt;p&gt;While this is the end of the series, it should be the beginning of a new lens through which you view system design. Design iteratively, build incrementally, and always measure your architecture against the axis of volatility. That is how software stays simple, stable, and scalable — even in the face of constant change.&lt;/p&gt;

&lt;p&gt;Thanks for reading every Sunday. &lt;/p&gt;

&lt;p&gt;Here are links to previous articles in case you missed them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62"&gt;Principles of Volatility-Based Decomposition in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Template for System Design Using ‘The Method’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b"&gt;Template for System Design Using ‘The Method’: Part II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/design-donts-in-system-design-with-the-method-2jcf"&gt;Design Don’ts in System Design with ‘The Method’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-isnt-about-requirements-its-about-change-2h70"&gt;System Design Isn’t About Requirements — It’s About Change&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>System Design Isn’t About Requirements — It’s About Change</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sun, 13 Jul 2025 07:33:42 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/system-design-isnt-about-requirements-its-about-change-2h70</link>
      <guid>https://dev.to/ujjwall-r/system-design-isnt-about-requirements-its-about-change-2h70</guid>
      <description>&lt;p&gt;Welcome to another Sunday Blog on System Design.&lt;br&gt;
This Sunday, we’ll explore how to deal will requirements and changes while designing a system.&lt;/p&gt;

&lt;p&gt;Here are the rules we've already summarized. As I often say:&lt;br&gt;
Learn the rules, follow the rules — and only once you're good at it, should you even think about bending them.&lt;/p&gt;

&lt;p&gt;I suggest going through the these two articles to fully grasp the ideas discussed here: &lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Part 1&lt;/a&gt; | &lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b"&gt;Part 2&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers? What are different use cases?
&lt;em&gt;(Remember: Almost always, these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;layers given in the template should correspond to 4 question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client : &lt;strong&gt;Who&lt;/strong&gt; interacts withe system&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers : &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Engines : &lt;strong&gt;How&lt;/strong&gt; system performs the business logic&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;ResourceAccess : &lt;strong&gt;How&lt;/strong&gt; system access the resources &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Resource : &lt;strong&gt;Where&lt;/strong&gt; is the system state&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Validate if your design follows the &lt;strong&gt;golden ratio (Manager:Engine)&lt;/strong&gt;. Some valid ratios: 1:(0/1), 2:1, 3:2, 5:3.&lt;br&gt;&lt;br&gt;
More than 5 Managers? You’re likely going wrong.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volatility decreases&lt;/strong&gt; from top to bottom, while &lt;strong&gt;reusability increases&lt;/strong&gt; from top to bottom.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Slices are subsystems. &lt;strong&gt;No more than 3 Managers in a subsystem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design iteratively, build incrementally.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Design Don'ts&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;A Client should not call multiple Managers for a single use case.&lt;/li&gt;
&lt;li&gt;A Client must not call Engines.&lt;/li&gt;
&lt;li&gt;Managers must not queue calls to more than one Manager in the same use case.
The need to have two (or more) Managers respond to a queued call is a strong indication that more Managers (and maybe all of them) would need to respond — so you should use a Pub/Sub Utility service instead.&lt;/li&gt;
&lt;li&gt;Engines and &lt;code&gt;ResourceAccess&lt;/code&gt; services do not receive queued calls.&lt;/li&gt;
&lt;li&gt;Clients, Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, or &lt;code&gt;Resource&lt;/code&gt; components do not publish events.&lt;/li&gt;
&lt;li&gt;Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, and &lt;code&gt;Resources&lt;/code&gt; do not subscribe to events. This must be done in a Client or a Manager.&lt;/li&gt;
&lt;li&gt;Engines never call each other.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ResourceAccess&lt;/code&gt; services never call each other.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Requirements and Changes
&lt;/h2&gt;

&lt;p&gt;Requirements change. Accept it—that’s what requirements do.&lt;/p&gt;

&lt;p&gt;Changing requirements drive demand for software professionals, ensuring job security and better compensation.&lt;/p&gt;

&lt;p&gt;Designing systems strictly based on initial requirements is a flawed and painful approach. Despite being a common practice, it often leads to failure because requirements are inherently incomplete, inaccurate, or subject to change. Capturing every use case up front is nearly impossible, and even if it were done perfectly, changes are inevitable. Designing against rigid requirements leads to wasted effort, rework, and frustration. Instead, systems should be built to accommodate change, as designing against static requirements is ultimately futile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Use Case
&lt;/h2&gt;

&lt;p&gt;In any system, most use cases are simply variations of a few essential behaviors. These essential behaviors are called core use cases, which represent the fundamental business needs of the system and rarely change. All other use cases—such as error handling, customer-specific adaptations, or incomplete scenarios—are non-core and change frequently.&lt;/p&gt;

&lt;p&gt;Despite a system potentially having hundreds of use cases, there are usually only 1 to 5 core use cases. These are not always clearly stated in requirement documents and must be discovered through analysis and abstraction. Identifying core use cases is a key responsibility of the architect, often requiring iteration and collaboration with stakeholders. While you shouldn't design directly against detailed requirements, analyzing them helps reveal what’s truly core and what is volatile.&lt;/p&gt;

&lt;p&gt;As an architect, your primary goal is to identify the smallest set of components needed to support all core use cases. Since non-core use cases are just variations of these, they can be handled by different interactions among the same components—not by changing the architecture itself.&lt;/p&gt;

&lt;p&gt;This approach is called composable design. It focuses on building flexible, reusable components rather than targeting specific use cases, which are often incomplete, inconsistent, and subject to change. Implementation-level changes (like integration logic inside managers) may occur, but the architecture remains stable.&lt;/p&gt;

&lt;p&gt;Composable design makes systems resilient to requirement changes and enables validation by checking if all core use cases can be satisfied through specific component interactions. This can be done with call chain diagrams, which show how components interact to fulfill a use case, offering a practical way to verify the design without needing perfect or complete requirements.&lt;/p&gt;

&lt;p&gt;Here is an example of call chain diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjwsar571t82rca7c1ok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjwsar571t82rca7c1ok.png" alt=" " width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Call chain diagrams are a fast and simple way to validate whether a system design can support a specific use case by showing interactions between components. However, they have limitations—they don’t show the order, duration, or frequency of calls, and can become unclear with complex interactions. Despite this, they are often sufficient for basic validation and are especially useful for communicating with nontechnical stakeholders due to their simplicity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smallest set
&lt;/h2&gt;

&lt;p&gt;As an architect, your mission is to design the smallest possible set of components that can support all core use cases, minimizing complexity and development effort. "Smallest" doesn’t mean a single monolithic component, nor does it mean one component per use case—both extremes are poor designs due to internal complexity or high integration cost.&lt;/p&gt;

&lt;p&gt;Instead, aim for an architecture with around 10–20 components, which strikes a balance between simplicity and flexibility. This range, seen across various systems (like the human body or a car), is powerful due to combinatorics: a small number of reusable components can be combined in many ways to support numerous use cases.&lt;/p&gt;

&lt;p&gt;Good architecture encapsulates volatility and uses logical layers (e.g., Managers, Engines, Resources) to remain adaptable as requirements evolve. Once you’ve reached a component set that can’t be reasonably reduced further without compromising clarity or function, you’ve found your optimal design—your smallest set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Duration
&lt;/h2&gt;

&lt;p&gt;Identifying core use cases and areas of volatility may take weeks or months, but that’s part of requirements analysis, not design. Once this groundwork is done, producing a valid design using composable principles (like The Method) should take a day or a week at most—and with experience, possibly just a few hours. The key idea is that design itself is fast when you're clear on what the system truly needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Change
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;fundamental rule of system design&lt;/strong&gt; is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Features are always aspects of integration, not implementation.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means features emerge not from isolated code or components, but from how those components are combined. It's a &lt;strong&gt;universal and fractal rule&lt;/strong&gt;—whether it's a car transporting you or a laptop enabling word processing, the feature arises from integration, not any single part.&lt;/p&gt;

&lt;p&gt;Trying to &lt;strong&gt;implement features directly&lt;/strong&gt; (as if they were standalone pieces of code) goes against how systems truly work. Functional decomposition, which focuses on coding features in isolation, leads to &lt;strong&gt;rigid, fragile systems&lt;/strong&gt; that are hard to change—since changes affect many areas at once.&lt;/p&gt;

&lt;p&gt;Fighting change by deferring it or dismissing user needs &lt;strong&gt;kills a system&lt;/strong&gt;. Customers need immediate solutions, not promises for the next release. A system that can't adapt quickly will be abandoned, even if it's still technically alive. To keep a system &lt;strong&gt;alive and relevant&lt;/strong&gt;, architecture must embrace change—and fast response to evolving requirements is essential.&lt;/p&gt;

&lt;p&gt;The key to handling change is not avoiding it—but &lt;strong&gt;containing its impact&lt;/strong&gt;. In a well-architected system using &lt;strong&gt;volatility-based decomposition&lt;/strong&gt; (as defined in &lt;em&gt;The Method&lt;/em&gt;), changes typically affect &lt;strong&gt;use cases&lt;/strong&gt;, which are implemented by &lt;strong&gt;Managers&lt;/strong&gt;. While a Manager might need to be rewritten due to a change in behavior, the core components it integrates—&lt;strong&gt;Engines, ResourceAccess, Resources, Utilities, and Clients&lt;/strong&gt;—remain intact.&lt;/p&gt;

&lt;p&gt;This structure ensures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Managers are expendable&lt;/strong&gt; and cheap to rewrite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most of the system's effort and complexity&lt;/strong&gt; lies in the reusable components &lt;strong&gt;beneath the Manager&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;By preserving and reusing these components, you &lt;strong&gt;contain the cost and effort&lt;/strong&gt; of adapting to change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach allows rapid adaptation without major rewrites—&lt;strong&gt;true agility&lt;/strong&gt;. You don’t redesign the whole system when a requirement changes—you just rewire the existing pieces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updated rules
&lt;/h2&gt;

&lt;p&gt;Lets update the set of rules we learnt. We will keep these on finger tips while designing system in future articles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers? What are different use cases?
&lt;em&gt;(Remember: Almost always, these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;layers given in the template should correspond to 4 question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client : &lt;strong&gt;Who&lt;/strong&gt; interacts withe system&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers : &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Engines : &lt;strong&gt;How&lt;/strong&gt; system performs the business logic&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;ResourceAccess : &lt;strong&gt;How&lt;/strong&gt; system access the resources &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Resource : &lt;strong&gt;Where&lt;/strong&gt; is the system state&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Validate if your design follows the &lt;strong&gt;golden ratio (Manager:Engine)&lt;/strong&gt;. Some valid ratios: 1:(0/1), 2:1, 3:2, 5:3.&lt;br&gt;&lt;br&gt;
More than 5 Managers? You’re likely going wrong.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volatility decreases&lt;/strong&gt; from top to bottom, while &lt;strong&gt;reusability increases&lt;/strong&gt; from top to bottom.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Slices are subsystems. &lt;strong&gt;No more than 3 Managers in a subsystem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design iteratively, build incrementally.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design with the smallest set of reusable components needed to support core use cases. A good architecture integrates ~10–20 components to support them composably. Features are outcomes of integration, not implementation.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Design Don'ts&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;A Client should not call multiple Managers for a single use case.&lt;/li&gt;
&lt;li&gt;A Client must not call Engines.&lt;/li&gt;
&lt;li&gt;Managers must not queue calls to more than one Manager in the same use case.
The need to have two (or more) Managers respond to a queued call is a strong indication that more Managers (and maybe all of them) would need to respond — so you should use a Pub/Sub Utility service instead.&lt;/li&gt;
&lt;li&gt;Engines and &lt;code&gt;ResourceAccess&lt;/code&gt; services do not receive queued calls.&lt;/li&gt;
&lt;li&gt;Clients, Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, or &lt;code&gt;Resource&lt;/code&gt; components do not publish events.&lt;/li&gt;
&lt;li&gt;Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, and &lt;code&gt;Resources&lt;/code&gt; do not subscribe to events. This must be done in a Client or a Manager.&lt;/li&gt;
&lt;li&gt;Engines never call each other.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ResourceAccess&lt;/code&gt; services never call each other.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Starting next week, we’ll begin exploring real-world examples of software design using The Method.&lt;br&gt;
See you next Sunday!&lt;/p&gt;

&lt;p&gt;Here are links to previous articles in case you missed them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62"&gt;Principles of Volatility-Based Decomposition in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Template for System Design Using ‘The Method’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b"&gt;Template for System Design Using ‘The Method’: Part II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/design-donts-in-system-design-with-the-method-2jcf"&gt;Design Don’ts in System Design with ‘The Method’&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>programming</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Design Don’ts in System Design with ‘The Method’</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sun, 06 Jul 2025 07:38:22 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/design-donts-in-system-design-with-the-method-2jcf</link>
      <guid>https://dev.to/ujjwall-r/design-donts-in-system-design-with-the-method-2jcf</guid>
      <description>&lt;p&gt;&lt;strong&gt;Welcome to another Sunday Blog on System Design.&lt;/strong&gt;&lt;br&gt;
This Sunday, we’ll explore the &lt;strong&gt;don’ts&lt;/strong&gt; to keep in mind when designing a system using &lt;em&gt;The Method&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here are the rules we've already summarized. As I often say:&lt;br&gt;
&lt;strong&gt;Learn the rules, follow the rules — and only once you're good at it, should you even think about bending them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I suggest going through the last two articles to fully grasp the ideas discussed here: &lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Part 1&lt;/a&gt; | &lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b"&gt;Part 2&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers? What are different use cases?
&lt;em&gt;(Remember: Almost always, these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;layers given in the template should correspond to 4 question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client : &lt;strong&gt;Who&lt;/strong&gt; interacts withe system&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers : &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Engines : &lt;strong&gt;How&lt;/strong&gt; system performs the business logic&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;ResourceAccess : &lt;strong&gt;How&lt;/strong&gt; system access the resources &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Resource : &lt;strong&gt;Where&lt;/strong&gt; is the system state&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Validate if your design follows the &lt;strong&gt;golden ratio (Manager:Engine)&lt;/strong&gt;. Some valid ratios: 1:(0/1), 2:1, 3:2, 5:3.&lt;br&gt;&lt;br&gt;
More than 5 Managers? You’re likely going wrong.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volatility decreases&lt;/strong&gt; from top to bottom, while &lt;strong&gt;reusability increases&lt;/strong&gt; from top to bottom.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Slices are subsystems. &lt;strong&gt;No more than 3 Managers in a subsystem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design iteratively, build incrementally.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now let's see how these don'ts are listed by opening a closed architecture to a semi-closed one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open and Closed Architecture
&lt;/h2&gt;

&lt;p&gt;In an open architecture, any component can call any other component in any layer. The flexibility is there, but it's a bad design. There is too much coupling, and encapsulation is heavily sacrificed.&lt;/p&gt;

&lt;p&gt;There are only two problems in Software Engineering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependency management&lt;/li&gt;
&lt;li&gt;Information hiding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both problems are intensified when we use an open architecture. Even calling horizontally (intra-layer) creates some amount of coupling, so it should be avoided.&lt;/p&gt;

&lt;p&gt;On the other hand, a closed architecture restricts access to only the immediate lower layer, allowing limited adjacent-layer interactions without skipping layers. Closed architecture promotes decoupling by trading flexibility for encapsulation. In general, that is a better trade than the other way around.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semi-Closed/Semi-Open Architecture
&lt;/h2&gt;

&lt;p&gt;A semi-closed/semi-open architecture allows calling more than one layer down. It still does not allow calling up or sideways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E.g.&lt;/strong&gt; A Manager can call a &lt;code&gt;ResourceAccess&lt;/code&gt; component if there is nothing to encapsulate in an Engine layer.&lt;/p&gt;

&lt;p&gt;This method relaxes the closed architecture with some don'ts and do's, making sure encapsulation is not compromised at the cost of flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flexibilities Allowed in 'The Method'
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Calling Utilities
&lt;/h3&gt;

&lt;p&gt;In a closed architecture, placing Utilities like Logging, Security, or Diagnostics is problematic because every component may need them. If Utilities are assigned to a specific layer, access becomes limited. To solve this, &lt;em&gt;The Method&lt;/em&gt; introduces a vertical utility bar that cuts across all layers, making Utilities accessible to every component.&lt;br&gt;
&lt;strong&gt;E.g.&lt;/strong&gt; Logging, Authentication, Security&lt;/p&gt;

&lt;h4&gt;
  
  
  Litmus Test for Utility
&lt;/h4&gt;

&lt;p&gt;To avoid the misuse of utilities by developers, there is a simple litmus test:&lt;br&gt;
Can the component plausibly be used in any other system, such as a smart cappuccino machine?&lt;/p&gt;

&lt;p&gt;For example, a smart cappuccino machine could use a Security service to check if the user is authorized to drink coffee. Similarly, it may want to log how much coffee office workers drink, run diagnostics, and publish events (e.g., running low on coffee) using a Pub/Sub service.&lt;/p&gt;

&lt;p&gt;Each of these needs justifies encapsulation in a Utility service. In contrast, you’d be hard-pressed to explain why a cappuccino machine needs a mortgage interest calculation service as a Utility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calling ResourceAccess by Business Logic
&lt;/h3&gt;

&lt;p&gt;Managers and Engines can access &lt;code&gt;ResourceAccess&lt;/code&gt; since they’re in the same layer. There might be cases where Managers need to reach Resources even without using Engines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managers Calling Engines
&lt;/h3&gt;

&lt;p&gt;Managers can call Engines directly because Engines serve as strategies within Manager workflows. This separation is more about design detail than architectural structure. These calls aren't lateral, as Engines function in a different dimension from Managers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Queued Manager-to-Manager
&lt;/h4&gt;

&lt;p&gt;While Managers should not call other Managers directly (i.e., sideways), a Manager can queue a call to another Manager.&lt;/p&gt;

&lt;p&gt;Technically, the queue itself is a Resource, and the publisher acts like a &lt;code&gt;ResourceAccess&lt;/code&gt; component. The queue listener is effectively another Client in the system, calling downward to the receiving Manager. No true sideways call actually takes place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Don'ts
&lt;/h2&gt;

&lt;p&gt;Treat any violation of these rules as a red flag and investigate further to see what you might be missing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Client should not call multiple Managers for a single use case.&lt;/li&gt;
&lt;li&gt;A Client must not call Engines.&lt;/li&gt;
&lt;li&gt;Managers must not queue calls to more than one Manager in the same use case.
The need to have two (or more) Managers respond to a queued call is a strong indication that more Managers (and maybe all of them) would need to respond — so you should use a Pub/Sub Utility service instead.&lt;/li&gt;
&lt;li&gt;Engines and &lt;code&gt;ResourceAccess&lt;/code&gt; services do not receive queued calls.&lt;/li&gt;
&lt;li&gt;Clients, Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, or &lt;code&gt;Resource&lt;/code&gt; components do not publish events.&lt;/li&gt;
&lt;li&gt;Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, and &lt;code&gt;Resources&lt;/code&gt; do not subscribe to events. This must be done in a Client or a Manager.&lt;/li&gt;
&lt;li&gt;Engines never call each other.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ResourceAccess&lt;/code&gt; services never call each other.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Updated Rules
&lt;/h2&gt;

&lt;p&gt;Let's update the rules based on what we have discussed today. On top of that, I am adding an additional observation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There may not be internal symmetry inside a component like a Manager, but strive toward symmetry in the overall design.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers? What are different use cases?
&lt;em&gt;(Remember: Almost always, these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;layers given in the template should correspond to 4 question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client : &lt;strong&gt;Who&lt;/strong&gt; interacts withe system&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers : &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Engines : &lt;strong&gt;How&lt;/strong&gt; system performs the business logic&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;ResourceAccess : &lt;strong&gt;How&lt;/strong&gt; system access the resources &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Resource : &lt;strong&gt;Where&lt;/strong&gt; is the system state&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Validate if your design follows the &lt;strong&gt;golden ratio (Manager:Engine)&lt;/strong&gt;. Some valid ratios: 1:(0/1), 2:1, 3:2, 5:3.&lt;br&gt;&lt;br&gt;
More than 5 Managers? You’re likely going wrong.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volatility decreases&lt;/strong&gt; from top to bottom, while &lt;strong&gt;reusability increases&lt;/strong&gt; from top to bottom.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Slices are subsystems. &lt;strong&gt;No more than 3 Managers in a subsystem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design iteratively, build incrementally.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Design Don'ts&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;A Client should not call multiple Managers for a single use case.&lt;/li&gt;
&lt;li&gt;A Client must not call Engines.&lt;/li&gt;
&lt;li&gt;Managers must not queue calls to more than one Manager in the same use case.
The need to have two (or more) Managers respond to a queued call is a strong indication that more Managers (and maybe all of them) would need to respond — so you should use a Pub/Sub Utility service instead.&lt;/li&gt;
&lt;li&gt;Engines and &lt;code&gt;ResourceAccess&lt;/code&gt; services do not receive queued calls.&lt;/li&gt;
&lt;li&gt;Clients, Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, or &lt;code&gt;Resource&lt;/code&gt; components do not publish events.&lt;/li&gt;
&lt;li&gt;Engines, &lt;code&gt;ResourceAccess&lt;/code&gt;, and &lt;code&gt;Resources&lt;/code&gt; do not subscribe to events. This must be done in a Client or a Manager.&lt;/li&gt;
&lt;li&gt;Engines never call each other.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ResourceAccess&lt;/code&gt; services never call each other.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Starting next week, we’ll begin exploring about the use cases and requirements.&lt;br&gt;
See you next Sunday!&lt;/p&gt;

&lt;p&gt;Here are links to previous articles in case you missed them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62"&gt;Principles of Volatility-Based Decomposition in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Template for System Design Using ‘The Method’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b"&gt;Template for System Design Using ‘The Method’: Part II&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>systemdesign</category>
      <category>software</category>
      <category>programming</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Template for System Design Using ‘The Method’: Part II</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sun, 29 Jun 2025 07:33:38 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b</link>
      <guid>https://dev.to/ujjwall-r/template-for-system-design-using-the-method-part-ii-5d5b</guid>
      <description>&lt;p&gt;Welcome to another Sunday article where we discuss &lt;strong&gt;System Design&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the first article in the series where I recommend the reader to read the previous article — &lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Template for System Design Using ‘The Method’&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are the rules we've already summarized. I keep repeating: we will &lt;strong&gt;learn&lt;/strong&gt; the rules, &lt;strong&gt;follow&lt;/strong&gt; the rules, and once we are good at it, &lt;strong&gt;only then&lt;/strong&gt; will we &lt;strong&gt;bend&lt;/strong&gt; the rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers?
&lt;em&gt;(Remember: these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now we will discuss some more &lt;strong&gt;aspects&lt;/strong&gt; of the template and update the rules.&lt;/p&gt;

&lt;h1&gt;
  
  
  Four Questions
&lt;/h1&gt;

&lt;p&gt;The layers given in the template should correspond to &lt;strong&gt;four questions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;: &lt;strong&gt;Who&lt;/strong&gt; interacts with the system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managers&lt;/strong&gt;: &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engines&lt;/strong&gt;: &lt;strong&gt;How&lt;/strong&gt; the system performs the business logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ResourceAccess&lt;/strong&gt;: &lt;strong&gt;How&lt;/strong&gt; the system accesses the resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource&lt;/strong&gt;: &lt;strong&gt;Where&lt;/strong&gt; the system state is stored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions can be asked both before initiating the design and while validating the design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1wlqu82rd4a3ax57247.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1wlqu82rd4a3ax57247.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the beginning, asking “what” helps list potential candidates for &lt;strong&gt;Managers&lt;/strong&gt;. But remember, components need not be perfect.&lt;/p&gt;

&lt;p&gt;Once done with the design, ask the questions again for validation:&lt;br&gt;
Are all your Clients “who,” with no trace of “what”?&lt;br&gt;
Are all the Managers “what,” without a smidgen of “who” or “where”?&lt;/p&gt;

&lt;p&gt;Again, the mapping of questions to layers will not be perfect. Some overlap may occur. However, if you're confident that the encapsulation of volatility is justified, there's no need to doubt that choice. If you're not convinced, the questions may indicate a red flag — a signal to revisit your decomposition.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Golden Ratio
&lt;/h1&gt;

&lt;p&gt;In the book &lt;em&gt;Righting Software&lt;/em&gt; by Juval Löwy, he shares observations from years of experience as a successful architect. I follow the same ratios as a source of truth for validations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 Manager → 0 or 1 Engine&lt;/li&gt;
&lt;li&gt;2 Managers → 1 Engine&lt;/li&gt;
&lt;li&gt;3 Managers → 2 Engines&lt;/li&gt;
&lt;li&gt;5 Managers → 3 Engines&lt;/li&gt;
&lt;li&gt;8 Managers → A lot! You've likely failed to decompose volatility. Redesign.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Volatility Decreases Top-Down, Reuse Increases
&lt;/h1&gt;

&lt;p&gt;Clients are more volatile than Managers. Engines are less volatile than Managers, and so on. A design in which volatility decreases down the layers is extremely valuable. Components in the lower layers often have more dependencies. If the components you depend on the most are also the most volatile, your system will implode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reuse&lt;/strong&gt; of services increases from top to bottom. Clients are hardly reusable. Managers are somewhat reusable — e.g., via both phone and web clients. Engines are even more reusable, as different use cases might share core logic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Services and Subsystems
&lt;/h1&gt;

&lt;p&gt;Group services by use case and divide them into &lt;strong&gt;slices&lt;/strong&gt;. A slice is a &lt;strong&gt;subsystem&lt;/strong&gt;. You'll get a deeper understanding in the next article, where I'll walk through an example.&lt;br&gt;
&lt;strong&gt;Make sure you don't have more than 3 Managers in a subsystem.&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.amazonaws.com%2Fuploads%2Farticles%2Fwsg7meg06yvqcy50yi9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsg7meg06yvqcy50yi9w.png" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developing a system like this can be done one slice/subsystem at a time.&lt;br&gt;
&lt;strong&gt;Design iteratively, build incrementally.&lt;/strong&gt;&lt;br&gt;
A component inside a subsystem cannot be released independently — it won't cover a complete use case. So release one &lt;strong&gt;subsystem&lt;/strong&gt; at a time during development.&lt;/p&gt;

&lt;h1&gt;
  
  
  Extensibility
&lt;/h1&gt;

&lt;p&gt;By extending the system, we &lt;strong&gt;do not&lt;/strong&gt; mean reopening components and developing them again. If you have designed correctly for extensibility, you can mostly leave existing parts untouched and extend the system holistically — by simply adding more slices or subsystems.&lt;/p&gt;

&lt;h1&gt;
  
  
  What Are Microservices Here?
&lt;/h1&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; assume each slice is a microservice. Creating a service per slice can result in an &lt;strong&gt;unnecessary number of microservices&lt;/strong&gt;, leading to excessive HTTP/TCP communications, unreliability, and complexity.&lt;/p&gt;

&lt;p&gt;Internal services like Engines and ResourceAccess should rely on fast, reliable, high-performance communication channels — such as TCP/IP, named pipes, IPC, domain sockets, Service Fabric remoting, custom in-memory interception chains, message queues, etc.&lt;/p&gt;

&lt;p&gt;A microservice can be a &lt;strong&gt;group of slices&lt;/strong&gt; if you have many of them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updated rules
&lt;/h1&gt;

&lt;p&gt;Let’s update the rules of the framework:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers? What are different use cases?
&lt;em&gt;(Remember: Almost always, these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;layers given in the template should correspond to 4 question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client : &lt;strong&gt;Who&lt;/strong&gt; interacts withe system&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers : &lt;strong&gt;What&lt;/strong&gt; is required of the system&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Engines : &lt;strong&gt;How&lt;/strong&gt; system performs the business logic&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;ResourceAccess : &lt;strong&gt;How&lt;/strong&gt; system access the resources &lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Resource : &lt;strong&gt;Where&lt;/strong&gt; is the system state&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Validate if your design follows the &lt;strong&gt;golden ratio (Manager:Engine)&lt;/strong&gt;. Some valid ratios: 1:(0/1), 2:1, 3:2, 5:3.&lt;br&gt;&lt;br&gt;
More than 5 Managers? You’re likely going wrong.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volatility decreases&lt;/strong&gt; from top to bottom, while &lt;strong&gt;reusability increases&lt;/strong&gt; from top to bottom.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Slices are subsystems. &lt;strong&gt;No more than 3 Managers in a subsystem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Design iteratively, build incrementally.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In the next article, I will make the given framework more solid with some don'ts and do's. Once we catch those, we then start delving into design examples.&lt;/p&gt;

&lt;p&gt;See you next Sunday!&lt;br&gt;
Stay Tuned!&lt;/p&gt;

&lt;p&gt;Here are links to previous articles in case you missed them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62"&gt;Principles of Volatility-Based Decomposition in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign"&gt;Template for System Design Using ‘The Method’&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Template for System Design Using ‘The Method’</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sat, 21 Jun 2025 09:41:48 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign</link>
      <guid>https://dev.to/ujjwall-r/template-for-system-design-using-the-method-3ign</guid>
      <description>&lt;p&gt;&lt;strong&gt;Welcome to another weekly article on System Design.&lt;/strong&gt; In this article, I will give you a template for how to design systems using &lt;em&gt;'The Method'&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As I’ve already stated: we are going to learn the rules, follow the rules, and once you are an expert — bend the rules.&lt;/p&gt;

&lt;p&gt;Let’s keep track of what we’ve learned so far, so everything stays at our fingertips even if you haven’t read the previous article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers?
&lt;em&gt;(Remember: these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s now start diving into the template.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Use Case
&lt;/h2&gt;

&lt;p&gt;A use case is an expression of required behavior — how the system is going to accomplish something to add business value. It describes the end-user interaction with the system or the system’s interaction with the user. It also illustrates system-to-system interactions and processing. It is always recommended to capture use cases graphically. Nothing communicates better and more simply than pictures.&lt;/p&gt;

&lt;p&gt;An activity diagram showing all possibilities can also be drawn.&lt;/p&gt;

&lt;p&gt;The two figures below show how a use case diagram (left) and an activity diagram (right) look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7s4sa2vyu0mgnf65clor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7s4sa2vyu0mgnf65clor.png" alt="Image" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should be noted that it is not feasible to draw activity diagrams for &lt;em&gt;all&lt;/em&gt; possible cases. So, only important ones should be covered, leaving the simple ones aside — they will be understood naturally through the layered approach we’re about to cover. Get ready for the ultimate framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layered Approach
&lt;/h2&gt;

&lt;p&gt;A layered approach is a better representation of systems and services. The encapsulations are layered:&lt;/p&gt;

&lt;p&gt;a) Each layer encapsulates the volatility of itself and of the layers below it, from the layers above.&lt;br&gt;
b) Within a layer, the services encapsulate volatility from each other. &lt;em&gt;(Reminder: by “services,” I do not mean microservices.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The following image is the same one I used to define a good design decision tree in the very first article. Don’t worry if you haven’t read it — but if you have, you’ll relate to 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.amazonaws.com%2Fuploads%2Farticles%2F0iyuq9ktzgmg9aejse5r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0iyuq9ktzgmg9aejse5r.png" alt="Image" width="800" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image below is taken from the book &lt;em&gt;Righting Software&lt;/em&gt; by Juval Löwy. I use the same color template while designing systems, and we’ll continue using it throughout the series:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktzlj9jyng87wt9ngyc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktzlj9jyng87wt9ngyc5.png" alt="Image" width="768" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should be obvious that the number of layers in a practical system is limited. These layers terminate at a resource layer — such as a database, file storage, or third-party API.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Services
&lt;/h2&gt;

&lt;p&gt;As I’ve already emphasized in previous articles: system design is not just tech — it is engineering.&lt;/p&gt;

&lt;p&gt;With service flow diagrams, the entire data flow can be understood very well. This is one of the key advantages of volatility-based decomposition. Designing in this layered manner makes service calls visualizable, giving us insights even before deployment — and certainly after some traffic is observed.&lt;/p&gt;

&lt;p&gt;Things like &lt;strong&gt;security&lt;/strong&gt;, &lt;strong&gt;scalability&lt;/strong&gt;, &lt;strong&gt;traffic&lt;/strong&gt;, &lt;strong&gt;throughput&lt;/strong&gt;, &lt;strong&gt;responsiveness&lt;/strong&gt;, &lt;strong&gt;consistency concerns&lt;/strong&gt;, and &lt;strong&gt;synchronization&lt;/strong&gt; can all be examined more clearly.&lt;/p&gt;
&lt;h2&gt;
  
  
  The General Template Framework for System Design
&lt;/h2&gt;

&lt;p&gt;Here is the general framework of &lt;em&gt;'The Method'&lt;/em&gt;. We will discuss each section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2z1i3a968myf9an4ta9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2z1i3a968myf9an4ta9.png" alt="Image" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Client
&lt;/h3&gt;

&lt;p&gt;These are the entry points to the system. Make sure your client is only a client — not a system. The client should not encapsulate business logic. All clients should use the same entry point to the system. A phone app and a web app should not be calling different backends.&lt;/p&gt;
&lt;h4&gt;
  
  
  Volatility by client:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Axis 1 (What can change for existing customers?):&lt;/strong&gt; Different users may demand different accessibility options, dark mode, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Axis 2 (What differs across customers?):&lt;/strong&gt; It can be a desktop app, Android app, or just an API interface. Technology may vary — React, .NET, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The Business Logic Layer
&lt;/h3&gt;

&lt;p&gt;This layer encapsulates the system’s use cases — i.e., what the system is supposed to do from a business perspective. The components here are &lt;strong&gt;Managers&lt;/strong&gt; and &lt;strong&gt;Engines&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manager&lt;/strong&gt;: Encapsulates volatility in the &lt;strong&gt;sequence&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engine&lt;/strong&gt;: Encapsulates volatility in the &lt;strong&gt;activity&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Manager can utilize zero or more Engines to complete a business task.&lt;/p&gt;

&lt;p&gt;For example, a car starting system may look like:&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="nc"&gt;MovementManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And within the Manager:&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="nc"&gt;PreparingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ConfirmAdjustSeat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;PreparingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AdjustSideGlass&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;PreparingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CloseWindow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;DrivingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AdjustBrake&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;DrivingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AdjustGear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;DrivingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AdjustAccelerator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;DrivingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AdjustClutch&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;DrivingEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StartICEngine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the Manager (&lt;code&gt;MovementManager&lt;/code&gt;) is utilizing multiple Engines — &lt;code&gt;PreparingEngine&lt;/code&gt;, &lt;code&gt;DrivingEngine&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ensure that two managers do not use two &lt;em&gt;different&lt;/em&gt; engines to do the &lt;em&gt;same&lt;/em&gt; job. That’s a symptom of &lt;strong&gt;functional decomposition&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Engines can be reused between Managers, as the same activity might appear in different use cases. Design Engines with &lt;strong&gt;reuse&lt;/strong&gt; in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Resource Access Layer
&lt;/h3&gt;

&lt;p&gt;Components here are called &lt;strong&gt;ResourceAccess&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Volatility by ResourceAccess:
&lt;/h4&gt;

&lt;p&gt;This layer defines &lt;em&gt;how&lt;/em&gt; to access a resource — but it should not expose contracts like &lt;code&gt;Read()&lt;/code&gt;, &lt;code&gt;Write()&lt;/code&gt;, &lt;code&gt;Open()&lt;/code&gt;, &lt;code&gt;Close()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead, it should use &lt;strong&gt;business verbs&lt;/strong&gt;, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CurrentFuelVolume()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetMusicPlaylists()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using database-style contracts creates tight coupling — any change in the resource's tech affects all upper layers. Avoid this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ResourceAccess&lt;/strong&gt; components may be reused across Engines or Managers needing access to the same resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Resource Layer
&lt;/h3&gt;

&lt;p&gt;This contains the actual physical resources — databases, file systems, caches, third-party APIs, etc. It encapsulates &lt;strong&gt;the tech&lt;/strong&gt; being used. This can also include external systems like payment APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utility
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Utilities&lt;/strong&gt; vertical bar (on the right of the diagram) includes common infrastructure services that most systems need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Messaging Queue&lt;/li&gt;
&lt;li&gt;Pub/Sub, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rechecking the Layer Classification
&lt;/h2&gt;

&lt;p&gt;Once you’ve classified your layers and components, ask these questions. If the answers are “yes,” you’ve done volatility-based decomposition — not functional decomposition.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are the &lt;strong&gt;names descriptive&lt;/strong&gt;? E.g., &lt;code&gt;SomeManager&lt;/code&gt;, &lt;code&gt;DoSomethingEngine&lt;/code&gt;, &lt;code&gt;SomethingResourceAccess&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;Managers&lt;/strong&gt;, the prefix should be a &lt;strong&gt;noun&lt;/strong&gt; tied to the encapsulated volatility (e.g., &lt;code&gt;MovementManager&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;Engines&lt;/strong&gt;, the prefix should be a &lt;strong&gt;noun&lt;/strong&gt; describing the activity (e.g., &lt;code&gt;DrivingEngine&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;ResourceAccess&lt;/strong&gt;, the prefix should be a &lt;strong&gt;noun&lt;/strong&gt; related to the resource (e.g., &lt;code&gt;FuelResourceAccess&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gerunds&lt;/strong&gt; (nouns ending in -ing) should only be used with Engines. Their use elsewhere usually signals functional decomposition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic business verbs&lt;/strong&gt; should &lt;em&gt;not&lt;/em&gt; be used in service names — only as operation names in ResourceAccess contracts.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Learn these rules&lt;/strong&gt;. They ensure we don’t fall into the trap of functional decomposition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  I’m Updating the Rules to Carry Forward
&lt;/h2&gt;

&lt;p&gt;Let’s keep the rules on our fingertips for the next article:&lt;/p&gt;

&lt;h3&gt;
  
  
  Updated Rules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities), and remember: a good system design speaks — through how components interact.&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system.&lt;/li&gt;
&lt;li&gt;Decompose based on &lt;strong&gt;volatility&lt;/strong&gt; — list the areas of volatility.&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component.&lt;/li&gt;
&lt;li&gt;List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers?
&lt;em&gt;(Remember: these axes are independent.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Verify whether a solution/component is masquerading as a requirement. Verify it is not variability. A volatility is not something that can be handled with if-else; that’s variability.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;strong&gt;layered approach&lt;/strong&gt; and proper naming convention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names should be descriptive and avoid atomic business verbs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;NounOfVolatility&amp;gt;Manager&lt;/code&gt;, &lt;code&gt;&amp;lt;Gerund&amp;gt;Engine&lt;/code&gt;, &lt;code&gt;&amp;lt;NounOfResource&amp;gt;Access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Atomic verbs should only be used for operation names, not service names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;See you next Sunday in another article where I will dive with examples. Stay Tuned!&lt;/p&gt;

&lt;p&gt;Here are links to previous articles in case you missed them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62"&gt;Principles of Volatility-Based Decomposition in System Design&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>Principles of Volatility-Based Decomposition in System Design</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sat, 14 Jun 2025 19:18:05 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62</link>
      <guid>https://dev.to/ujjwall-r/principles-of-volatility-based-decomposition-in-system-design-2b62</guid>
      <description>&lt;p&gt;Welcome to another Sunday Blog on System Design. This Sunday, we will look into the principles of doing a volatility-based decomposition. Once we are done understanding and memorizing the rules, I will start transferring the framework for doing System Design as explained by Juval Löwy in his book &lt;em&gt;Righting Software&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As I’ve already stated: we are going to learn the rules, follow the rules, and once you are an expert — bend the rules.&lt;/p&gt;

&lt;p&gt;Let’s keep track of what we’ve learned so far, to keep things at our fingertips even if you haven’t read the previous article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A good system design speaks (how components interact)&lt;/li&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities)&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system&lt;/li&gt;
&lt;li&gt;Reduce coupling between services as much as possible&lt;/li&gt;
&lt;li&gt;Decompose based on volatility — list the areas of volatility&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component&lt;/li&gt;
&lt;li&gt;Symmetry is a good sign of good design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we start understanding and implementing the framework in the next article, we will verify the design using the memorized rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  Listing the Volatility — Tools to Identify Them
&lt;/h2&gt;

&lt;p&gt;Once a project starts, the requirements themselves are communicated in terms of functionalities — "the system should do so and so." It's the role of the architect to analyze the requirements and list the volatilities.&lt;br&gt;
Another way to figure out the volatility is through customer interviews.&lt;/p&gt;

&lt;h3&gt;
  
  
  Volatile vs Variable
&lt;/h3&gt;

&lt;p&gt;Volatility refers to changes that affect several components in the system, while variability refers to changes that can be handled in code using &lt;code&gt;if-else&lt;/code&gt;. So it’s necessary to understand the difference between volatility and variability.&lt;/p&gt;




&lt;h3&gt;
  
  
  Axes of Volatility: Technique to Identify Volatility
&lt;/h3&gt;

&lt;p&gt;One axis of change is &lt;strong&gt;over time for existing customers&lt;/strong&gt; — how their requirements evolve. The business or expectations of the software’s consumer may shift over time.&lt;/p&gt;

&lt;p&gt;The second axis of change occurs &lt;strong&gt;at the same time across different customers&lt;/strong&gt;. Imagine freezing time and analyzing the second axis: Are all customers using the application in exactly the same way? What are the different use cases, and how can they be accommodated?&lt;/p&gt;

&lt;p&gt;If something does not map to either axis of volatility, you should not encapsulate it at all — there should be no building block in your system to represent it. Creating such a block likely indicates functional decomposition.&lt;/p&gt;

&lt;p&gt;These axes can serve as references during customer interviews to ask better questions, list down requirements, and later analyze volatility.&lt;/p&gt;




&lt;p&gt;As you can see in the figure below, your design should follow a lifecycle while refactoring. Design iteratively like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav7fh972s2pz1pam5jzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav7fh972s2pz1pam5jzv.png" alt=" " width="790" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Figure A&lt;/strong&gt;, you come up with one component — but that’s not good. Then, by analyzing along the axes of volatility, you realize that some things can be encapsulated into separate components. The result is &lt;strong&gt;Figure B&lt;/strong&gt;. You keep factoring the design until all volatilities are encapsulated.&lt;/p&gt;

&lt;p&gt;Another way to find volatility is by examining how competitors have designed their systems. That can reveal alternative approaches that can be explored across both axes.&lt;/p&gt;




&lt;h4&gt;
  
  
  Almost always, the axes should be independent
&lt;/h4&gt;

&lt;p&gt;When we say the axes of volatility are independent, we mean the changes we consider using &lt;strong&gt;Axis 1&lt;/strong&gt; cannot be the same changes we calculate using &lt;strong&gt;Axis 2&lt;/strong&gt;. If they are, it may be a case of functional decomposition.&lt;/p&gt;




&lt;h3&gt;
  
  
  Solutions Masquerading as Requirements
&lt;/h3&gt;

&lt;p&gt;It is very common for an architect or developer to map a requirement from the spec directly into a component. We should always check whether that requirement is actually a &lt;strong&gt;solution masquerading as a requirement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, assume “Cooking” is listed as a requirement in the design spec for a house. Isn’t it actually masquerading for “Feeding”? There are several alternatives to cooking — ordering food, or going out for dinner.&lt;/p&gt;

&lt;p&gt;It’s exceedingly common for customers to suggest solutions as if they were requirements. Imagine you create a “Cooking” component, and later the customer demands a new “Pizza” component. Instead, having a “Feeding” component that encapsulates cooking, ordering pizza, or going out is more flexible and future-proof.&lt;/p&gt;




&lt;h3&gt;
  
  
  Volatility Listing
&lt;/h3&gt;

&lt;p&gt;So before decomposing the system into components, the &lt;strong&gt;first step&lt;/strong&gt; should be listing the volatilities after gathering requirements.&lt;br&gt;
To do so, one should think along both the independent axes. Then, see what “solutions” are masquerading as requirements.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We have now seen the principles of volatility-based decomposition. Let’s update the rules we’ll follow when designing real systems in future blogs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A good system design speaks (how components interact)&lt;/li&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities)&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system&lt;/li&gt;
&lt;li&gt;Reduce coupling between services as much as possible&lt;/li&gt;
&lt;li&gt;Decompose based on volatility — list the areas of volatility&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component&lt;/li&gt;
&lt;li&gt;Symmetry is a good sign of good design&lt;/li&gt;
&lt;li&gt;The required behavior should be accomplished by the interaction between various encapsulated areas of volatility&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List the requirements, then identify the volatilities using both axes:&lt;br&gt;
— What can change for existing customers over time?&lt;br&gt;
— Keeping time constant, what differs across customers?What are different use cases?&lt;br&gt;
(Remember: these axes are independent.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify whether a solution/component is masquerading as a requirement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify it is not variability. A volatility is not which can be handled with if-else. Its variability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In the next article next Sunday, we will start discussing a &lt;strong&gt;framework to actually do system design&lt;/strong&gt;. Stay tuned!&lt;/p&gt;

&lt;p&gt;Here are the links to previous articles in case you missed them. Its highly recommended to read the 4th one in the list which is about practical example of listing the volatility.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3"&gt;Volatility-Based Decomposition: A System Design Example&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Volatility-Based Decomposition: A System Design Example</title>
      <dc:creator>Ujjwal Raj</dc:creator>
      <pubDate>Sun, 08 Jun 2025 05:19:20 +0000</pubDate>
      <link>https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3</link>
      <guid>https://dev.to/ujjwall-r/volatility-based-decomposition-a-system-design-example-an3</guid>
      <description>&lt;p&gt;Welcome to another Sunday article where we dive into system design.&lt;/p&gt;

&lt;p&gt;As I’ve already stated: we are going to learn the rules, follow the rules, and once you are an expert — bend the rules.&lt;/p&gt;

&lt;p&gt;Let’s keep track of what we’ve learned so far, to keep things at our fingertips even if you haven’t read the previous article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A good system design &lt;em&gt;speaks&lt;/em&gt; (how components interact)&lt;/li&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities)&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system&lt;/li&gt;
&lt;li&gt;Reduce coupling between services as much as possible&lt;/li&gt;
&lt;li&gt;Decompose based on volatility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we will dive into &lt;strong&gt;volatility-based decomposition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the last blog, we compared volatility-based and functionally based decomposition of a mechanical car. Don’t worry if you missed that article — we’ll again compare a functionally decomposed trading system with a volatility-based trading software system. This same example is taken from the book &lt;em&gt;The Righting Software&lt;/em&gt; by Juval Löwy. We’ll prove again why functional decomposition is bad and volatility-based decomposition is good. We will see that &lt;strong&gt;software engineering is art, not just tech — like many other fields&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Through these examples, I’m trying to convince my readers why the rules of &lt;em&gt;The Method&lt;/em&gt; are fruitful. Once we’re done, we’ll start jumping into learning the exact steps of how to do this art. How to implement the rules in detail, with hands-on examples and real-world problems in upcoming blogs. So hold on.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Functionally Decomposed Trading System Design
&lt;/h2&gt;

&lt;p&gt;Functional decomposition is nothing but breaking a system into functional components. Each component is responsible for one function. For a stock trading application, this is the functional decomposition design — very obvious and what we’ve been taught in universities. Look at the components in the figure below carefully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjcdpdzbliyqd4z24ld9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjcdpdzbliyqd4z24ld9.png" alt="Image" width="457" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flaws in this architecture:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client is responsible for implementing the logic. The client is no longer a client — it has become an abstraction of business logic. It’s a system. Frontend developers now don’t like their job anymore. Congratulations, you’ve made their job more complicated and senseless.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a user wants to buy some stocks by selling others, they need to sell first and then buy. But during this process, prices might change — the sold stocks might drop in value or the ones to buy might get more expensive. This could mean the money from selling isn’t enough to buy the desired amount.&lt;/p&gt;

&lt;p&gt;So, what should the system do? Options include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buy fewer stocks than planned&lt;/li&gt;
&lt;li&gt;Sell more than originally intended&lt;/li&gt;
&lt;li&gt;Use extra money from the user’s cash account&lt;/li&gt;
&lt;li&gt;Cancel the entire transaction&lt;/li&gt;
&lt;li&gt;Ask the user what to do&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The main point is that the system needs special business rules to decide — and right now, those rules are handled by the &lt;strong&gt;client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine migrating from a web application to a phone application. The whole business logic has to be rewritten. Frontend developers are now almost cursing the architect. They are maintaining versions and variations of clients.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The user receives an email for all the activities in selling stocks, buying stocks, and trade scheduling. Imagine adding SMS support as a new communication protocol — all the services (reminder: services here are not microservices, just components) need to be changed to adapt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Imagine your application is now launching in another country. To support the currency and new laws of that country, you either rewrite all the services or carry around a bloated monolith full of complex, tangled logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services like Analyzing and Reporting are tightly coupled with others. They contain the logic of services like Buying Stocks to observe user patterns. Reporting needs the business logic of other components to determine which scenarios can lead to what level of threat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Imagine adding a new stock feed system. All services need to be updated with the new rules and data schema. A total disaster for developers — a bomb blast of changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Volatility-Based Decomposition of a Trading System
&lt;/h2&gt;

&lt;p&gt;Before designing, it’s important to list the requirements at hand. The &lt;strong&gt;areas of volatility&lt;/strong&gt; are decided by analyzing those requirements.&lt;/p&gt;

&lt;p&gt;Let’s see how a good trading system would look if broken based on volatility. In the next article, we’ll discuss &lt;em&gt;how exactly to think&lt;/em&gt; and break the system using volatility. Maybe I’ll add one or two rules to the list. For now, let’s look at what can be considered areas of volatility or change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User volatility:&lt;/strong&gt; The end user can check the current state of funds. They may alter, query, or report the state. It also includes the volatility of user types — e.g., admin or regular user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client application volatility:&lt;/strong&gt; A simple user might be happy with a basic web page, while professionals may need dashboards, spreadsheet support, or even a mobile app. This is clearly an area of change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security volatility:&lt;/strong&gt; How does a user authenticate? It could be simple ID/password, SSO, or passwordless login. Different OAuth clients may need to be integrated. Even authorization is volatile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notification volatility:&lt;/strong&gt; Email? In-app notification? SMS? This is a volatile area. Even language support may be added later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Storage volatility:&lt;/strong&gt; Is the database cloud-based? Is the cache in-memory or server-based? Is it file storage or something else?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connection and synchronization volatility:&lt;/strong&gt; Why not keep connections asynchronous? The trader can send independent requests to the app and maximize profit. A messaging queue might be better than simple async calls. This is volatile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trade item volatility:&lt;/strong&gt; Customers may want to trade stocks, commodities, bonds, currencies, or future contracts. The trade item itself is volatile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workflow volatility:&lt;/strong&gt; If the trade item is volatile, so is the processing. The steps in trading stocks differ from those for bonds or currencies. So the trading &lt;em&gt;workflow&lt;/em&gt; is volatile too — same for analysis workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Market feed system volatility:&lt;/strong&gt; Stock feeds can come from Bloomberg, Reuters, or internal simulations. The feed source is volatile.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you’ve identified the volatilities, you can decompose them into components. One such decomposition looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjf2lrohsqzlq2s038viy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjf2lrohsqzlq2s038viy.png" alt="Image" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Listing volatilities and creating components is rarely one-to-one. One component often encapsulates multiple volatilities. Transitioning from volatility areas to components involves some rules — and we’ll master them throughout this series. Some components may align with operational concepts like queuing or event publishing. A volatility can also be handled by a third-party service — e.g., OAuth for security, or an external service for notifications.&lt;/p&gt;

&lt;p&gt;Let’s briefly discuss what volatility each component encapsulates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Access Component:&lt;/strong&gt; Encapsulates data storage volatility. It knows where the data is, what technology is used, and handles business logic for reading/writing. Other components don’t care about storage details — they just use the data access layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Storage:&lt;/strong&gt; The physical or logical data store — database, file-based, cache, local or cloud.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any change in storage will only affect the data access component, keeping other parts decoupled. This enables minimal impact when storage needs to change.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notification Utility:&lt;/strong&gt; Technology used for messaging — e.g., pub-sub, messaging queues, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trade Workflow Component:&lt;/strong&gt; What is being traded (stocks, currencies)? What are the steps? What changes per country/currency? Even if trade items are fixed, workflows change — this component handles that. It may use a third-party tool to manage workflows, saving/loading workflow instances from workflow storage. It supports different workflows, devices, and durations (seconds to days), ensuring consistency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Analysis Workflows:&lt;/strong&gt; Follows a similar pattern as trading workflows. Encapsulates volatility in analysis logic and uses the same workflow storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feed Access:&lt;/strong&gt; Encapsulates volatility of market feed source and format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clients:&lt;/strong&gt; Apps like Trader App A, Trader App B, and the Customer Portal — each handles how to best present data on their respective platforms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Let’s add some new rules to our list. In the next Sunday article, we’ll dive deeper into the rules and observations for breaking systems into components after identifying volatility.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A good system design &lt;em&gt;speaks&lt;/em&gt; (how components interact)&lt;/li&gt;
&lt;li&gt;Avoid functional decomposition (what we were doing in universities)&lt;/li&gt;
&lt;li&gt;The client should not be the core business. Let the client be the client — not the system&lt;/li&gt;
&lt;li&gt;Reduce coupling between services as much as possible&lt;/li&gt;
&lt;li&gt;Decompose based on volatility — list the areas of volatility&lt;/li&gt;
&lt;li&gt;There is rarely a one-to-one mapping between a volatility area and a component&lt;/li&gt;
&lt;li&gt;Symmetry is a good sign of good design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stay tuned!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are the links to previous articles in case you missed them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/why-functional-decomposition-leads-to-bad-system-design-5chd"&gt;Why Functional Decomposition Leads to Bad System Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/system-design-basics-why-the-right-method-matters-44f"&gt;System Design Basics: Why The Right Method Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ujjwall-r/the-anti-design-thinking-in-system-design-2ph1"&gt;The Anti-Design Thinking in System Design&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>programming</category>
      <category>development</category>
    </item>
  </channel>
</rss>
