<?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: Muhammad Hadeed Tariq</title>
    <description>The latest articles on DEV Community by Muhammad Hadeed Tariq (@hadeedtariq).</description>
    <link>https://dev.to/hadeedtariq</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%2F1306840%2F0f688b42-79f5-4e67-800b-c90a6eb2a744.png</url>
      <title>DEV Community: Muhammad Hadeed Tariq</title>
      <link>https://dev.to/hadeedtariq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hadeedtariq"/>
    <language>en</language>
    <item>
      <title>Understanding Durability in PostgreSQL The "D" in ACID</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Fri, 18 Jul 2025 07:10:18 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/understanding-durability-in-postgresql-the-d-in-acid-1f40</link>
      <guid>https://dev.to/hadeedtariq/understanding-durability-in-postgresql-the-d-in-acid-1f40</guid>
      <description>&lt;p&gt;In our previous deep-dive articles on ACID, we explored &lt;strong&gt;Isolation&lt;/strong&gt; in PostgreSQL, understanding how isolation levels work under the hood. You can revisit that discussion &lt;a href="https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's been a few months since that article (life happens - juggling a job, projects, and everything in between), but I'm now back and committed to writing consistently. I craft these articles not only for you but also as a resource for my future self, which is why I delve deeply into specific subtopics and include practical prototypes for better clarity. Today, we're going to break down the final, crucial pillar of the ACID model: &lt;strong&gt;Durability&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What Durability Means&lt;/li&gt;
&lt;li&gt;How PostgreSQL Manages Durability Under the Hood&lt;/li&gt;
&lt;li&gt;Write-Ahead Logging (WAL): Durability’s Foundation&lt;/li&gt;
&lt;li&gt;Dirty Pages and Deferred Disk Writes&lt;/li&gt;
&lt;li&gt;Crash Recovery: Why WAL Exists in the First Place&lt;/li&gt;
&lt;li&gt;Practical Implications: A Real-World Banking Scenario&lt;/li&gt;
&lt;li&gt;Distributed Transactions and Durability&lt;/li&gt;
&lt;li&gt;Summary: Why Durability Is Non-Negotiable&lt;/li&gt;
&lt;li&gt;Further Reading&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. What durability means?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Durability&lt;/strong&gt; means that once a &lt;strong&gt;transaction is committed&lt;/strong&gt;, its changes &lt;strong&gt;must persist&lt;/strong&gt;  no matter what. Even if the database server crashes or there's a power loss, the committed changes &lt;strong&gt;must still be there&lt;/strong&gt; when the system comes back up.&lt;/p&gt;

&lt;p&gt;Sounds simple? The internal mechanisms aren't.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How PostgreSQL manages durability under the hood
&lt;/h2&gt;

&lt;p&gt;A common misconception  especially among developers new to PostgreSQL  is that when a write query is executed (like &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt;), the changes are &lt;strong&gt;immediately written to disk&lt;/strong&gt;. Contrary to what many assume, PostgreSQL does &lt;strong&gt;not immediately write changes to disk&lt;/strong&gt; when a query is executed. Instead, it follows a carefully layered process that balances speed with reliability.&lt;/p&gt;

&lt;p&gt;Let’s examine that process in structured steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Modifications Begin in Memory: The Buffer Cache
&lt;/h3&gt;

&lt;p&gt;All write operations in PostgreSQL first modify data &lt;strong&gt;in memory&lt;/strong&gt;, not on disk. This memory region is known as the &lt;strong&gt;buffer cache&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PostgreSQL stores all data in fixed-size blocks called &lt;strong&gt;data pages&lt;/strong&gt; (typically 8KB).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a row is updated or inserted, the relevant data page is loaded into memory (if not already present).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The modification is applied directly to the &lt;strong&gt;in-memory copy&lt;/strong&gt; of the page.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design greatly enhances performance by minimizing disk I/O. However, it introduces a serious risk: &lt;strong&gt;memory is volatile&lt;/strong&gt;. If the system crashes now, those changes are gone.&lt;/p&gt;

&lt;p&gt;So how does PostgreSQL protect those changes? That’s where the next mechanism comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Write-Ahead Logging (WAL): Durability’s Foundation
&lt;/h2&gt;

&lt;p&gt;To guarantee durability, PostgreSQL uses the &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt;  a journal-like structure that records what changes are about to happen &lt;strong&gt;before&lt;/strong&gt; they’re applied to disk.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 What the WAL Does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For every data modification, PostgreSQL generates a WAL record describing the change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This WAL record is written and &lt;strong&gt;flushed to disk&lt;/strong&gt; before the transaction is considered committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only after this flush does PostgreSQL report the transaction as "successfully committed."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that &lt;strong&gt;even if a crash occurs&lt;/strong&gt;, PostgreSQL can use the WAL to replay and &lt;strong&gt;reapply changes&lt;/strong&gt; upon recovery.&lt;/p&gt;

&lt;p&gt;You can dive deeper into this concept in my article on &lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5"&gt;Atomicity&lt;/a&gt;, where I also provide a &lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5#wal-simulation-in-go"&gt;prototype WAL simulation in Go&lt;/a&gt; to illustrate how the logging and recovery process works.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Dirty Pages and Deferred Disk Writes
&lt;/h2&gt;

&lt;p&gt;Even after WAL is safely persisted, the &lt;strong&gt;actual data pages in memory&lt;/strong&gt; are not immediately written to disk. These modified pages are known as &lt;strong&gt;dirty pages&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 When Are Dirty Pages Flushed?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Checkpoints:&lt;/strong&gt; Periodic events where PostgreSQL flushes dirty pages to disk to reduce recovery time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Background Writer:&lt;/strong&gt; A dedicated process that writes dirty pages incrementally, smoothing out I/O spikes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design allows PostgreSQL to &lt;strong&gt;batch writes&lt;/strong&gt; and avoid frequent disk operations, which boosts throughput without compromising durability  since WAL is already safely stored.&lt;/p&gt;

&lt;p&gt;To understand the interaction between buffer cache, background writer, and checkpointing in more depth, refer to &lt;a href="https://www.postgresql.fastware.com/blog/lets-get-back-to-basics-postgresql-memory-components" rel="noopener noreferrer"&gt;this analysis of PostgreSQL's memory components&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Crash Recovery: Why WAL Exists in the First Place
&lt;/h2&gt;

&lt;p&gt;Let’s briefly imagine a system &lt;strong&gt;without WAL&lt;/strong&gt;. If all changes live only in memory, and the server crashes, those changes vanish  even if users were told the transaction succeeded.&lt;/p&gt;

&lt;p&gt;That’s a &lt;strong&gt;catastrophic failure&lt;/strong&gt; of durability.&lt;/p&gt;

&lt;p&gt;WAL ensures that PostgreSQL can recover by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Scanning the WAL log on startup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replaying committed changes to reconstruct the latest consistent state&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This recovery process is &lt;strong&gt;automatic&lt;/strong&gt; and forms the backbone of PostgreSQL's fault tolerance.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Practical Implications: A Real-World Banking Scenario
&lt;/h2&gt;

&lt;p&gt;Consider this use case: a user initiates a &lt;strong&gt;bank transfer&lt;/strong&gt;. The application confirms success, but the server crashes milliseconds later.&lt;/p&gt;

&lt;p&gt;If durability is not guaranteed, that transaction might never make it to the ledger:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The sender’s balance was reduced in memory but not written to disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The recipient never receives the money.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such a failure damages trust and introduces serious compliance issues. Durability mechanisms like WAL ensure that &lt;strong&gt;confirmed transactions remain valid, no matter what&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Distributed Transactions and Durability
&lt;/h2&gt;

&lt;p&gt;Durability becomes even more challenging in &lt;strong&gt;distributed systems&lt;/strong&gt;, where data spans multiple nodes or databases.&lt;/p&gt;

&lt;p&gt;To ensure consistency across all participants, protocols like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Two-Phase Commit (2PC)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Three-Phase Commit (3PC)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consensus algorithms&lt;/strong&gt; (Raft, Paxos)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...are used to make sure either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All nodes commit the transaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or all abort  ensuring &lt;strong&gt;atomicity and durability&lt;/strong&gt; even in partial failures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While PostgreSQL itself is a single-node system, extensions like &lt;strong&gt;Citus&lt;/strong&gt; or external systems like &lt;strong&gt;CockroachDB&lt;/strong&gt; apply these principles in distributed settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Summary: Why Durability Is Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;Durability in PostgreSQL is not an optional feature  it is &lt;strong&gt;integral to correctness&lt;/strong&gt;. Here's a recap of how it is achieved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Changes are made to memory (buffer cache)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A WAL record is generated and flushed to disk before commit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dirty pages remain in memory and are flushed later via checkpoints or background writer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WAL enables crash recovery by replaying committed changes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without these safeguards, &lt;strong&gt;even successful transactions can silently vanish&lt;/strong&gt;, leading to irreparable data loss.&lt;/p&gt;

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

&lt;p&gt;To strengthen your understanding of ACID principles in PostgreSQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk"&gt;Isolation Levels in PostgreSQL (The “I” in ACID)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5"&gt;Atomicity and WAL Simulation in Go&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>postgres</category>
      <category>backend</category>
    </item>
    <item>
      <title>Understanding Durability in PostgreSQL The "D" in ACID</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Fri, 18 Jul 2025 07:10:18 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/understanding-durability-in-postgresql-the-d-in-acid-3o36</link>
      <guid>https://dev.to/hadeedtariq/understanding-durability-in-postgresql-the-d-in-acid-3o36</guid>
      <description>&lt;p&gt;In our previous deep-dive articles on ACID, we explored &lt;strong&gt;Isolation&lt;/strong&gt; in PostgreSQL, understanding how isolation levels work under the hood. You can revisit that discussion &lt;a href="https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's been a few months since that article (life happens - juggling a job, projects, and everything in between), but I'm now back and committed to writing consistently. I craft these articles not only for you but also as a resource for my future self, which is why I delve deeply into specific subtopics and include practical prototypes for better clarity. Today, we're going to break down the final, crucial pillar of the ACID model: &lt;strong&gt;Durability&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What Durability Means&lt;/li&gt;
&lt;li&gt;How PostgreSQL Manages Durability Under the Hood&lt;/li&gt;
&lt;li&gt;Write-Ahead Logging (WAL): Durability’s Foundation&lt;/li&gt;
&lt;li&gt;Dirty Pages and Deferred Disk Writes&lt;/li&gt;
&lt;li&gt;Crash Recovery: Why WAL Exists in the First Place&lt;/li&gt;
&lt;li&gt;Practical Implications: A Real-World Banking Scenario&lt;/li&gt;
&lt;li&gt;Distributed Transactions and Durability&lt;/li&gt;
&lt;li&gt;Summary: Why Durability Is Non-Negotiable&lt;/li&gt;
&lt;li&gt;Further Reading&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. What durability means?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Durability&lt;/strong&gt; means that once a &lt;strong&gt;transaction is committed&lt;/strong&gt;, its changes &lt;strong&gt;must persist&lt;/strong&gt;  no matter what. Even if the database server crashes or there's a power loss, the committed changes &lt;strong&gt;must still be there&lt;/strong&gt; when the system comes back up.&lt;/p&gt;

&lt;p&gt;Sounds simple? The internal mechanisms aren't.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How PostgreSQL manages durability under the hood
&lt;/h2&gt;

&lt;p&gt;A common misconception  especially among developers new to PostgreSQL  is that when a write query is executed (like &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt;), the changes are &lt;strong&gt;immediately written to disk&lt;/strong&gt;. Contrary to what many assume, PostgreSQL does &lt;strong&gt;not immediately write changes to disk&lt;/strong&gt; when a query is executed. Instead, it follows a carefully layered process that balances speed with reliability.&lt;/p&gt;

&lt;p&gt;Let’s examine that process in structured steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Modifications Begin in Memory: The Buffer Cache
&lt;/h3&gt;

&lt;p&gt;All write operations in PostgreSQL first modify data &lt;strong&gt;in memory&lt;/strong&gt;, not on disk. This memory region is known as the &lt;strong&gt;buffer cache&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PostgreSQL stores all data in fixed-size blocks called &lt;strong&gt;data pages&lt;/strong&gt; (typically 8KB).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a row is updated or inserted, the relevant data page is loaded into memory (if not already present).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The modification is applied directly to the &lt;strong&gt;in-memory copy&lt;/strong&gt; of the page.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design greatly enhances performance by minimizing disk I/O. However, it introduces a serious risk: &lt;strong&gt;memory is volatile&lt;/strong&gt;. If the system crashes now, those changes are gone.&lt;/p&gt;

&lt;p&gt;So how does PostgreSQL protect those changes? That’s where the next mechanism comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Write-Ahead Logging (WAL): Durability’s Foundation
&lt;/h2&gt;

&lt;p&gt;To guarantee durability, PostgreSQL uses the &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt;  a journal-like structure that records what changes are about to happen &lt;strong&gt;before&lt;/strong&gt; they’re applied to disk.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 What the WAL Does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For every data modification, PostgreSQL generates a WAL record describing the change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This WAL record is written and &lt;strong&gt;flushed to disk&lt;/strong&gt; before the transaction is considered committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only after this flush does PostgreSQL report the transaction as "successfully committed."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that &lt;strong&gt;even if a crash occurs&lt;/strong&gt;, PostgreSQL can use the WAL to replay and &lt;strong&gt;reapply changes&lt;/strong&gt; upon recovery.&lt;/p&gt;

&lt;p&gt;You can dive deeper into this concept in my article on &lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5"&gt;Atomicity&lt;/a&gt;, where I also provide a &lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5#wal-simulation-in-go"&gt;prototype WAL simulation in Go&lt;/a&gt; to illustrate how the logging and recovery process works.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Dirty Pages and Deferred Disk Writes
&lt;/h2&gt;

&lt;p&gt;Even after WAL is safely persisted, the &lt;strong&gt;actual data pages in memory&lt;/strong&gt; are not immediately written to disk. These modified pages are known as &lt;strong&gt;dirty pages&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 When Are Dirty Pages Flushed?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Checkpoints:&lt;/strong&gt; Periodic events where PostgreSQL flushes dirty pages to disk to reduce recovery time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Background Writer:&lt;/strong&gt; A dedicated process that writes dirty pages incrementally, smoothing out I/O spikes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design allows PostgreSQL to &lt;strong&gt;batch writes&lt;/strong&gt; and avoid frequent disk operations, which boosts throughput without compromising durability  since WAL is already safely stored.&lt;/p&gt;

&lt;p&gt;To understand the interaction between buffer cache, background writer, and checkpointing in more depth, refer to &lt;a href="https://www.postgresql.fastware.com/blog/lets-get-back-to-basics-postgresql-memory-components" rel="noopener noreferrer"&gt;this analysis of PostgreSQL's memory components&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Crash Recovery: Why WAL Exists in the First Place
&lt;/h2&gt;

&lt;p&gt;Let’s briefly imagine a system &lt;strong&gt;without WAL&lt;/strong&gt;. If all changes live only in memory, and the server crashes, those changes vanish  even if users were told the transaction succeeded.&lt;/p&gt;

&lt;p&gt;That’s a &lt;strong&gt;catastrophic failure&lt;/strong&gt; of durability.&lt;/p&gt;

&lt;p&gt;WAL ensures that PostgreSQL can recover by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Scanning the WAL log on startup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replaying committed changes to reconstruct the latest consistent state&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This recovery process is &lt;strong&gt;automatic&lt;/strong&gt; and forms the backbone of PostgreSQL's fault tolerance.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Practical Implications: A Real-World Banking Scenario
&lt;/h2&gt;

&lt;p&gt;Consider this use case: a user initiates a &lt;strong&gt;bank transfer&lt;/strong&gt;. The application confirms success, but the server crashes milliseconds later.&lt;/p&gt;

&lt;p&gt;If durability is not guaranteed, that transaction might never make it to the ledger:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The sender’s balance was reduced in memory but not written to disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The recipient never receives the money.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such a failure damages trust and introduces serious compliance issues. Durability mechanisms like WAL ensure that &lt;strong&gt;confirmed transactions remain valid, no matter what&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Distributed Transactions and Durability
&lt;/h2&gt;

&lt;p&gt;Durability becomes even more challenging in &lt;strong&gt;distributed systems&lt;/strong&gt;, where data spans multiple nodes or databases.&lt;/p&gt;

&lt;p&gt;To ensure consistency across all participants, protocols like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Two-Phase Commit (2PC)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Three-Phase Commit (3PC)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consensus algorithms&lt;/strong&gt; (Raft, Paxos)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...are used to make sure either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All nodes commit the transaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or all abort  ensuring &lt;strong&gt;atomicity and durability&lt;/strong&gt; even in partial failures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While PostgreSQL itself is a single-node system, extensions like &lt;strong&gt;Citus&lt;/strong&gt; or external systems like &lt;strong&gt;CockroachDB&lt;/strong&gt; apply these principles in distributed settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Summary: Why Durability Is Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;Durability in PostgreSQL is not an optional feature  it is &lt;strong&gt;integral to correctness&lt;/strong&gt;. Here's a recap of how it is achieved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Changes are made to memory (buffer cache)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A WAL record is generated and flushed to disk before commit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dirty pages remain in memory and are flushed later via checkpoints or background writer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WAL enables crash recovery by replaying committed changes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without these safeguards, &lt;strong&gt;even successful transactions can silently vanish&lt;/strong&gt;, leading to irreparable data loss.&lt;/p&gt;

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

&lt;p&gt;To strengthen your understanding of ACID principles in PostgreSQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk"&gt;Isolation Levels in PostgreSQL (The “I” in ACID)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5"&gt;Atomicity and WAL Simulation in Go&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>postgres</category>
      <category>backend</category>
    </item>
    <item>
      <title>Hands-On with P2P Networks: Building a Messaging System</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Mon, 12 May 2025 04:46:46 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/hands-on-with-p2p-networks-building-a-messaging-system-12nd</link>
      <guid>https://dev.to/hadeedtariq/hands-on-with-p2p-networks-building-a-messaging-system-12nd</guid>
      <description>&lt;p&gt;Imagine a world where communication happens directly between devices no central server, no middleman, just peer-to-peer. That’s the essence of pure peer-to-peer (P2P) networks. These networks are resilient, decentralized, and increasingly relevant in systems like IoT Device Communication, file sharing, and secure messaging.&lt;/p&gt;

&lt;p&gt;In this article, we’ll break down how a pure peer-to-peer system works by building a simple messaging system from scratch using Golang. We'll explore core P2P concepts like node identification, message routing, and decentralized lookup, and implement them step by step in a way that’s easy to follow even if you’re not a Go expert.&lt;/p&gt;

&lt;p&gt;By the end, you’ll not only understand the theory behind P2P communication but also have a working messaging network where nodes can discover and message each other without relying on any central server.&lt;/p&gt;

&lt;p&gt;Let’s dive into the mechanics behind this powerful network design&lt;/p&gt;

&lt;h2&gt;
  
  
  My Journey: From BitTorrent to DHTs
&lt;/h2&gt;

&lt;p&gt;While writing my own mini BitTorrent client to download Linux distributions, I stumbled upon the term &lt;strong&gt;pure peer-to-peer network&lt;/strong&gt;, and more specifically, &lt;strong&gt;Kademlia&lt;/strong&gt;. At first, these terms felt overwhelming, but I kept exploring and things started to click.&lt;/p&gt;

&lt;p&gt;That’s when I came across something fundamental  the concept of a &lt;strong&gt;Distributed Hash Table (DHT)&lt;/strong&gt;. So first, I’ll break down the core terms used in DHTs to build a solid foundation. Then, we’ll move on to the prototype project I built, which will make everything much clearer through practical demonstration.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;Distributed Hash Table (DHT)&lt;/strong&gt; is basically like a &lt;strong&gt;hash table&lt;/strong&gt;, but spread across many peers in a network. A regular hash table stores &lt;strong&gt;(key, value)&lt;/strong&gt; pairs and offers fast lookups, often in &lt;strong&gt;O(1)&lt;/strong&gt; time complexity, because the data is kept in one place  usually in memory.&lt;/p&gt;

&lt;p&gt;But a &lt;strong&gt;DHT works differently&lt;/strong&gt;. Here, the key-value pairs aren’t stored in one table  they’re &lt;strong&gt;distributed across multiple nodes&lt;/strong&gt; in the network. For example, each node (often identified by its &lt;strong&gt;IP address&lt;/strong&gt; and a unique &lt;strong&gt;Node ID&lt;/strong&gt;) holds a portion of the data. So, when you want to find a key, you don’t search a local table  you need to &lt;strong&gt;find the right node&lt;/strong&gt; that holds it.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;routing algorithms&lt;/strong&gt; come in  they help direct the query to the correct node. Among several DHT routing algorithms, &lt;strong&gt;Kademlia&lt;/strong&gt; stands out as one of the most efficient, because it uses a clever &lt;strong&gt;XOR-based distance metric&lt;/strong&gt; for routing, and it can locate a key in around &lt;strong&gt;O(log N)&lt;/strong&gt; time, where N is the number of nodes in the network.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Kademlia?
&lt;/h2&gt;

&lt;p&gt;Now you might be wondering, &lt;em&gt;what is Kademlia?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Kademlia is a &lt;strong&gt;routing algorithm&lt;/strong&gt; used in DHT-based peer-to-peer systems. It’s built on a clever idea: instead of using geographical or IP-based distances, it uses something called the &lt;strong&gt;XOR distance metric&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each peer (or node) has a &lt;strong&gt;Node ID&lt;/strong&gt;, typically a 160-bit (20-byte) value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you want to find a node or a key, you &lt;strong&gt;XOR&lt;/strong&gt; the target ID with your own Id.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The result gives you a &lt;strong&gt;distance&lt;/strong&gt;, and the &lt;strong&gt;smaller the value (closer the XOR is to 0), the closer the node is to you&lt;/strong&gt; in the DHT.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The most significant bit (from the left) where two IDs differ determines the "distance" in the network  this forms the basis of the routing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I get that all of this may sound a bit maze-like right now, but don’t worry  once I show you an example, it’ll start making a lot more sense.&lt;/p&gt;

&lt;p&gt;Right now, I’m just laying the foundation  explaining the basic concepts you’ll need to understand &lt;strong&gt;Kademlia&lt;/strong&gt; and how it helps structure a pure peer-to-peer network.&lt;/p&gt;

&lt;h2&gt;
  
  
  A guide to routing table
&lt;/h2&gt;

&lt;p&gt;As we dive deeper into &lt;strong&gt;Kademlia&lt;/strong&gt;, another important concept comes up  is  &lt;strong&gt;routing table&lt;/strong&gt;. So, let’s break that down.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;routing table&lt;/strong&gt; is a data structure each node maintains to keep track of other nodes in the network. It is made up of &lt;strong&gt;K-buckets&lt;/strong&gt;  now you might be wondering, what are K-buckets?&lt;/p&gt;

&lt;p&gt;Think of &lt;strong&gt;K-buckets&lt;/strong&gt; as containers that store information about the &lt;strong&gt;closest nodes&lt;/strong&gt; to a given node, based on XOR distance. Each K-bucket typically holds information about &lt;strong&gt;up to K nodes&lt;/strong&gt;  in many implementations, K is 20.&lt;/p&gt;

&lt;p&gt;Now, the number of K-buckets a node has depends on the &lt;strong&gt;bit-length of the Node ID&lt;/strong&gt;. For example, if the Node ID is 160 bits long (as in many real-world systems like BitTorrent), then the routing table will have &lt;strong&gt;160 K-buckets&lt;/strong&gt;  one for each possible bit prefix length. &lt;/p&gt;

&lt;h2&gt;
  
  
  Messaging System
&lt;/h2&gt;

&lt;p&gt;So as you get familiar with the terms used in the pure peer to peer network now we looked in to our example which is a pure peer to peer messaging system&lt;/p&gt;

&lt;p&gt;Let’s start with the &lt;strong&gt;NodeID&lt;/strong&gt;. In our example, each peer is assigned a unique &lt;code&gt;NodeID&lt;/code&gt;, which for simplicity is just &lt;strong&gt;16 bits (2 bytes)&lt;/strong&gt;. This keeps things easy to follow, though in real systems like Kademlia, the IDs are usually 160 bits. The &lt;code&gt;NodeID&lt;/code&gt; is simply an array of bytes and can be represented as a hexadecimal string for readability.&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;const&lt;/span&gt; &lt;span class="n"&gt;IdLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;IdBits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IdBits&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;IdLength&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&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;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&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;p&gt;To measure how "far apart" two nodes are in the network, we use the &lt;strong&gt;XOR distance metric&lt;/strong&gt;  a fundamental concept in DHT (Distributed Hash Table) systems. The XOR of two node IDs gives a new value that represents how different they are bit-by-bit. A smaller XOR result means the nodes are closer in the ID space.&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otherId&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;otherId&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&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;p&gt;Once we can uniquely identify and compare distances between peers, the next step is to maintain a list of known peers. This is where &lt;strong&gt;K-Buckets&lt;/strong&gt; come into play. A K-Bucket is simply a container that stores a small list of peer contacts  typically capped at a fixed number like 20 in real systems, but we’ll use 2 here for demonstration purposes.&lt;/p&gt;

&lt;p&gt;Each contact holds essential info about a peer: its &lt;code&gt;NodeID&lt;/code&gt;, network address (e.g., IP and port), and the last time it was seen online.&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;const&lt;/span&gt; &lt;span class="n"&gt;contactSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Contacts&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Id&lt;/span&gt;           &lt;span class="n"&gt;NodeID&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;last_seen_at&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;KBucket&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;contacts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can search the bucket for a specific peer by ID using the &lt;code&gt;Find&lt;/code&gt; method, which returns the address if the node is found.&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;KBucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;id&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To maintain the K-Bucket, we use the &lt;code&gt;Add&lt;/code&gt; method. It checks if the node already exists. If there's space, it adds the new contact. If the bucket is full, it tries to evict the least recently seen contact using the &lt;code&gt;Evict&lt;/code&gt; method.&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;KBucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="n"&gt;Contacts&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;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;contactSize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contact&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;true&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;evicted&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Evict&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;evicted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contact&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;true&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;"There is no space in this bucket"&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;false&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;p&gt;Eviction is a key part of a robust peer list. When the bucket is full, we sort the contacts by their &lt;code&gt;last_seen_at&lt;/code&gt; timestamp (oldest first) and attempt to ping the oldest contact. If it's offline, we safely remove it and make room for a new one.&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;KBucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Evict&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;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&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;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_seen_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_seen_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&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;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&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="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;...&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;true&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;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This strategy aligns with &lt;strong&gt;Kademlia's Least Recently Seen (LRS)&lt;/strong&gt; eviction policy  ensuring that more active and reliable peers remain in the routing table while stale or unreachable peers are replaced. This is essential for maintaining a responsive and scalable peer-to-peer network.&lt;/p&gt;

&lt;p&gt;Once the structure of the K-Buckets is in place, we move on to the core component of peer discovery: the &lt;strong&gt;Routing Table&lt;/strong&gt;. The routing table acts as a high-level container for all buckets and is responsible for managing peer lookups and updates across the network. It consists of a slice of K-Buckets and the current node's ID.&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;type&lt;/span&gt; &lt;span class="n"&gt;RoutingTable&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;KBucket&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;selfId&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;NodeID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each peer maintains its own routing table, which contains buckets representing various distance ranges from the current node. When a new contact is introduced, the appropriate bucket is determined based on the &lt;strong&gt;Most Significant Bit (MSB)&lt;/strong&gt; index of the XOR distance between the current node ID and the contact's ID. This is handled by the &lt;code&gt;GetMSBIndex&lt;/code&gt; utility function:&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;func&lt;/span&gt; &lt;span class="n"&gt;GetMSBIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sign&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BitLen&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function ensures that a contact is placed in the correct bucket based on its logical distance from the current node. If the calculated distance is zero (i.e., the node is attempting to add itself), the function returns &lt;code&gt;-1&lt;/code&gt;, and the contact is ignored.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Add&lt;/code&gt; method of the routing table adds a given contact to the correct bucket, if possible:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selfId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GetMSBIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;isAdded&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isAdded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;"The contact is added to bucket: %d &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;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;"Not added"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;"Same peer can't connect with each other"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;p&gt;Another critical feature is the ability to &lt;strong&gt;find the closest peers&lt;/strong&gt; to a target node ID. This is particularly useful during message forwarding and when bootstrapping the network. The &lt;code&gt;FindClosestContacts&lt;/code&gt; method performs a global scan across all buckets, sorts the contacts by XOR distance to the target ID, and returns the closest &lt;code&gt;k&lt;/code&gt; contacts:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;FindClosestContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetID&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&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="n"&gt;Contacts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;allContacts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buckets&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;allContacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allContacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allContacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;targetID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allContacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;targetID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allContacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allContacts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;allContacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;allContacts&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To support the initialization of nodes and routing tables, we define utility constructors. &lt;code&gt;NewNodeId&lt;/code&gt; generates a hashed node ID using SHA-1, and &lt;code&gt;NewRoutingTable&lt;/code&gt; initializes the routing table with empty K-Buckets.&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;func&lt;/span&gt; &lt;span class="n"&gt;NewNodeId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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;NodeID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;newId&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newId&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newId&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;newId&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;NewRoutingTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selfID&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;buckets&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="n"&gt;KBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IdBits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KBucket&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;contacts&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="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contactSize&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;selfId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;selfID&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;h2&gt;
  
  
  Adding Messaging Capability to Peers
&lt;/h2&gt;

&lt;p&gt;With the routing infrastructure in place, we can now add real messaging capabilities between nodes in the network. This is crucial for simulating peer-to-peer interactions like sending commands, exchanging data, or simulating real-world communication in a distributed system.&lt;/p&gt;

&lt;p&gt;We introduce a &lt;code&gt;MessagingPeer&lt;/code&gt; structure, which encapsulates the logic to start a server, send and receive messages, and use the routing table to locate other peers in the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Message Structure
&lt;/h3&gt;

&lt;p&gt;We define a &lt;code&gt;Messages&lt;/code&gt; struct to encapsulate message-related data:&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;type&lt;/span&gt; &lt;span class="n"&gt;Messages&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SenderId&lt;/span&gt;       &lt;span class="n"&gt;NodeID&lt;/span&gt;
    &lt;span class="n"&gt;ReceiverId&lt;/span&gt;     &lt;span class="n"&gt;NodeID&lt;/span&gt;
    &lt;span class="n"&gt;MessageContent&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;MessageId&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SenderId&lt;/code&gt; and &lt;code&gt;ReceiverId&lt;/code&gt; identify the message endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MessageContent&lt;/code&gt; holds the actual message text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MessageId&lt;/code&gt; can be used for tracking, deduplication, or threading.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. MessagingPeer Struct
&lt;/h3&gt;

&lt;p&gt;We now define a &lt;code&gt;MessagingPeer&lt;/code&gt; to wrap the node's messaging functionality:&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;type&lt;/span&gt; &lt;span class="n"&gt;MessagingPeer&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;           &lt;span class="n"&gt;NodeID&lt;/span&gt;
    &lt;span class="n"&gt;Messages&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;
    &lt;span class="n"&gt;Port&lt;/span&gt;         &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;RoutingTable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Messages&lt;/code&gt; keeps a record of received messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RoutingTable&lt;/code&gt; is used to find other nodes (reusing our earlier routing logic).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each peer listens on its own &lt;code&gt;Port&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Starting the Server
&lt;/h3&gt;

&lt;p&gt;Each peer runs a TCP server to receive messages:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ln&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;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&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;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to start server: %v"&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;conn&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;ln&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Accept&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;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&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;ul&gt;
&lt;li&gt;&lt;p&gt;The server listens on its configured port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incoming connections are handled concurrently.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Receiving and Storing Messages
&lt;/h3&gt;

&lt;p&gt;When a peer receives a message, it is deserialized and stored:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;buf&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="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;n&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;conn&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;buf&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;Messages&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;msg&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="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&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;p&gt;This allows each peer to act as a receiver in the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Local Node Lookup
&lt;/h3&gt;

&lt;p&gt;We add a helper function that wraps our existing routing logic to find nodes by ID:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;FindNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetID&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Contacts&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;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindClosestContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contactSize&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;p&gt;This uses our bucket-based routing table to get nearby contacts.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Iterative Lookup Across Peers
&lt;/h3&gt;

&lt;p&gt;If a node is not found locally, we query other known peers:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;IterativeFindNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetId&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;knownPeers&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;visited&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="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&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;shortList&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindClosestContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contactSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;closest&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;shortList&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;newShortList&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;shortList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;idStr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&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;visited&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idStr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idStr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
            &lt;span class="n"&gt;peer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;knownPeers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idStr&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;peer&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;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;closerContacts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;peer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;closerContacts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;newShortList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newShortList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&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;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newShortList&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&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;targetId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;contactSize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;contactSize&lt;/span&gt;&lt;span class="p"&gt;]&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;EqualContacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;closest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;
        &lt;span class="n"&gt;shortList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newShortList&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;closest&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Works similarly to Kademlia’s node lookup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stops when no closer peers are found.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Sending a Message to Another Peer
&lt;/h3&gt;

&lt;p&gt;We now allow one peer to send a message to another, using either the routing table or iterative search:&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&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;peerId&lt;/span&gt; &lt;span class="n"&gt;NodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;peerId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"same peer can't send message to itself"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GetMSBIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;peerAddress&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peerId&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;peerAddress&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;closest&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IterativeFindNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;closest&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;con&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;peerId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;peerAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;
                &lt;span class="k"&gt;break&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;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;peerAddress&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not find peer address"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;conn&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;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peerAddress&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="s"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to connect to peer: %w"&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;SenderId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;mp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ReceiverId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;peerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;MessageContent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;MessageId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"Random"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;msgBytes&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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="s"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to serialize message: %w"&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;_&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;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msgBytes&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="s"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to send message: %w"&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="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"message sent successfully"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Attempts direct routing first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Falls back to iterative peer discovery if needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Message is serialized as JSON and sent via TCP.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Peer Initialization
&lt;/h3&gt;

&lt;p&gt;Finally, we define a constructor for &lt;code&gt;MessagingPeer&lt;/code&gt;:&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;func&lt;/span&gt; &lt;span class="n"&gt;NewMessagingPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;add&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;"%s:%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;selfID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewNodeId&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;add&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="n"&gt;selfID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Messages&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="n"&gt;Messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NewRoutingTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selfID&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;p&gt;This sets the &lt;code&gt;NodeID&lt;/code&gt; using the address + port as a seed, ensuring uniqueness in the network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main Function: Bringing It All Together
&lt;/h2&gt;

&lt;p&gt;As all the components are now in place for our &lt;strong&gt;simple peer-to-peer messaging system&lt;/strong&gt;, we move on to our &lt;code&gt;main&lt;/code&gt; function, where we use everything we’ve built so far  peer creation, server start-up, routing table population, and the actual message sending mechanism.&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="s"&gt;"time"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/HadeedTariq/p-to-p-msg-system-kademlia/algo"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We import the necessary packages  including our &lt;code&gt;algo&lt;/code&gt; package where all the peer and routing logic lives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating and Starting Peers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;peerA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessagingPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;peerA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;peerB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessagingPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;peerB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;peerC&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessagingPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;peerC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;peerD&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessagingPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8003&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;peerD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;peerE&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessagingPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8004&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;peerE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create five peers (&lt;code&gt;A&lt;/code&gt; through &lt;code&gt;E&lt;/code&gt;), each listening on a unique port.&lt;br&gt;&lt;br&gt;
Each &lt;code&gt;MessagingPeer&lt;/code&gt; starts its own server in a goroutine to handle incoming messages concurrently.&lt;/p&gt;

&lt;p&gt;We add a small delay using &lt;code&gt;time.Sleep&lt;/code&gt; to ensure all servers are up before proceeding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manually Populating Routing Tables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;peerB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;peerB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;peerC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;peerD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RoutingTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contacts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;peerE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&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;p&gt;In a real distributed network, peers discover each other via ping or bootstrap mechanisms.&lt;br&gt;&lt;br&gt;
Here, we &lt;strong&gt;manually add entries&lt;/strong&gt; to some routing tables to simulate an imperfect but realistic partial network view.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Peer B knows A and C.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C knows D.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;D knows E.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mimics limited knowledge in a real-world scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simulating the Network Map
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MessagingPeer&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;peerA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;peerA&lt;/span&gt;
&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;peerB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;peerB&lt;/span&gt;
&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;peerC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;peerC&lt;/span&gt;
&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;peerD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;peerD&lt;/span&gt;
&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;peerE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;peerE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We construct a &lt;code&gt;network&lt;/code&gt; map to simulate our distributed environment.&lt;br&gt;&lt;br&gt;
This acts as a directory the sending peer can use during &lt;code&gt;IterativeFindNode()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note: This is only for simulation. In a real P2P system, peers wouldn’t have access to this map directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sending the Message
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;msg&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;peerB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from B to E"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peerE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;network&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="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;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;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s where the actual communication happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Peer B tries to send a message to Peer E.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since B doesn't know E directly, it uses the &lt;strong&gt;iterative lookup&lt;/strong&gt; we implemented earlier to find E via the known path B → C → D → E.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once found, it establishes a TCP connection and sends the message.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If successful, we see &lt;code&gt;"message sent successfully"&lt;/code&gt; printed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping the Program Alive
&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;select&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We block the main goroutine using &lt;code&gt;select {}&lt;/code&gt; so all servers stay alive and continue listening for incoming messages.&lt;/p&gt;

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

&lt;p&gt;So as you can see, we’ve built our own small peer-to-peer messaging system from scratch! I’ve tried to explain each concept in a simple and easy-to-understand way so you don’t need to copy and paste everything blindlyjust understand the flow and play around with the code.&lt;br&gt;
You can find the complete source code here: &lt;a href="https://github.com/HadeedTariq/p-to-p-msg-system-kademlia" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;
I also write about database-related topics and other backend concepts. Feel free to check out more of my work here: &lt;a href="https://dev.to/hadeedtariq"&gt;@HadeedTariq on Dev.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before I end this post, I want to take a moment to express my deep love and unwavering support for our Palestinian Muslim brothers and sisters 🇵🇸. Their lives, their struggles, and their voices matter. In a world that too often turns a blind eye, we must continue to speak up and stand with the oppressed. May justice rise, may peace prevail, and may the people of Palestine live with dignity, freedom, and hope. You are not forgotten &lt;strong&gt;your life matters&lt;/strong&gt;.The recent surge in terrorist activities and the brutal actions by Israel are unequivocally condemned.&lt;/p&gt;

</description>
      <category>backenddevelopment</category>
      <category>go</category>
      <category>p2p</category>
      <category>learning</category>
    </item>
    <item>
      <title>Understanding Isolation in PostgreSQL: The “I” in ACID</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Sun, 04 May 2025 11:39:43 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk</link>
      <guid>https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk</guid>
      <description>&lt;p&gt;In the previous &lt;a href="https://dev.to/hadeedtariq/mastering-database-consistency-unlocking-the-c-in-acid-with-postgresql-4m6p"&gt;article&lt;/a&gt;, we explored the &lt;strong&gt;Consistency&lt;/strong&gt; aspect of ACID — the fundamental set of properties that define reliable database transactions. As part of this deep dive series on ACID, I’m using &lt;strong&gt;PostgreSQL&lt;/strong&gt; as the reference system, but the principles largely apply to most relational databases with only minor differences in implementation.&lt;/p&gt;

&lt;p&gt;Today’s topic is &lt;strong&gt;Isolation&lt;/strong&gt;, the “I” in ACID. Isolation becomes critical when &lt;strong&gt;multiple transactions run concurrently&lt;/strong&gt;. It ensures that the &lt;strong&gt;outcome of executing transactions in parallel is the same as if they were executed one after another&lt;/strong&gt; — avoiding weird side effects, data corruption, or misleading results.&lt;/p&gt;

&lt;p&gt;Imagine two transactions running at the same time: one updating a balance and another reading it. Without proper isolation, the reader might get a value that never actually existed, leading to inconsistencies or even security issues.&lt;/p&gt;

&lt;p&gt;Each &lt;strong&gt;isolation level&lt;/strong&gt; represents a tradeoff between &lt;strong&gt;performance and consistency&lt;/strong&gt;. The right choice depends on your &lt;strong&gt;application’s needs&lt;/strong&gt;. Some systems prioritize consistency (e.g., banking apps), while others may prefer availability and speed (e.g., analytics dashboards). We’ll explore all major isolation levels with examples and caveats so you know when and why to use each.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of Contents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Read Uncommitted&lt;/li&gt;
&lt;li&gt;Read Committed&lt;/li&gt;
&lt;li&gt;Repeatable Read&lt;/li&gt;
&lt;li&gt;Serializable Read&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Read Uncommitted
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Read Uncommitted&lt;/strong&gt; isolation level allows a transaction to read data that has been modified by another transaction but not yet committed. While this may appear beneficial for performance, especially in highly concurrent systems, it introduces a significant risk: the possibility of &lt;strong&gt;dirty reads&lt;/strong&gt;. A dirty read occurs when a transaction reads data that is later rolled back, meaning the data never officially existed in the database.&lt;/p&gt;

&lt;p&gt;At this level, no locks are acquired on the data being read, so transactions are free to read rows that might still be in the process of being changed. This non-blocking behavior can improve speed, but it does so at the cost of consistency and reliability. In practice, systems operating under Read Uncommitted may make decisions based on temporary or invalid data, which can be especially dangerous in environments where correctness matters—like financial systems or inventory tracking. Let's take a look with example.&lt;/p&gt;

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

&lt;p&gt;Here’s how a dirty read can happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction A&lt;/strong&gt; starts and updates a user's balance from &lt;code&gt;100&lt;/code&gt; to &lt;code&gt;200&lt;/code&gt;. However, the change is not yet committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction B&lt;/strong&gt; runs while Transaction A is still open and reads the new balance of &lt;code&gt;200&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Believing the balance is updated, Transaction B takes some action—like approving a purchase or initiating a transfer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Later, &lt;strong&gt;Transaction A fails&lt;/strong&gt; or is &lt;strong&gt;rolled back&lt;/strong&gt;, which means the update to &lt;code&gt;200&lt;/code&gt; is discarded and the balance remains &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, Transaction B has already acted on the assumption that the balance was &lt;code&gt;200&lt;/code&gt;, even though that value was never officially stored.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a dirty read: Transaction B relied on data that was never committed and ultimately did not exist. As a result, the system may end up in an incorrect state—something that is especially dangerous when financial or business-critical logic is involved.&lt;/p&gt;

&lt;p&gt;Because of such risks, &lt;strong&gt;Read Uncommitted provides no isolation guarantees&lt;/strong&gt; and is rarely suitable for real-world applications. It might be acceptable in certain reporting or analytics tasks where minor inconsistencies are tolerable, but in most cases, more reliable isolation levels like &lt;strong&gt;Read Committed&lt;/strong&gt; are preferred.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read Committed
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Read Committed&lt;/strong&gt; isolation level ensures that a transaction can only read data that has already been committed by other transactions. This provides a significant improvement over Read Uncommitted, as it &lt;strong&gt;prevents dirty reads&lt;/strong&gt;. A transaction will never see partial or rollback-prone changes made by others.&lt;/p&gt;

&lt;p&gt;However, while this level avoids dirty reads, it doesn't completely eliminate concurrency issues. One key problem that can still occur under Read Committed is a &lt;strong&gt;write-write conflict&lt;/strong&gt;, often referred to as a &lt;strong&gt;lost update&lt;/strong&gt;. This happens when two transactions read the same data, modify it independently, and then overwrite each other’s results, unintentionally discarding one set of changes.&lt;/p&gt;

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

&lt;p&gt;Here’s how a lost update can occur under Read Committed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction A&lt;/strong&gt; reads a value &lt;code&gt;x = 0&lt;/code&gt; from the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction B&lt;/strong&gt; also reads the same value &lt;code&gt;x = 0&lt;/code&gt; shortly after.&lt;/li&gt;
&lt;li&gt;Both transactions independently increment &lt;code&gt;x&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction A&lt;/strong&gt; writes &lt;code&gt;x = 1&lt;/code&gt; back to the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction B&lt;/strong&gt; then also writes &lt;code&gt;x = 1&lt;/code&gt;, &lt;strong&gt;overwriting A’s result&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final value in the database is &lt;code&gt;1&lt;/code&gt;, even though both transactions performed an increment, and logically, the value should have been &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This type of issue happens because Read Committed does not prevent two transactions from reading the same data at the same time, nor does it coordinate their updates. Without additional mechanisms like &lt;strong&gt;explicit locking&lt;/strong&gt;, &lt;strong&gt;optimistic concurrency control&lt;/strong&gt;, or &lt;strong&gt;application-level safeguards&lt;/strong&gt;, such conflicts can go undetected.&lt;/p&gt;

&lt;p&gt;Read Committed is the &lt;strong&gt;default isolation level in PostgreSQL&lt;/strong&gt;, offering a reasonable balance between performance and safety for many use cases. It’s a safe starting point for most applications, but developers must still be aware of its limitations under concurrent write scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeatable Read
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Repeatable Read&lt;/strong&gt; isolation level ensures that once a transaction reads data, that data stays the same throughout the life of the transaction. Even if other transactions update or insert rows in the background, your transaction continues to operate on a consistent snapshot of the data. This prevents anomalies like &lt;strong&gt;non-repeatable reads&lt;/strong&gt; and in PostgreSQL, even &lt;strong&gt;phantom reads&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This level is useful when you need strong consistency within a transaction — like generating reports, doing multi-step calculations, or reading the same data multiple times while expecting it not to change.&lt;/p&gt;

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

&lt;p&gt;Here’s what Repeatable Read helps prevent:&lt;/p&gt;

&lt;h4&gt;
  
  
  Non-Repeatable Reads
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction A&lt;/strong&gt; starts and reads a row where &lt;code&gt;x = 1&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Meanwhile, &lt;strong&gt;Transaction B&lt;/strong&gt; updates that same row to &lt;code&gt;x = 3&lt;/code&gt; and commits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;strong&gt;Transaction A&lt;/strong&gt; reads &lt;code&gt;x&lt;/code&gt; again, it still sees &lt;code&gt;x = 1&lt;/code&gt;, not the updated value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This guarantees that any value you read &lt;strong&gt;once&lt;/strong&gt; stays the same, regardless of external changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Phantom Reads
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction A&lt;/strong&gt; runs a query like &lt;code&gt;SELECT * FROM users WHERE age &amp;gt; 30&lt;/code&gt; and sees 5 users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the same time, &lt;strong&gt;Transaction B&lt;/strong&gt; inserts a new user with &lt;code&gt;{ name: "John", age: 35 }&lt;/code&gt; and commits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;strong&gt;Transaction A&lt;/strong&gt; reruns the same query, it still sees &lt;strong&gt;only the original 5 users&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The new user (“John”) doesn’t appear because the snapshot taken at the start of the transaction &lt;strong&gt;excludes any changes made afterward&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Behind the scenes, PostgreSQL uses &lt;strong&gt;MVCC (Multi-Version Concurrency Control)&lt;/strong&gt; to maintain this behavior. It captures a &lt;strong&gt;snapshot&lt;/strong&gt; of the database when the transaction starts, and all reads are based on that version. If a conflicting update is attempted, PostgreSQL may throw a &lt;strong&gt;serialization error&lt;/strong&gt;, requiring the transaction to retry.&lt;/p&gt;

&lt;p&gt;While PostgreSQL offers strong protection under Repeatable Read, &lt;strong&gt;behavior varies across databases&lt;/strong&gt;. For example, in &lt;strong&gt;MySQL&lt;/strong&gt;, phantom reads can still occur unless you use extra locking. So even though the name is the same, the guarantees may differ — always check how your specific database implements it.&lt;/p&gt;

&lt;p&gt;Sure! Here's the &lt;strong&gt;Serializable Reads&lt;/strong&gt; section rewritten in a medium-length, article-friendly format with a clear explanation and example under a single subheading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serializable Read
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Serializable&lt;/strong&gt; isolation level is the strictest isolation guarantee offered by PostgreSQL. It ensures that all concurrent transactions behave as if they were executed one after another, in some serial order — even if they’re actually running in parallel.&lt;/p&gt;

&lt;p&gt;PostgreSQL doesn’t use traditional locking to achieve this. Instead, it uses a smarter, more efficient technique called &lt;strong&gt;Serializable Snapshot Isolation (SSI)&lt;/strong&gt;. This approach avoids blocking other transactions during reads or writes. Instead of holding locks, PostgreSQL watches for patterns that &lt;em&gt;could&lt;/em&gt; lead to inconsistencies and rolls back one of the transactions if a conflict is detected.&lt;/p&gt;

&lt;p&gt;This ensures consistency but introduces the possibility of &lt;strong&gt;serialization failures&lt;/strong&gt;, meaning your transaction might be rolled back and you’ll need to retry it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example — Preventing Subtle Conflicts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction A&lt;/strong&gt; reads from a table of available coupons where &lt;code&gt;active = true&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction B&lt;/strong&gt; simultaneously marks one of those coupons as &lt;code&gt;active = false&lt;/code&gt; and commits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction A&lt;/strong&gt;, unaware of the change, proceeds to assign the now-inactive coupon to a user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PostgreSQL detects that the sequence of actions would not be valid if executed in order and &lt;strong&gt;rolls back Transaction A&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This rollback ensures the system remains consistent, as if Transaction B had completed before Transaction A even started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key point&lt;/strong&gt;: In PostgreSQL, Serializable doesn’t block others like traditional locking — it lets transactions run in parallel and only intervenes if the outcome would be invalid. Other databases like MySQL or SQL Server often rely on row or table locking to achieve similar guarantees, which can reduce performance or cause deadlocks.&lt;/p&gt;

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

&lt;p&gt;Isolation is a &lt;strong&gt;crucial piece of the puzzle&lt;/strong&gt; when it comes to building reliable, concurrent applications. Picking the right isolation level is all about &lt;strong&gt;understanding your use case&lt;/strong&gt; — whether you're building a banking system that demands full consistency or a high-throughput analytics app that prioritizes availability.&lt;/p&gt;

&lt;p&gt;PostgreSQL gives you &lt;strong&gt;excellent control and guarantees&lt;/strong&gt;, especially through MVCC and SSI. But remember — with stronger isolation often comes &lt;strong&gt;increased complexity&lt;/strong&gt; and &lt;strong&gt;performance trade-offs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before I end this post, I want to take a moment to express my deep love and unwavering support for our Palestinian Muslim brothers and sisters 🇵🇸. Their lives, their struggles, and their voices matter. In a world that too often turns a blind eye, we must continue to speak up and stand with the oppressed. May justice rise, may peace prevail, and may the people of Palestine live with dignity, freedom, and hope. You are not forgotten—&lt;strong&gt;your life matters&lt;/strong&gt;.The recent surge in terrorist activities and the brutal actions by Israel are unequivocally condemned.&lt;/p&gt;

</description>
      <category>acid</category>
      <category>database</category>
      <category>postgres</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Mastering Database Consistency: Unlocking the 'C' in ACID with PostgreSQL</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Sun, 20 Apr 2025 13:31:17 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/mastering-database-consistency-unlocking-the-c-in-acid-with-postgresql-4m6p</link>
      <guid>https://dev.to/hadeedtariq/mastering-database-consistency-unlocking-the-c-in-acid-with-postgresql-4m6p</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5"&gt;last article&lt;/a&gt;, I talked about &lt;strong&gt;atomicity&lt;/strong&gt; in databases. As you know, I’m doing a deep-dive series on &lt;strong&gt;ACID&lt;/strong&gt; in databases, and now it's time to tackle the &lt;strong&gt;C&lt;/strong&gt;—&lt;strong&gt;Consistency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As always, I’ll use PostgreSQL for demonstration, but with minor changes, this applies to almost all traditional relational databases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt; means that when a transaction runs—which is just a group of operations—the state of the database remains valid both &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; the transaction. This includes ensuring that constraints like &lt;code&gt;UNIQUE&lt;/code&gt;, &lt;code&gt;NOT NULL&lt;/code&gt;, &lt;code&gt;CHECK&lt;/code&gt;, and foreign key rules are upheld. If a transaction would violate these rules, it’s rolled back automatically.&lt;/p&gt;

&lt;p&gt;Let's deep dive into:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Real-World Consistency: The E-commerce Platform
&lt;/li&gt;
&lt;li&gt;
Consistency Through Relationships (Cascade Operations)
&lt;/li&gt;
&lt;li&gt;How PostgreSQL Enforces Consistency Internally&lt;/li&gt;
&lt;li&gt;Consistency Difference from CAP Theorem&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real-World Consistency: The E-commerce Platform
&lt;/h2&gt;

&lt;p&gt;Let’s say you’re building an e-commerce platform. In a typical order transaction, several operations happen together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Reducing stock&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating the order&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sending notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These operations must respect all business rules and constraints before being committed. If, for example, the stock level drops below zero or the order cannot be created due to a constraint violation, the entire transaction is rolled back. This is where consistency from the ACID principles ensures that your database remains in a valid state — no partial or inconsistent data gets committed.&lt;br&gt;
For instance, stock should never go below zero. To enforce that, you might add a constraint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;stock_positive&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine during a transaction, a customer places an order for more items than are available. If the constraint fails but the order still gets created — your database is &lt;strong&gt;not consistent&lt;/strong&gt;, and thus not ACID compliant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency ensures that all business rules, constraints, and dependencies are respected before a transaction is committed.&lt;/strong&gt; It keeps your data clean and trustworthy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Consistency Through Relationships (Cascade Operations)
&lt;/h2&gt;

&lt;p&gt;But consistency doesn’t stop at just field-level checks. It also involves maintaining &lt;strong&gt;referential integrity&lt;/strong&gt; across related tables.&lt;/p&gt;

&lt;p&gt;Imagine your database has a &lt;code&gt;users&lt;/code&gt; table and an &lt;code&gt;orders&lt;/code&gt; table, where each order belongs to a user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a user is deleted, all of their orders should be deleted too. PostgreSQL handles this via cascading operations, which are processed synchronously as part of the same transaction — helping maintain consistency across tables.&lt;/p&gt;

&lt;p&gt;To visually understand this process, take a look at the diagram below. It illustrates the path of a cascade delete, showing how PostgreSQL ensures that both the user and their associated orders are handled within the same transaction, enforcing referential integrity.&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%2F5irgnvm7n9xam88ohshj.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%2F5irgnvm7n9xam88ohshj.png" alt="Consistency Diagram" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, some large-scale systems offload these cascading deletions to background jobs or asynchronous triggers. While this may improve performance, it introduces risk: if the job fails or runs late, and another transaction reads the data that should have been deleted, your system may act on stale or invalid data.&lt;/p&gt;

&lt;p&gt;This leads to a consistency problem — not because of the database engine itself, but due to how the application is designed.&lt;/p&gt;




&lt;h2&gt;
  
  
  How PostgreSQL Enforces Consistency Internally
&lt;/h2&gt;

&lt;p&gt;To enforce this kind of consistency — both in constraints and in relational integrity — PostgreSQL relies on a mechanism called the &lt;strong&gt;WAL (Write-Ahead Log)&lt;/strong&gt;, which I discussed in detail in the &lt;a href="https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5"&gt;previous article on Atomicity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Whenever a transaction begins, every operation — whether it’s a new insert, a cascading delete from a foreign key relationship, or a column update — is first written to the WAL &lt;em&gt;before&lt;/em&gt; it modifies the actual data in your tables. &lt;/p&gt;

&lt;p&gt;This ensures that &lt;strong&gt;no partial or invalid state ever reaches the persistent database&lt;/strong&gt;. If something fails (like a constraint violation or a cascading issue), PostgreSQL can safely roll back using the WAL, guaranteeing that the data remains consistent and valid throughout the system.&lt;/p&gt;

&lt;p&gt;Here’s a high-level look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN TRANSACTION
  → Write operation to WAL (INSERT, DELETE, UPDATE)
  → Validate constraints (CHECK, UNIQUE, FK, NOT NULL)
  → If everything is valid: COMMIT
  → Else: ROLLBACK (discard uncommitted WAL entries)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So even in complex operations like deleting a user and all their orders via &lt;code&gt;ON DELETE CASCADE&lt;/code&gt;, all changes are recorded in WAL first. If &lt;strong&gt;anything fails&lt;/strong&gt;, the entire chain — including the dependent deletions — is rolled back, and your data remains untouched and valid.&lt;/p&gt;

&lt;p&gt;This is how &lt;strong&gt;PostgreSQL ensures relational consistency — even deep across table relationships — at the transaction level&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency Difference from CAP Theorem
&lt;/h2&gt;

&lt;p&gt;Many people confuse &lt;strong&gt;&lt;a href="https://www.ibm.com/think/topics/cap-theorem" rel="noopener noreferrer"&gt;CAP Theorem&lt;/a&gt;&lt;/strong&gt; consistency with &lt;strong&gt;ACID consistency&lt;/strong&gt;, but they refer to different things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CAP consistency&lt;/strong&gt; applies to &lt;strong&gt;distributed systems&lt;/strong&gt; where data is replicated across multiple nodes. It means that &lt;strong&gt;every node must reflect the most recent write&lt;/strong&gt;, or return an error if it cannot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For example, if a user writes data to &lt;strong&gt;Node A&lt;/strong&gt;, and another user reads that data immediately from &lt;strong&gt;Node B&lt;/strong&gt;, CAP consistency guarantees that Node B either returns the updated value or fails to respond if the update hasn't reached it yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This differs from &lt;strong&gt;eventual consistency&lt;/strong&gt;, where &lt;strong&gt;Node B may return outdated (stale) data&lt;/strong&gt; while it catches up — but eventually, all nodes will synchronize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each model has trade-offs: &lt;strong&gt;CAP consistency&lt;/strong&gt; favors correctness, while &lt;strong&gt;eventual consistency&lt;/strong&gt; favors availability and scalability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So CAP consistency is about all replicas agreeing on the same value while ACID consistency is about maintaining data integrity within a single database instance.&lt;/p&gt;

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

&lt;p&gt;Consistency is not just about applying rules—it’s about &lt;strong&gt;ensuring your business logic, data integrity, and user trust remain intact&lt;/strong&gt;, even when the system is under load.&lt;/p&gt;

&lt;p&gt;From constraint checking to WAL logging to concurrency control, PostgreSQL has your back. And if you’re building critical apps—like an e-commerce platform—you should care deeply about this stuff.&lt;/p&gt;

&lt;p&gt;Before I end this post, I want to take a moment to express my deep love and unwavering support for our Palestinian Muslim brothers and sisters 🇵🇸. Their lives, their struggles, and their voices matter. In a world that too often turns a blind eye, we must continue to speak up and stand with the oppressed. May justice rise, may peace prevail, and may the people of Palestine live with dignity, freedom, and hope. You are not forgotten—&lt;strong&gt;your life matters&lt;/strong&gt;.The recent surge in terrorist activities and the brutal actions by Israel are unequivocally condemned.&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>acid</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understanding Atomicity: The First Pillar of ACID Transactions</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Sun, 13 Apr 2025 06:33:48 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5</link>
      <guid>https://dev.to/hadeedtariq/understanding-atomicity-the-first-pillar-of-acid-transactions-4gm5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you've worked with relational databases, you've likely come across the term &lt;strong&gt;ACID&lt;/strong&gt;—an acronym that ensures reliable database transactions. Each letter in ACID holds deep meaning and importance: &lt;strong&gt;Atomicity&lt;/strong&gt;, &lt;strong&gt;Consistency&lt;/strong&gt;, &lt;strong&gt;Isolation&lt;/strong&gt;, and &lt;strong&gt;Durability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we're going to focus on the first pillar: &lt;strong&gt;Atomicity&lt;/strong&gt;. You’ll understand what it means, why it matters, and how databases implement it internally. This post includes a real-world analogy, a SQL implementation, and even a hands-on &lt;strong&gt;Go simulation of a Write-Ahead Log (WAL)&lt;/strong&gt;—a key mechanism databases like &lt;strong&gt;PostgreSQL&lt;/strong&gt; use to guarantee atomicity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're interested in diving into the rest of ACID properties, you can explore:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/mastering-database-consistency-unlocking-the-c-in-acid-with-postgresql-4m6p"&gt;Consistency in ACID&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/understanding-isolation-in-postgresql-the-i-in-acid-22hk"&gt;Isolation in ACID&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/hadeedtariq/understanding-durability-in-postgresql-the-d-in-acid-1f40"&gt;Durability in ACID&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's deep dive in to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is Atomicity in Databases?&lt;/li&gt;
&lt;li&gt;Atomicity in Action: A Collaborative Recipe Platform&lt;/li&gt;
&lt;li&gt;How Databases Ensure Atomicity (Under the Hood)&lt;/li&gt;
&lt;li&gt;Write Ahead Logging Explained&lt;/li&gt;
&lt;li&gt;WAL Simulation in Go&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What is Atomicity in Databases?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;For demonstration purposes, we'll assume a PostgreSQL database. However, with only minor changes, the same principles and techniques apply to almost all traditional SQL databases like MySQL, MariaDB, and SQL Server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Atomicity&lt;/strong&gt; means that a group of operations within a transaction are treated as a single, indivisible unit. Either &lt;strong&gt;all&lt;/strong&gt; operations succeed, or &lt;strong&gt;none&lt;/strong&gt; do. There’s no halfway state.&lt;/p&gt;

&lt;p&gt;Think of a transaction like a switch—it either flips entirely or not at all. This prevents data corruption, especially in systems where multiple operations are tightly coupled.&lt;/p&gt;




&lt;h2&gt;
  
  
  Atomicity in Action: A Collaborative Recipe Platform
&lt;/h2&gt;

&lt;p&gt;Let’s skip the classic "bank transfer" story. Here’s a fresh real-world scenario that shows &lt;strong&gt;why atomicity is critical&lt;/strong&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Scenario: Collaborative Recipe Creation Platform&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A platform where users can collaboratively create and edit recipes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Atomic Transaction Example:
&lt;/h4&gt;

&lt;p&gt;When a user adds a new ingredient to a recipe, three things must happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The ingredient is added to the recipe's ingredient list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The recipe’s "last modified" timestamp is updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The contributor’s "contribution count" is incremented.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  The Problem Without Atomicity:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The ingredient is added, but the recipe no longer exists.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The contributor's count updates, but the ingredient is never stored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One part succeeds while the others fail—leading to &lt;strong&gt;data inconsistency&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, without atomicity, there's a real risk of data inconsistency—where some parts of a transaction are saved while others are not. In a simple recipe app, it might just mean a missing ingredient or an incorrect contributor count. But in critical business applications—like banking, e-commerce, or healthcare—even small inconsistencies can lead to serious consequences. It can damage user trust, trigger system errors, and ultimately cause financial or reputational loss. That's why atomicity isn’t just a nice-to-have—it’s essential.&lt;br&gt;
So, how do databases actually guarantee atomicity during operations? Let’s see how we can ensure atomicity using SQL transactions in a practical scenario.&lt;/p&gt;
&lt;h3&gt;
  
  
  Practical SQL Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you'd structure this in SQL to &lt;strong&gt;ensure atomicity&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;-- Start the transaction&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 1: Check if the recipe exists and lock it&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;recipe_id&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;recipes&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;recipe_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 2: Add a new ingredient&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;ingredients&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipe_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;added_by&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Garlic'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 3: Update the recipe's timestamp&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;recipes&lt;/span&gt; 
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;last_modified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;recipe_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 4: Increment user's contribution count&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; 
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;contribution_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contribution_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;-- Commit only if all operations succeed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;strong&gt;any step fails&lt;/strong&gt;, the database rolls everything back to the state before &lt;code&gt;BEGIN&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Databases Ensure Atomicity (Under the Hood)
&lt;/h2&gt;

&lt;p&gt;Now you may wonder, &lt;strong&gt;how does the database make sure this all-or-nothing behavior works&lt;/strong&gt;, especially if the system crashes in between?&lt;/p&gt;

&lt;p&gt;The answer lies in something called a &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Write Ahead Logging Explained
&lt;/h2&gt;

&lt;p&gt;In PostgreSQL, &lt;strong&gt;Write-Ahead Logging (WAL)&lt;/strong&gt; ensures that every transaction is &lt;strong&gt;all or nothing&lt;/strong&gt;—the core of &lt;strong&gt;atomicity&lt;/strong&gt;. Before the database makes any real changes, it first &lt;strong&gt;writes them to a special log file&lt;/strong&gt; (the WAL). Think of it like drafting a message in your notes app before sending it—if your phone crashes, you still have the draft.&lt;/p&gt;

&lt;p&gt;If the system crashes in the middle of a transaction, PostgreSQL uses that log to figure out what was safely finished and what wasn’t. It &lt;strong&gt;only applies the changes that were fully completed&lt;/strong&gt;, and rolls back anything else. This way, the database never ends up in a broken or half-updated state.&lt;/p&gt;

&lt;p&gt;WAL also adds a touch of &lt;strong&gt;durability&lt;/strong&gt;, because even if the power goes out, the log is still there to bring everything back as it was before.&lt;/p&gt;

&lt;h2&gt;
  
  
  WAL Simulation in Go
&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;"bufio"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;WriteAheadLog&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;logFile&lt;/span&gt; &lt;span class="kt"&gt;string&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;NewWriteAheadLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;WriteAheadLog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;WriteAheadLog&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;logFile&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;filename&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;WriteAheadLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LogWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction&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="n"&gt;file&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_APPEND&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_CREATE&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_WRONLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0644&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="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;"Error writing log:"&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="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&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="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="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;"Logged:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transaction&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;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;WriteAheadLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LogRecover&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;file&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logFile&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="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;"Error reading log:"&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="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;"Recovering transactions..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scanner&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewScanner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&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;"Recovered:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&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;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;WriteAheadLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Commit&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logFile&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="m"&gt;0644&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="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;"Error committing log:"&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="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;"Committed transactions."&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;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;wal&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewWriteAheadLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wal_log.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INSERT INTO users VALUES(1, 'Alice')"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UPDATE users SET name = 'Bob' WHERE id = 1"&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;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Simulating system restart...&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;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogRecover&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Atomicity&lt;/strong&gt; ensures that your data operations don't leave the database in a broken or inconsistent state. Whether you’re building a social app, a recipe platform, or a financial system—atomic transactions &lt;strong&gt;preserve trust and data integrity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Modern databases, especially PostgreSQL, use mechanisms like &lt;strong&gt;WAL&lt;/strong&gt; to guarantee atomicity even in the face of unexpected crashes. By understanding these internals, you become better equipped to design reliable, scalable systems.&lt;/p&gt;

&lt;p&gt;In future articles, we’ll dive into the remaining pillars of ACID—&lt;strong&gt;Consistency, Isolation, and Durability&lt;/strong&gt;—each critical in its own right.&lt;/p&gt;

&lt;p&gt;Before I end this post, I want to take a moment to express my deep love and unwavering support for our Palestinian Muslim brothers and sisters 🇵🇸. Their lives, their struggles, and their voices matter. In a world that too often turns a blind eye, we must continue to speak up and stand with the oppressed. May justice rise, may peace prevail, and may the people of Palestine live with dignity, freedom, and hope. You are not forgotten—&lt;strong&gt;your life matters&lt;/strong&gt;.The recent surge in terrorist activities and the brutal actions by Israel are unequivocally condemned.&lt;/p&gt;

</description>
      <category>database</category>
      <category>acid</category>
      <category>databasetransactions</category>
      <category>databaseinternals</category>
    </item>
    <item>
      <title>From Slow Queries to Fast Responses: The Power of Connection Pooling</title>
      <dc:creator>Muhammad Hadeed Tariq</dc:creator>
      <pubDate>Mon, 17 Mar 2025 02:23:34 +0000</pubDate>
      <link>https://dev.to/hadeedtariq/from-slow-queries-to-fast-responses-the-power-of-connection-pooling-3gpk</link>
      <guid>https://dev.to/hadeedtariq/from-slow-queries-to-fast-responses-the-power-of-connection-pooling-3gpk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So, what is &lt;strong&gt;connection pooling&lt;/strong&gt;? If you’re a backend developer working with databases, you've likely heard this term. You might have also come across advice on the internet suggesting that instead of opening and closing a connection to the database every time, you should use &lt;strong&gt;connection pooling&lt;/strong&gt; in your application. But why? What are the benefits?&lt;/p&gt;

&lt;p&gt;Let’s dive deep into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Normal Database Interaction

&lt;ul&gt;
&lt;li&gt;Downsides&lt;/li&gt;
&lt;li&gt;Diagram for Normal Database Interaction&lt;/li&gt;
&lt;li&gt;Code for Normal Database Interaction&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Connection Pooling

&lt;ul&gt;
&lt;li&gt;Benefits of Connection Pooling&lt;/li&gt;
&lt;li&gt;Diagram for Connection Pooling&lt;/li&gt;
&lt;li&gt;Code for Connection Pooling&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Things to Consider When Using Connection Pooling&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Normal Database Interaction
&lt;/h2&gt;

&lt;p&gt;Normally, in an application, database interaction follows this process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A request comes to the server.&lt;/li&gt;
&lt;li&gt;The server establishes a connection to the database.&lt;/li&gt;
&lt;li&gt;The request is processed, and the response is returned.&lt;/li&gt;
&lt;li&gt;The connection is closed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To make a request and get a response, a &lt;strong&gt;protocol&lt;/strong&gt; is required. This is usually &lt;strong&gt;TCP&lt;/strong&gt; (Transmission Control Protocol) or &lt;strong&gt;gRPC&lt;/strong&gt; (gRPC Remote Procedure Calls). Let’s assume &lt;strong&gt;TCP&lt;/strong&gt; is being used. You may already know that TCP has a &lt;strong&gt;cost&lt;/strong&gt; due to the &lt;a href="https://www.codecademy.com/resources/blog/what-is-tcp/" rel="noopener noreferrer"&gt;three-way handshake&lt;/a&gt; process, which adds &lt;strong&gt;latency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With this native approach, every request opens a &lt;strong&gt;new connection&lt;/strong&gt; to the database and then closes it after processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Downsides
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Resource Consumption&lt;/strong&gt;: Each request creates a new TCP connection, leading to excessive resource usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability Issues&lt;/strong&gt;: If site traffic is high, maintaining a separate connection for each user can cause the &lt;strong&gt;database to hit its connection limit&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased Costs&lt;/strong&gt;: Running many connections increases database expenses significantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Diagram for Normal Database Interaction
&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%2Fxv1clq44f9ei2szgzjtn.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%2Fxv1clq44f9ei2szgzjtn.png" alt="Normal Database Interaction Diagram" width="800" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Code for Normal Database Interaction
&lt;/h3&gt;

&lt;p&gt;For demonstration purposes, we’ll use &lt;strong&gt;PostgreSQL&lt;/strong&gt; with &lt;strong&gt;Node.js&lt;/strong&gt; and the &lt;code&gt;pg&lt;/code&gt; driver. However, you can use other drivers for different languages:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Python&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;psycopg2&lt;/strong&gt; → Most widely used PostgreSQL adapter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;asyncpg&lt;/strong&gt; → High-performance async driver for PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLAlchemy&lt;/strong&gt; → ORM that uses &lt;code&gt;psycopg2&lt;/code&gt; by default&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Java&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL JDBC Driver&lt;/strong&gt; → &lt;code&gt;org.postgresql.Driver&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hibernate&lt;/strong&gt; → ORM that works with PostgreSQL via JDBC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spring Data JPA&lt;/strong&gt; → Uses Hibernate under the hood&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. C# (.NET)&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Npgsql&lt;/strong&gt; → Official PostgreSQL driver for .NET&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entity Framework Core&lt;/strong&gt; → Uses &lt;code&gt;Npgsql&lt;/code&gt; for PostgreSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;4. PHP&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PDO_PGSQL&lt;/strong&gt; → PHP Data Object (PDO) driver for PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pg_connect()&lt;/strong&gt; → Native PostgreSQL function in PHP&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;5. Ruby&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;pg gem&lt;/strong&gt; → Default PostgreSQL adapter for Ruby&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ActiveRecord&lt;/strong&gt; → Uses &lt;code&gt;pg&lt;/code&gt; for PostgreSQL in Rails&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;6. Go&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;pgx&lt;/strong&gt; → High-performance PostgreSQL driver&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;database/sql with lib/pq&lt;/strong&gt; → Go's standard DB driver with PostgreSQL support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Install the &lt;code&gt;pg&lt;/code&gt; package&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;pg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Create a database connection file (&lt;code&gt;db.js&lt;/code&gt;)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// PostgreSQL connection configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Connect to the database&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connected to PostgreSQL!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connection error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;3. Query the Database (&lt;code&gt;index.js&lt;/code&gt;)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error executing query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Close the connection&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;4. Run the script&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, &lt;strong&gt;every request establishes a new database connection&lt;/strong&gt;, processes the query, and then immediately closes the connection. While this may seem straightforward, it introduces significant overhead, consuming unnecessary resources and increasing latency. This approach becomes even more problematic as traffic scales, leading to performance bottlenecks.  &lt;/p&gt;

&lt;p&gt;To address these inefficiencies, let’s explore &lt;strong&gt;connection pooling&lt;/strong&gt;—a smarter way to manage database connections efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connection Pooling
&lt;/h2&gt;

&lt;p&gt;Now, let’s explore &lt;strong&gt;connection pooling&lt;/strong&gt; and how it optimizes database interactions.  &lt;/p&gt;

&lt;p&gt;Instead of establishing a new connection for every request, &lt;strong&gt;a pool of persistent TCP connections is maintained within the application’s memory&lt;/strong&gt;, allowing connections to be &lt;strong&gt;reused efficiently&lt;/strong&gt;. This eliminates the overhead of repeatedly opening and closing connections, reducing &lt;strong&gt;latency&lt;/strong&gt; and &lt;strong&gt;resource consumption&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;For more advanced scenarios, &lt;strong&gt;isolated connection pool environments&lt;/strong&gt; (such as managed database connection pools) are available, but for simplicity, we'll focus on the in-memory approach.  &lt;/p&gt;

&lt;p&gt;Here’s how it works when a request is made:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The application retrieves an &lt;strong&gt;available connection&lt;/strong&gt; from the pool.
&lt;/li&gt;
&lt;li&gt;The query is executed.
&lt;/li&gt;
&lt;li&gt;The connection is returned to the pool, making it &lt;strong&gt;ready for reuse&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Benefits of Connection Pooling
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduces Latency&lt;/strong&gt;: No need to establish a fresh TCP connection each time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saves Authentication Time&lt;/strong&gt;: The database does not need to authenticate every request separately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: The number of connections in the pool can be &lt;strong&gt;dynamically increased or decreased&lt;/strong&gt; based on load.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Diagram for Connection Pooling
&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%2Fprn8hetbaeramtdkad2k.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%2Fprn8hetbaeramtdkad2k.png" alt="Connection Pooling Diagram" width="800" height="902"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Code for Connection Pooling
&lt;/h3&gt;

&lt;p&gt;We will modify the previous code to use &lt;strong&gt;connection pooling&lt;/strong&gt; instead of individual connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Create a connection pool (&lt;code&gt;db.js&lt;/code&gt;)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// PostgreSQL connection pool configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                        &lt;span class="c1"&gt;// Maximum number of clients in the pool&lt;/span&gt;
  &lt;span class="na"&gt;idleTimeoutMillis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// Close idle clients after 30 seconds&lt;/span&gt;
  &lt;span class="na"&gt;connectionTimeoutMillis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// Return error if connection takes longer than 2 sec&lt;/span&gt;
  &lt;span class="na"&gt;allowExitOnIdle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;// Prevents process exit if idle clients exist&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Event listeners for debugging&lt;/span&gt;
&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connected to PostgreSQL!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;acquire&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client acquired from the pool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;release&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client released back to the pool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unexpected error on idle client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;em&gt;2. Query the Database (&lt;code&gt;index.js&lt;/code&gt;)&lt;/em&gt;*
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Get a client from the pool&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connected to database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Users:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error executing query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Release the client back to the pool&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Run the script&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Things to Consider When Using Connection Pooling
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always return connections to the pool&lt;/strong&gt; after execution. Otherwise, you might run out of connections, leading to application downtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid too few connections&lt;/strong&gt; in the pool, as this can introduce latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid too many connections&lt;/strong&gt;, as excessive connections may consume unnecessary resources and slow down the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set an idle timeout&lt;/strong&gt; to release connections that remain &lt;strong&gt;unused&lt;/strong&gt; for too long.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set a query timeout&lt;/strong&gt; to ensure connections are not held indefinitely due to slow queries.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Efficient database interaction is crucial for building scalable applications. As we've seen, directly opening and closing connections for every request is &lt;strong&gt;inefficient, resource-intensive, and limits scalability&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
By implementing &lt;strong&gt;connection pooling&lt;/strong&gt;, we significantly &lt;strong&gt;reduce latency, optimize resource usage, and improve overall performance&lt;/strong&gt;. Instead of repeatedly establishing new connections, a pool of persistent connections is maintained, allowing queries to be executed &lt;strong&gt;faster and more efficiently&lt;/strong&gt;. &lt;/p&gt;

</description>
      <category>backend</category>
      <category>database</category>
      <category>performance</category>
      <category>sql</category>
    </item>
  </channel>
</rss>
