<?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: Nikita Rykhlov</title>
    <description>The latest articles on DEV Community by Nikita Rykhlov (@nikita_rykhlov).</description>
    <link>https://dev.to/nikita_rykhlov</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%2F3175624%2Fbf5f41b0-d861-4da7-a755-5656c03e304e.png</url>
      <title>DEV Community: Nikita Rykhlov</title>
      <link>https://dev.to/nikita_rykhlov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nikita_rykhlov"/>
    <language>en</language>
    <item>
      <title>⚙️ Go Tools: Password Hashing with Argon2 Instead of bcrypt</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Fri, 20 Jun 2025 10:46:31 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/go-tools-password-hashing-with-argon2-instead-of-bcrypt-38aj</link>
      <guid>https://dev.to/nikita_rykhlov/go-tools-password-hashing-with-argon2-instead-of-bcrypt-38aj</guid>
      <description>&lt;p&gt;Storing passwords securely is one of the most critical security tasks in modern applications. Many developers still rely on time-tested algorithms like &lt;strong&gt;bcrypt&lt;/strong&gt;, but technology doesn't stand still. In this article, we'll explore &lt;strong&gt;Argon2&lt;/strong&gt; — a modern and secure password hashing algorithm that serves as an excellent alternative to bcrypt. We'll also look at how to implement it in &lt;strong&gt;Go (Golang)&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Argon2?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A Quick Recap on bcrypt
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;bcrypt&lt;/strong&gt; is a cryptographic algorithm specifically designed for password hashing. It resists brute-force attacks thanks to the use of "salt" and a tunable cost factor that increases computational complexity.&lt;/p&gt;

&lt;p&gt;However, over time new threats have emerged — especially those involving specialized hardware such as GPUs and ASICs for password cracking. This is where &lt;strong&gt;bcrypt&lt;/strong&gt; starts to fall short compared to more modern solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Argon2?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Argon2&lt;/strong&gt; is the winner of the &lt;a href="https://password-hashing.net/" rel="noopener noreferrer"&gt;Password Hashing Competition (PHC)&lt;/a&gt;, a competition organized by the cryptographic community to find a new standard for secure password hashing. It was developed by a team of cryptographers from the University of Luxembourg: &lt;strong&gt;Alex Biryukov&lt;/strong&gt;, &lt;strong&gt;Daniel Dinu&lt;/strong&gt;, and &lt;strong&gt;Dmitry Khovratovich&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Argon2 was chosen for its resistance to various types of attacks, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timing attacks&lt;/li&gt;
&lt;li&gt;GPU/ASIC-based attacks&lt;/li&gt;
&lt;li&gt;Memory-hard attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Argon2 offers three different modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Argon2d&lt;/strong&gt; — provides maximum protection against hardware attacks but is vulnerable to timing attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Argon2i&lt;/strong&gt; — resistant to timing attacks but weaker against hardware-based attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Argon2id&lt;/strong&gt; — a hybrid mode combining the best features of both.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For most practical purposes, &lt;strong&gt;Argon2id&lt;/strong&gt; is recommended.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Argon2 Is Better Than bcrypt
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;bcrypt&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Argon2&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Protection against GPU attacks&lt;/td&gt;
&lt;td&gt;Weak&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configurable memory usage&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallelism support&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resistance to timing attacks&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short, &lt;strong&gt;Argon2&lt;/strong&gt; is a more flexible, modern, and secure solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using Argon2 in Go
&lt;/h2&gt;

&lt;p&gt;The package &lt;a href="https://pkg.go.dev/golang.org/x/crypto/argon2" rel="noopener noreferrer"&gt;&lt;code&gt;golang.org/x/crypto/argon2&lt;/code&gt;&lt;/a&gt; provides a solid implementation of the Argon2 algorithm.&lt;/p&gt;

&lt;p&gt;In this example, we'll use &lt;strong&gt;Argon2id&lt;/strong&gt; (&lt;code&gt;IDKey&lt;/code&gt;), which combines the strengths of &lt;strong&gt;Argon2i&lt;/strong&gt; and &lt;strong&gt;Argon2d&lt;/strong&gt;: it's resistant to side-channel attacks and protected against time-memory trade-off attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get golang.org/x/crypto/argon2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/subtle"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"golang.org/x/crypto/argon2"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Recommended RFC parameters for most applications&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;saltLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;       &lt;span class="c"&gt;// length of salt in bytes&lt;/span&gt;
    &lt;span class="n"&gt;keyLength&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt;       &lt;span class="c"&gt;// length of derived key (e.g., for AES-256)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;        &lt;span class="c"&gt;// number of iterations&lt;/span&gt;
    &lt;span class="n"&gt;memory&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="c"&gt;// memory cost in KiB (~64MB)&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;        &lt;span class="c"&gt;// number of parallel threads&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;generateSalt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateSalt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;saltLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;hashed&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;argon2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IDKey&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;verifyPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expectedHash&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;newHash&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;argon2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IDKey&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subtleCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expectedHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Prevent timing attacks&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;subtleCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subtle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConstantTimeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"mySecureP@ssw0rd"&lt;/span&gt;

    &lt;span class="c"&gt;// Step 1: Hash the password&lt;/span&gt;
    &lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hashed password: %x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Step 2: Verify correct password&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;verifyPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✅ Password is valid"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"❌ Password is invalid"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Step 3: Verify incorrect password&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;verifyPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wrongPass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"❌ Incorrect password was accepted!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✅ Verification rejected incorrect password"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔐 &lt;strong&gt;Tip:&lt;/strong&gt; Never use fixed &lt;code&gt;salt&lt;/code&gt; values. Always generate a new random salt before each password hashing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Recommended Parameters
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Parameter&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;time&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Number of passes through memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;64 * 1024&lt;/td&gt;
&lt;td&gt;Amount of memory used in KiB (~64 MB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;threads&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Number of threads to use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;keyLength&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;Length of the resulting key in bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;saltLength&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Random salt to prevent collisions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;These values are suitable for most web applications. Adjust them based on your system's capabilities or specific requirements (e.g., mobile devices).&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;While &lt;strong&gt;bcrypt&lt;/strong&gt; remains a solid choice, &lt;strong&gt;Argon2&lt;/strong&gt; offers superior protection against modern threats, particularly GPU and ASIC-based attacks. With its flexibility and efficient resource usage, it is becoming the de-facto standard for password hashing in new projects.&lt;/p&gt;

&lt;p&gt;If you're developing in &lt;strong&gt;Go&lt;/strong&gt;, integrating Argon2 is straightforward using existing libraries. Just remember to choose appropriate parameters for your application load and always store the salt and metadata correctly.&lt;/p&gt;




&lt;p&gt;📎 &lt;strong&gt;Useful Links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc9106" rel="noopener noreferrer"&gt;RFC 9106 — The Argon2 Password Hash and Proof-of-Work Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkg.go.dev/golang.org/x/crypto/argon2" rel="noopener noreferrer"&gt;Go Argon2 Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkg.go.dev/crypto/subtle" rel="noopener noreferrer"&gt;Go crypto/subtle Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;📌 What do you think?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you already switched from bcrypt to Argon2 in your projects — or still sticking with the classic?&lt;/p&gt;

&lt;p&gt;What password hashing strategy do you use in Go — and how do you manage security vs. performance?&lt;/p&gt;

&lt;p&gt;👇 Share your thoughts and experience in the comments — I’d love to learn from you!&lt;/p&gt;

&lt;p&gt;👍 If you enjoyed this article, don’t forget to like and share it — help others upgrade their password security the right way!&lt;/p&gt;




&lt;p&gt;📣 &lt;strong&gt;Follow me and read my content on other platforms:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check out this and other articles on my pages:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/nikita-rykhlov/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📚 &lt;strong&gt;&lt;a href="https://medium.com/@nikita_rykhlov" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📘 &lt;strong&gt;&lt;a href="https://www.facebook.com/groups/nikitarykhlov" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
✈️ &lt;strong&gt;&lt;a href="https://t.me/nikitaRykhlovBlog" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🐦 &lt;strong&gt;&lt;a href="https://x.com/NikitaRykhlov" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, almost forgot — &lt;strong&gt;&lt;a href="https://nikita-rykhlov.tech/" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔔 &lt;em&gt;Follow me not to miss new articles and guides on hot topics!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>go</category>
      <category>security</category>
    </item>
    <item>
      <title>🏗️ Architecture: How to Visualize System Interaction - Use Case Diagram</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Mon, 16 Jun 2025 11:15:04 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/architecture-how-to-visualize-system-interaction-use-case-diagram-5amp</link>
      <guid>https://dev.to/nikita_rykhlov/architecture-how-to-visualize-system-interaction-use-case-diagram-5amp</guid>
      <description>&lt;p&gt;A &lt;strong&gt;Use Case Diagram&lt;/strong&gt; emerged as part of the &lt;strong&gt;Unified Modeling Language (UML)&lt;/strong&gt;, which was developed in the mid-1990s. The core concept was proposed by specialists &lt;strong&gt;Grady Booch&lt;/strong&gt;, &lt;strong&gt;James Rumbaugh&lt;/strong&gt;, and &lt;strong&gt;Ivar Jacobson&lt;/strong&gt;, who worked at Rational Software at that time. By combining their approaches to object-oriented analysis and design, they created UML — a standard that became a universal tool for describing software system architecture. The Use Case Diagram became an important part of this language because it allowed visualizing how users interact with the system even at the requirements gathering stage.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Use Case Diagram?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Use Case Diagram&lt;/strong&gt; is one of the types of diagrams in UML that shows how different participants (actors) interact with the functionalities of a system. It helps visualize the main goals of users and define what actions the system must support to fulfill those goals.&lt;/p&gt;




&lt;h2&gt;
  
  
  Main Elements of a Use Case Diagram:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Actor&lt;/strong&gt; — An external entity that interacts with the system. This can be a person, another system, or even time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Case&lt;/strong&gt; — A functionality or action provided by the system to the actor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relationships between actors and use cases&lt;/strong&gt; — Indicate who participates in which action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relationships between use cases&lt;/strong&gt; — Such as &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;extend&lt;/code&gt;, and inheritance, which describe complex behavioral scenarios.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use Use Case Diagrams?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simplify communication with clients and stakeholders.&lt;/li&gt;
&lt;li&gt;Help define the boundaries of the system.&lt;/li&gt;
&lt;li&gt;Serve as a foundation for further design and testing.&lt;/li&gt;
&lt;li&gt;Provide a high-level view of the system's behavior without diving into implementation details.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Example:
&lt;/h2&gt;

&lt;p&gt;Imagine you are developing a platform for online food ordering. Your system should support features such as registration, menu browsing, placing orders, tracking deliveries, and rating orders. The actors may include: customer, courier, and restaurant.&lt;/p&gt;

&lt;p&gt;Here’s how the textual description of this diagram might 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%2Fdlaxn2hjmijiycfvoj1g.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%2Fdlaxn2hjmijiycfvoj1g.png" alt="Food Delivery Service Use Case Diagram" width="435" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PlantUML&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@startuml
left to right direction
actor "Customer" as client
actor "Courier" as courier
actor "Restaurant" as restaurant

rectangle "Food Delivery Service" {
  client -- (Registration)
  client -- (Browse Menu)
  client -- (Place Order)
  client -- (Track Order)
  client -- (Rate Order)

  restaurant -- (Receive Order)
  restaurant -- (Prepare Order)

  courier -- (Receive Order for Delivery)
  courier -- (Deliver Order)
}

(Place Order) .&amp;gt; (Receive Order) : include
(Deliver Order) .&amp;gt; (Track Order) : extend
@enduml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How to Read This Diagram?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Customer&lt;/strong&gt; can:

&lt;ul&gt;
&lt;li&gt;Register in the app,&lt;/li&gt;
&lt;li&gt;Browse restaurant menus,&lt;/li&gt;
&lt;li&gt;Place orders,&lt;/li&gt;
&lt;li&gt;Track delivery status,&lt;/li&gt;
&lt;li&gt;Rate completed orders.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Restaurant&lt;/strong&gt; is responsible for:

&lt;ul&gt;
&lt;li&gt;Receiving order information,&lt;/li&gt;
&lt;li&gt;Preparing meals for delivery.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Courier&lt;/strong&gt; is involved in:

&lt;ul&gt;
&lt;li&gt;Receiving the order for delivery,&lt;/li&gt;
&lt;li&gt;Delivering the meal to the customer.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;include&lt;/code&gt; relationship shows that when a &lt;strong&gt;customer places an order&lt;/strong&gt;, the &lt;strong&gt;restaurant always receives the order&lt;/strong&gt;.&lt;br&gt;
The &lt;code&gt;extend&lt;/code&gt; relationship indicates that &lt;strong&gt;delivering the order&lt;/strong&gt; may optionally be part of the &lt;strong&gt;tracking process&lt;/strong&gt;.&lt;/p&gt;




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

&lt;p&gt;A Use Case Diagram is a powerful tool for analyzing requirements and modeling system behavior in the early stages of development. It allows you to foresee key product features and understand how different users will interact with the system.&lt;/p&gt;

&lt;p&gt;Use use case diagrams to better structure requirements, improve team communication, and create a clear vision of what your system should do.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;📌 What do you think?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever created a Use Case Diagram for your projects?&lt;/p&gt;

&lt;p&gt;What tools or notations do you prefer for modeling system behavior — PlantUML, draw.io, or something else?&lt;/p&gt;

&lt;p&gt;👇 Share your thoughts and experience in the comments — I’d love to learn from you!&lt;/p&gt;

&lt;p&gt;👍 If you enjoyed this article, don’t forget to like and share it — help others discover how to use Use Case Diagrams effectively!&lt;/p&gt;




&lt;p&gt;📣 &lt;strong&gt;Follow me and read my content on other platforms:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check out this and other articles on my pages:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/nikita-rykhlov/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📚 &lt;strong&gt;&lt;a href="https://medium.com/@nikita_rykhlov" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📘 &lt;strong&gt;&lt;a href="https://www.facebook.com/groups/nikitarykhlov" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
✈️ &lt;strong&gt;&lt;a href="https://t.me/nikitaRykhlovBlog" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🐦 &lt;strong&gt;&lt;a href="https://x.com/NikitaRykhlov" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, almost forgot — &lt;strong&gt;&lt;a href="https://nikita-rykhlov.tech/" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔔 &lt;em&gt;Follow me not to miss new articles and guides on hot topics!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>⚙️ Go Tools: Yet Another Configuration Tool for Go Applications — zerocfg</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Tue, 03 Jun 2025 14:39:54 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/go-tools-yet-another-configuration-tool-for-go-applications-zerocfg-1fij</link>
      <guid>https://dev.to/nikita_rykhlov/go-tools-yet-another-configuration-tool-for-go-applications-zerocfg-1fij</guid>
      <description>&lt;p&gt;&lt;strong&gt;Configuration management&lt;/strong&gt; is an essential part of any application development. In Go, the standard &lt;code&gt;flag&lt;/code&gt; package provides a convenient way to work with command-line flags. However, in practice, there is often a need to support not only CLI arguments but also other sources such as YAML files, environment variables, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;zerocfg&lt;/strong&gt; is a lightweight library that preserves the simplicity and familiar interface of the &lt;code&gt;flag&lt;/code&gt; package while adding support for YAML, environment variables (env), and custom configuration sources.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Intuitive API&lt;/strong&gt;, similar to &lt;code&gt;flag&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🧼 &lt;strong&gt;Minimizes boilerplate code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Detects unknown keys&lt;/strong&gt; in the configuration&lt;/li&gt;
&lt;li&gt;📚 Supports &lt;strong&gt;multiple sources&lt;/strong&gt;: CLI, YAML, ENV, and others&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Hides sensitive data&lt;/strong&gt; (e.g., passwords) when printing configurations&lt;/li&gt;
&lt;li&gt;🧩 &lt;strong&gt;Extensible&lt;/strong&gt;: supports custom types and providers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Usage Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="n"&gt;zfg&lt;/span&gt; &lt;span class="s"&gt;"github.com/chaindead/zerocfg"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/chaindead/zerocfg/env"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;databaseHost&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database host"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;databasePort&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database port"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;databaseUserName&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database user name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;databaseUserPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database user password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;databaseName&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;databaseDSN&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres://%s:%s@%s:%d/%s?sslmode=disable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseUserName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseUserPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databasePort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;databaseDSN&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔁 Configuration Source Priority
&lt;/h2&gt;

&lt;p&gt;Priorities determine which values will be used if they are defined in multiple sources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Command-line flags&lt;/strong&gt; (highest priority)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Additional providers&lt;/strong&gt; (in the order they are listed)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default values&lt;/strong&gt; (lowest priority)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This mechanism allows flexible parameter configuration and overrides depending on the application’s runtime context.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Supported Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLI (command-line flags)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ENV (environment variables)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;YAML (configuration files)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CLI Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go &lt;span class="nt"&gt;--db&lt;/span&gt;.host localhost &lt;span class="nt"&gt;--db&lt;/span&gt;.port 6432 &lt;span class="nt"&gt;--db&lt;/span&gt;.username admin &lt;span class="nt"&gt;--db&lt;/span&gt;.password pass &lt;span class="nt"&gt;--db&lt;/span&gt;.name postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ENV Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DB_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localhost &lt;span class="nv"&gt;DB_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6432 &lt;span class="nv"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="nv"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pass &lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  YAML Example
&lt;/h3&gt;

&lt;p&gt;To use a YAML file, you need to slightly modify the source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="n"&gt;zfg&lt;/span&gt; &lt;span class="s"&gt;"github.com/chaindead/zerocfg"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/chaindead/zerocfg/env"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/chaindead/zerocfg/yaml"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config.path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"configuration file path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;databaseHost&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database host"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;databasePort&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database port"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;databaseUserName&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database user name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;databaseUserPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database user password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;databaseName&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;databaseDSN&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres://%s:%s@%s:%d/%s?sslmode=disable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseUserName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseUserPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databasePort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;databaseName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;databaseDSN&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;config.yml&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres_pass"&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the app like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go &lt;span class="nt"&gt;-c&lt;/span&gt; config.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📋 Additional Options
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fields marked with &lt;code&gt;zfg.Secret()&lt;/code&gt; are &lt;strong&gt;hidden when printed&lt;/strong&gt; via &lt;code&gt;zfg.Show()&lt;/code&gt; — useful for passwords and tokens.&lt;/li&gt;
&lt;li&gt;Fields with &lt;code&gt;zfg.Required()&lt;/code&gt; are considered &lt;strong&gt;mandatory&lt;/strong&gt; — if they are not provided in any source, an error will be returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;databaseUserPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db.password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"database user password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;zfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧱 Extensibility
&lt;/h2&gt;

&lt;p&gt;The library supports &lt;strong&gt;custom data types&lt;/strong&gt; and &lt;strong&gt;custom configuration providers&lt;/strong&gt;, making it flexible and adaptable to any project needs.&lt;/p&gt;




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

&lt;p&gt;The &lt;strong&gt;zerocfg&lt;/strong&gt; library offers a simple yet powerful way to manage configuration in Go applications. While preserving the familiar interface of the standard &lt;code&gt;flag&lt;/code&gt; package, it extends its capabilities with support for YAML files, environment variables, and custom configuration sources. Its intuitive API, minimal boilerplate, unknown key detection, and sensitive data masking make it an excellent choice for modern applications.&lt;/p&gt;

&lt;p&gt;If you're looking for a lightweight and extensible configuration management library for Go — &lt;strong&gt;zerocfg&lt;/strong&gt; is a great fit for your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/chaindead/zerocfg" rel="noopener noreferrer"&gt;More about zerocfg&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;📌 What do you think?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you tried zerocfg or other configuration management tools in Go yet?&lt;/p&gt;

&lt;p&gt;What libraries or approaches do you use in your projects to handle application settings?&lt;/p&gt;

&lt;p&gt;👇 Leave a comment below — I’d love to hear your experience!&lt;/p&gt;

&lt;p&gt;👍 Don’t forget to like and share if you found this helpful — so more people can benefit from it too!&lt;/p&gt;




&lt;p&gt;📣 &lt;strong&gt;Follow me and read my content on other platforms:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check out this and other articles on my pages:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/nikita-rykhlov/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📚 &lt;strong&gt;&lt;a href="https://medium.com/@nikita_rykhlov" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📘 &lt;strong&gt;&lt;a href="https://www.facebook.com/groups/nikitarykhlov" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
✈️ &lt;strong&gt;&lt;a href="https://t.me/nikitaRykhlovBlog" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🐦 &lt;strong&gt;&lt;a href="https://x.com/NikitaRykhlov" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, almost forgot — &lt;strong&gt;&lt;a href="https://nikita-rykhlov.tech/" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔔 &lt;em&gt;Follow me not to miss new articles and guides on hot topics!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Architecture: Document architecture in a way that everyone understands</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Tue, 27 May 2025 16:56:39 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/architecture-document-architecture-in-a-way-that-everyone-understands-16dp</link>
      <guid>https://dev.to/nikita_rykhlov/architecture-document-architecture-in-a-way-that-everyone-understands-16dp</guid>
      <description>&lt;p&gt;In the world of backend development and designing complex systems, it's not enough just to write good code — it's equally important to clearly communicate architectural ideas to your team, clients, or new developers joining the project. One of the most effective tools for this is the &lt;strong&gt;C4 Model&lt;/strong&gt; — a simple yet powerful way to document and visualize software architecture.&lt;/p&gt;

&lt;p&gt;Created by Simon Brown, the C4 model offers a &lt;strong&gt;hierarchical approach to diagramming&lt;/strong&gt;, allowing you to gradually zoom in from broad concepts to detailed implementation. The model consists of four levels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;System Context&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Containers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Components&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What makes it especially convenient is that &lt;strong&gt;C4 is often used together with PlantUML&lt;/strong&gt;, a powerful text-based tool for creating UML diagrams. This allows you to describe your system structure directly in code, easily keep diagrams up to date, and automate their rendering.&lt;/p&gt;

&lt;p&gt;Let’s explore each level and provide examples using PlantUML.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. System Context Diagram
&lt;/h2&gt;

&lt;p&gt;At the highest level of abstraction, we see the whole system within its environment. The goal of this level is to show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What system is being built&lt;/li&gt;
&lt;li&gt;Who interacts with it (users, external systems)&lt;/li&gt;
&lt;li&gt;How it connects to other systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Suppose you're building a &lt;strong&gt;food delivery platform&lt;/strong&gt; . The diagram would include: the core service itself, users (customers, couriers, restaurant owners, admins), payment gateways, SMS services, geolocation APIs, and analytics systems — everything your platform interacts with externally to function effectively.&lt;/p&gt;
&lt;/blockquote&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%2Fyqd6jjzxe9ezb0t2u74k.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%2Fyqd6jjzxe9ezb0t2u74k.png" alt="System Context Diagram: Food Delivery Service" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PlantUML:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@startuml
title System Context Diagram: Food Delivery Service

skinparam rectangle {
    roundCorner 20
}

actor "User" as user
actor "Courier" as courier
actor "Admin" as admin
actor "Restaurant Owner" as restaurant_owner

[Food Delivery Service] as foodservice

user --&amp;gt; foodservice : Orders food, views menu
courier --&amp;gt; foodservice : Receives tasks, updates status
restaurant_owner --&amp;gt; foodservice : Manages menu, accepts orders
admin --&amp;gt; foodservice : Administers system, analytics, moderation

foodservice --&amp;gt; [Payment Gateway] : Payment processing
foodservice --&amp;gt; [SMS Service] : Sends notifications
foodservice --&amp;gt; [Geolocation API] : Location detection
foodservice --&amp;gt; [Analytics System] : Sends metrics

note right of foodservice
  A full-featured food delivery platform
  supporting multiple restaurants, users,
  couriers and analytics.
end note

@enduml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Container Diagram
&lt;/h2&gt;

&lt;p&gt;At this level, we look &lt;em&gt;inside&lt;/em&gt; the system and show its main &lt;strong&gt;containers&lt;/strong&gt; — these are separate processes or hosts that communicate with each other. A container can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A web application (e.g., Node.js API)&lt;/li&gt;
&lt;li&gt;A database (PostgreSQL, MongoDB)&lt;/li&gt;
&lt;li&gt;A message broker (RabbitMQ, Kafka)&lt;/li&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;li&gt;Frontend app (React)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In a food delivery platform, possible containers could be:&lt;br&gt;
&lt;strong&gt;API Gateway&lt;/strong&gt; — routes incoming requests to the appropriate services&lt;br&gt;
&lt;strong&gt;Order Service&lt;/strong&gt; — manages order lifecycle (creation, modification, queueing)&lt;br&gt;
&lt;strong&gt;Restaurant Service&lt;/strong&gt; — handles restaurant and menu data&lt;br&gt;
&lt;strong&gt;User Service&lt;/strong&gt; — manages user profiles and authentication&lt;br&gt;
&lt;strong&gt;Notification Service&lt;/strong&gt; — sends alerts and updates via SMS or push&lt;br&gt;
&lt;strong&gt;Payment Service&lt;/strong&gt; — processes payments through an external gateway&lt;br&gt;
&lt;strong&gt;Location Service&lt;/strong&gt; — integrates with geolocation APIs for couriers and users&lt;br&gt;
&lt;strong&gt;Analytics Service&lt;/strong&gt; — collects and analyzes system metrics&lt;br&gt;
&lt;strong&gt;PostgreSQL Cluster&lt;/strong&gt; — stores core data like users, orders, and restaurants&lt;br&gt;
&lt;strong&gt;Redis Cache&lt;/strong&gt; — improves performance by caching frequently accessed data&lt;br&gt;
&lt;strong&gt;RabbitMQ&lt;/strong&gt; — handles internal service communication via events&lt;br&gt;
&lt;strong&gt;Kafka&lt;/strong&gt; — logs all events for analytics and system recovery&lt;/p&gt;
&lt;/blockquote&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%2Fiqg0ay8tiaw57p6lnk7g.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%2Fiqg0ay8tiaw57p6lnk7g.png" alt="Container Diagram: Food Delivery Service" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PlantUML:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@startuml
title Container Diagram: Food Delivery Service

package "Food Delivery Service" {
  [API Gateway] as gateway
  [Order Service] as orderservice
  [Restaurant Service] as restaurantservice
  [User Service] as userservice
  [Notification Service] as notificationservice
  [Payment Service] as paymentservice
  [Location Service] as locationservice
  [Analytics Service] as analyticsservice
  [PostgreSQL Cluster] as database
  [Redis Cache] as cache
  [RabbitMQ] as messagebroker
  [Kafka] as eventlog

  note bottom of orderservice
    Manages order lifecycle:
    creation, modification, queueing.
  end note

  note bottom of messagebroker
    Used for internal communication
    between services via events.
  end note

  note bottom of eventlog
    Stores all system events
    for analytics and recovery.
  end note
}

gateway --&amp;gt; orderservice
gateway --&amp;gt; restaurantservice
gateway --&amp;gt; userservice
gateway --&amp;gt; paymentservice
gateway --&amp;gt; locationservice

orderservice --&amp;gt; database
orderservice --&amp;gt; messagebroker
orderservice --&amp;gt; cache

restaurantservice --&amp;gt; database
restaurantservice --&amp;gt; cache

userservice --&amp;gt; database

paymentservice --&amp;gt; [Payment Gateway]

locationservice --&amp;gt; [Geolocation API]

notificationservice &amp;lt;-- messagebroker
analyticsservice &amp;lt;-- eventlog

@enduml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Component Diagram
&lt;/h2&gt;

&lt;p&gt;Now we go one level deeper and look at &lt;strong&gt;what components reside inside each container&lt;/strong&gt;. At this point, developer-level design decisions begin to emerge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which modules, services, repositories are used&lt;/li&gt;
&lt;li&gt;How they interact with each other&lt;/li&gt;
&lt;li&gt;Which frameworks and technologies are involved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Inside the &lt;em&gt;Order Service&lt;/em&gt; container, there might be these components:&lt;br&gt;
&lt;strong&gt;HTTP Handler&lt;/strong&gt; — receives and routes incoming HTTP requests&lt;br&gt;
&lt;strong&gt;Order Use Case&lt;/strong&gt; — contains core business logic for creating, updating, and retrieving orders&lt;br&gt;
&lt;strong&gt;Order Repository&lt;/strong&gt; — interacts with the database to persist and retrieve order data&lt;br&gt;
&lt;strong&gt;Event Publisher&lt;/strong&gt; — publishes events (e.g., “OrderCreated”) to the message broker&lt;br&gt;
&lt;strong&gt;Config Manager&lt;/strong&gt; — provides configuration values to all components&lt;br&gt;
&lt;strong&gt;Validator&lt;/strong&gt; — ensures input data is valid before processing&lt;br&gt;
&lt;strong&gt;Metrics Collector&lt;/strong&gt; — gathers performance and usage metrics for monitoring&lt;/p&gt;
&lt;/blockquote&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%2F6gz3ga9sgw8yqf6xr5x2.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%2F6gz3ga9sgw8yqf6xr5x2.png" alt="Component Diagram: Order Service" width="719" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PlantUML:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@startuml
title Component Diagram: Order Service

package "OrderService" {
  [HTTP Handler] as handler
  [Order Use Case] as usecase
  [Order Repository] as repo
  [Event Publisher] as publisher
  [Config Manager] as config
  [Validator] as validator
  [Metrics Collector] as metrics

  note right of usecase
    Contains business logic for creating,
    updating and retrieving orders.
  end note

  note bottom of validator
    Validates order data before
    performing any operations.
  end note
}

handler --&amp;gt; usecase : Create / Get order
usecase --&amp;gt; validator : Validates input data
usecase --&amp;gt; repo : Works with DB
usecase --&amp;gt; publisher : Publishes event
usecase --&amp;gt; metrics : Logs metrics

config -down-&amp;gt; handler
config -down-&amp;gt; usecase
config -down-&amp;gt; repo
config -down-&amp;gt; publisher

@enduml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Code Diagram
&lt;/h2&gt;

&lt;p&gt;This is the lowest level — the source code level. Here you can show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Class diagrams&lt;/li&gt;
&lt;li&gt;Object interactions&lt;/li&gt;
&lt;li&gt;Method or function calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, code diagrams can quickly become outdated if not maintained. They’re best used to explain key algorithms or complex parts of the logic that are hard to understand without visual representation.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A diagram demonstrating the internal structure of the &lt;code&gt;OrderUsecase&lt;/code&gt;, showing how it interacts with core components like &lt;code&gt;OrderRepository&lt;/code&gt;, &lt;code&gt;EventPublisher&lt;/code&gt;, and &lt;code&gt;Validator&lt;/code&gt;. This UML diagram clarifies the flow of operations during order creation — from validation and persistence to event publishing, helping developers understand the logic and dependencies at the code level.&lt;/p&gt;
&lt;/blockquote&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%2F9dmpsog12n8i6k9ypes4.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%2F9dmpsog12n8i6k9ypes4.png" alt="Code Diagram: Order Usecase" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PlantUML:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@startuml
title Code Diagram: Order Usecase

class OrderUsecase {
  +CreateOrder(*Order) error
  +GetOrder(string) (*Order, error)
}

class OrderRepository {
  +Save(*Order) error
  +FindByID(string) (*Order, error)
}

class EventPublisher {
  +Publish(event Event) error
}

class Validator {
  +ValidateOrder(*Order) error
}

OrderUsecase --&amp;gt; OrderRepository : Uses
OrderUsecase --&amp;gt; EventPublisher : On create
OrderUsecase --&amp;gt; Validator : Before save

note right of OrderUsecase
  Executes business logic for order creation,
  calls repository and event publisher.
end note

@enduml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Use the C4 Model?
&lt;/h2&gt;

&lt;p&gt;The C4 model is valuable because it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplifies communication&lt;/strong&gt; between developers, analysts, testers, and managers.&lt;/li&gt;
&lt;li&gt;Allows you to &lt;strong&gt;see the big picture&lt;/strong&gt; while having the ability to zoom into specific areas.&lt;/li&gt;
&lt;li&gt;Improves &lt;strong&gt;architecture documentation&lt;/strong&gt; — especially important in long-term projects.&lt;/li&gt;
&lt;li&gt;Eases &lt;strong&gt;onboarding of new team members&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Helps with &lt;strong&gt;risk assessment&lt;/strong&gt;, threat modeling, and architectural reviews.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Start Using C4 and PlantUML
&lt;/h2&gt;

&lt;p&gt;If you want to start applying C4 in your work, here are some steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with the System Context level&lt;/strong&gt; — define who interacts with what.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move to the Containers level&lt;/strong&gt; — show the main technical blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add the Components level for key containers&lt;/strong&gt; — reveal their internal structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the Code level when necessary&lt;/strong&gt; — only where it adds real value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write diagrams in PlantUML&lt;/strong&gt; — this will help you maintain them easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrate into documentation&lt;/strong&gt; — for example, via Markdown or Confluence with PlantUML support.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;The C4 model is more than just a set of diagrams — it's a &lt;strong&gt;structured approach to understanding and describing architecture&lt;/strong&gt;. It helps everyone on the project — from technical specialists to business stakeholders — speak the same language.&lt;/p&gt;

&lt;p&gt;If you're working on complex backend systems, microservices, or simply want to better organize your thoughts during design, the C4 model will be a great addition to your toolkit. And using &lt;strong&gt;PlantUML&lt;/strong&gt; will make working with diagrams easy, repeatable, and well-documented.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://c4model.com/" rel="noopener noreferrer"&gt;More about C4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://plantuml.com/en/" rel="noopener noreferrer"&gt;More about PlantUML&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;What do you think?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you tried C4 or PlantUML yet?&lt;/p&gt;

&lt;p&gt;What tools or methods do you use to document your system architecture?&lt;/p&gt;

&lt;p&gt;👇 Leave a comment below — I’d love to hear your experience!&lt;/p&gt;

&lt;p&gt;👍 Don’t forget to like and share if you found this helpful — so more people can benefit from it too!&lt;/p&gt;




&lt;p&gt;📣 &lt;strong&gt;Follow me and read my content on other platforms:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check out this and other articles on my pages:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/nikita-rykhlov/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📚 &lt;strong&gt;&lt;a href="https://medium.com/@nikita_rykhlov" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📘 &lt;strong&gt;&lt;a href="https://www.facebook.com/groups/nikitarykhlov" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
✈️ &lt;strong&gt;&lt;a href="https://t.me/nikitaRykhlovBlog" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🐦 &lt;strong&gt;&lt;a href="https://x.com/NikitaRykhlov" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, almost forgot — &lt;strong&gt;&lt;a href="https://nikita-rykhlov.tech/" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔔 &lt;em&gt;Follow me not to miss new articles and guides on hot topics!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>⚙️ Go Tools: Code Generation from OpenAPI Specs in Go with oapi-codegen</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Thu, 22 May 2025 13:05:00 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/go-tools-code-generation-from-openapi-specs-in-go-with-oapi-codegen-3jc1</link>
      <guid>https://dev.to/nikita_rykhlov/go-tools-code-generation-from-openapi-specs-in-go-with-oapi-codegen-3jc1</guid>
      <description>&lt;p&gt;When developing web applications in Go, especially when building RESTful APIs, &lt;strong&gt;documentation&lt;/strong&gt; and strict adherence to a specification play a crucial role. For these purposes, the &lt;strong&gt;OpenAPI (Swagger)&lt;/strong&gt; format is often used. However, manually maintaining both code and specification can lead to inconsistencies and errors.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;oapi-codegen&lt;/strong&gt; tool helps automate the creation of part of the code based on an OpenAPI specification.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/oapi-codegen/oapi-codegen" rel="noopener noreferrer"&gt;GitHub Repository: oapi-codegen&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is oapi-codegen?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;oapi-codegen&lt;/strong&gt; is a powerful open-source code generator designed for Go projects. It accepts an &lt;strong&gt;OpenAPI 3.0&lt;/strong&gt; specification in YAML or JSON format and generates ready-to-use Go code that implements server interfaces, client libraries, data models, routes, and other API components.&lt;/p&gt;

&lt;p&gt;This significantly reduces the amount of boilerplate code required to build HTTP servers and clients, while ensuring consistency between the specification and the actual implementation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Data Model Generation&lt;/strong&gt;: Create Go structs based on schemas defined in the OpenAPI spec.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Server Interface Creation&lt;/strong&gt;: Automatically generate handler methods for request processing.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Client SDK Support&lt;/strong&gt;: Generate client packages for interacting with the API.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Input Validation&lt;/strong&gt;: Validate query parameters, headers, request bodies, etc., according to the spec.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Framework Integration&lt;/strong&gt;: Works with popular HTTP routers and frameworks like Chi, Echo, Gin, Fiber, Gorilla Mux, Iris, and even standard &lt;code&gt;net/http&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Extensibility&lt;/strong&gt;: Supports custom templates and imports for tailored generation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You can install the tool using the standard Go command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example Usage
&lt;/h2&gt;

&lt;p&gt;Suppose you have a file &lt;code&gt;openapi.yaml&lt;/code&gt; that describes a simple user management API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.3&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;User API&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;/users/{id}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get user by ID&lt;/span&gt;
      &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;getV1GetUserByID&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;id&lt;/span&gt;
          &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
            &lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123"&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;User response&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/User'&lt;/span&gt;
&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;id&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;name&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a configuration file &lt;code&gt;config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;chi-server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;models&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;server_interface.gen.go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oapi-codegen &lt;span class="nt"&gt;--config&lt;/span&gt; config.yaml openapi.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated file will contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data structures (&lt;code&gt;User&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;ServerInterface&lt;/code&gt; interface with methods for each endpoint&lt;/li&gt;
&lt;li&gt;Route setup and middleware implementation for the selected framework (Chi in this case)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can implement your handler logic without worrying about routing or parsing requests manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Framework Integration
&lt;/h2&gt;

&lt;p&gt;oapi-codegen supports integration with many popular HTTP libraries:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Framework&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Support&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/go-chi/chi" rel="noopener noreferrer"&gt;Chi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/labstack/echo" rel="noopener noreferrer"&gt;Echo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/gofiber/fiber" rel="noopener noreferrer"&gt;Fiber&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/gin-gonic/gin" rel="noopener noreferrer"&gt;Gin&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/gorilla/mux" rel="noopener noreferrer"&gt;gorilla/mux&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/kataras/iris" rel="noopener noreferrer"&gt;Iris&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://pkg.go.dev/net/http" rel="noopener noreferrer"&gt;net/http&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;✅ (Go 1.22+)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each framework has its own set of generated helpers and example implementations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use oapi-codegen?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Specification-Code Consistency
&lt;/h3&gt;

&lt;p&gt;Generating code from an OpenAPI spec ensures that your API always matches the documentation, reducing the risk of mismatches and bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Time Savings
&lt;/h3&gt;

&lt;p&gt;You save time writing routes, validation logic, models, and other repetitive code elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Scalable for Large APIs
&lt;/h3&gt;

&lt;p&gt;Ideal for large-scale APIs where maintaining clean, structured code and making frequent changes is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Design-First API Development
&lt;/h3&gt;

&lt;p&gt;oapi-codegen fits perfectly into a &lt;strong&gt;Design-First API&lt;/strong&gt; workflow, where the specification is written before development begins. This makes the API design process consistent and aligned with the original plan.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;oapi-codegen&lt;/strong&gt; is a powerful tool for automating code generation from OpenAPI specifications in Go. It allows developers to focus on business logic rather than setting up routes and validations manually. If you're working on an API in a team or striving for clean, well-documented code, this utility is an excellent choice.&lt;/p&gt;




&lt;h3&gt;
  
  
  📣 Follow me and read my content on other platforms:
&lt;/h3&gt;

&lt;p&gt;Check out this and other articles on my pages:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/nikita-rykhlov/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📚 &lt;strong&gt;&lt;a href="https://medium.com/@nikita_rykhlov" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
📘 &lt;strong&gt;&lt;a href="https://www.facebook.com/groups/nikitarykhlov" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
✈️ &lt;strong&gt;&lt;a href="https://t.me/nikitaRykhlovBlog" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🐦 &lt;strong&gt;&lt;a href="https://x.com/NikitaRykhlov" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, almost forgot — &lt;strong&gt;&lt;a href="https://nikita-rykhlov.tech/" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔔 &lt;em&gt;Follow me not to miss new articles and guides on hot topics!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>learning</category>
      <category>go</category>
    </item>
    <item>
      <title>📌 Design-First API: Why It Matters for Complex Systems</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Tue, 20 May 2025 13:53:48 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/design-first-api-why-it-matters-for-complex-systems-2i7o</link>
      <guid>https://dev.to/nikita_rykhlov/design-first-api-why-it-matters-for-complex-systems-2i7o</guid>
      <description>&lt;p&gt;Over the years, I’ve learned that a good API doesn’t start with code — it starts with thoughtful design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design-First API&lt;/strong&gt; is an approach where you define the API contract &lt;em&gt;before&lt;/em&gt; writing any implementation code — typically using specifications like OpenAPI (Swagger). This lets teams agree on the shape and behavior of the API early in the development process.&lt;/p&gt;

&lt;p&gt;It’s especially powerful in microservice architectures, where clear, stable interfaces between services are critical.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Why this approach works:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clear separation of concerns&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Early alignment on requirements&lt;/strong&gt; across frontend, backend, and cross-functional teams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation&lt;/strong&gt;: generate clients, server stubs, validation logic (tools like &lt;code&gt;oapi-codegen&lt;/code&gt; help a lot)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Living documentation&lt;/strong&gt; that stays up-to-date with the actual implementation&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 From my experience:
&lt;/h3&gt;

&lt;p&gt;On previous projects — including a B2B wholesale platform and a document templating system — applying the Design-First approach helped us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed up development by enabling parallel workstreams&lt;/li&gt;
&lt;li&gt;Reduce integration bugs&lt;/li&gt;
&lt;li&gt;Keep service contracts clean and consistent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Would you like me to share some practical examples from real-world implementations? Let me know 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
      <category>go</category>
    </item>
    <item>
      <title>Hello! This Is My Technical Blog</title>
      <dc:creator>Nikita Rykhlov</dc:creator>
      <pubDate>Tue, 20 May 2025 13:15:53 +0000</pubDate>
      <link>https://dev.to/nikita_rykhlov/hello-this-is-my-technical-blog-occ</link>
      <guid>https://dev.to/nikita_rykhlov/hello-this-is-my-technical-blog-occ</guid>
      <description>&lt;p&gt;Hi! My name is &lt;strong&gt;Nikita Rykhlov&lt;/strong&gt;, and I’m a Senior Backend Developer with over &lt;strong&gt;5 years of experience&lt;/strong&gt; building scalable, fault-tolerant, and high-performance systems.&lt;/p&gt;

&lt;p&gt;This blog is where I share my technical knowledge, dive into real-world use cases, and explore how to build robust backend solutions.&lt;/p&gt;




&lt;h3&gt;
  
  
  💻 What I Do
&lt;/h3&gt;

&lt;p&gt;Over the past few years, I’ve worked on projects ranging from monolithic applications to distributed microservice architectures.&lt;br&gt;&lt;br&gt;
My main tech stack includes:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Go&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt;, &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;Kafka&lt;/strong&gt;, &lt;strong&gt;Kubernetes&lt;/strong&gt;, &lt;strong&gt;gRPC&lt;/strong&gt;, &lt;strong&gt;DDD&lt;/strong&gt;, &lt;strong&gt;CI/CD&lt;/strong&gt;, and other modern backend technologies.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔍 What I’m Focusing On Now
&lt;/h3&gt;

&lt;p&gt;Right now, I'm deepening my knowledge in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Software Architecture&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System Design&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distributed Systems&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Mesh (Istio)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud-native Development&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, I'm growing as a technical writer and mentor — publishing articles, helping junior developers, and sharing practical tips from everyday engineering tasks.&lt;/p&gt;




&lt;h3&gt;
  
  
  💡 Why I'm Doing This
&lt;/h3&gt;

&lt;p&gt;Because I want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure and deepen my own knowledge&lt;/li&gt;
&lt;li&gt;Help others grow alongside me&lt;/li&gt;
&lt;li&gt;Keep learning consistently&lt;/li&gt;
&lt;li&gt;Make a small but useful contribution to the developer community&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📚 What You’ll Find Here
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In-depth breakdowns of architectural patterns&lt;/li&gt;
&lt;li&gt;Practical Golang guides&lt;/li&gt;
&lt;li&gt;Tool and library reviews&lt;/li&gt;
&lt;li&gt;System design tips&lt;/li&gt;
&lt;li&gt;Personal insights on teamwork and leadership&lt;/li&gt;
&lt;li&gt;Real-world case studies&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 The blog has just begun
&lt;/h3&gt;

&lt;p&gt;This is the very first post — and only the beginning. There’s a lot more coming, for both beginners and experienced developers alike.&lt;/p&gt;

&lt;p&gt;If you want to understand how to build reliable backend systems, grow as an engineer, and stay up-to-date with modern practices — welcome aboard!&lt;/p&gt;

&lt;p&gt;Subscribe and stay tuned for updates.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
