<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Siddharth Sabron</title>
    <subtitle>Siddharth is a software engineer, primarily interested in algorithms, design principles, databases, storage engines, large-scale systems and distributed systems</subtitle>
    <link rel="self" type="application/atom+xml" href="https://siddharthsabron.in/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://siddharthsabron.in"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-28T00:00:00+00:00</updated>
    <id>https://siddharthsabron.in/atom.xml</id>
    <entry xml:lang="en">
        <title>Clik - A Self-Deployable URL Shortener</title>
        <published>2026-03-28T00:00:00+00:00</published>
        <updated>2026-03-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/projects/click-url-shortner/"/>
        <id>https://siddharthsabron.in/projects/click-url-shortner/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/projects/click-url-shortner/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1764315576415-ef01b802e8ff?q=80&amp;amp;w=1074&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;Random click by siddharth sabron&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Random Click&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;_xc-5gQ6sro&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Building a URL shortener is a classic system design interview question. I built one to find out how many of those whiteboard answers actually survive contact with real code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-stack&quot;&gt;The Stack&lt;&#x2F;h2&gt;
&lt;p&gt;No abstractions over abstractions. Here is what it runs on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java 21&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spring Boot 3.4.2&lt;&#x2F;strong&gt; handles HTTP so I can focus on what matters underneath&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;MySQL 8.0&lt;&#x2F;strong&gt; (the database choice is load-bearing, explained below)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spring Data JPA + Hibernate&lt;&#x2F;strong&gt; with Envers for write auditing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spring Security&lt;&#x2F;strong&gt; with JWT-based auth for URL ownership&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Maven&lt;&#x2F;strong&gt; for builds, nothing clever&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Two tables. That is the entire data model.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;short_urls  &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;  internal_id (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;BIGINT&lt;&#x2F;span&gt;&lt;span&gt; PK), long_url, short_code, &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;user_id&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;FK nullable), click_count, created_at&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;users       &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;  id (PK), email, password_hash, first_name, last_name, ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The redirect path is a single indexed lookup on &lt;code&gt;short_code&lt;&#x2F;code&gt;. That query runs on every click, so that is the one that matters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-id-problem&quot;&gt;The ID Problem&lt;&#x2F;h2&gt;
&lt;p&gt;I did not use &lt;code&gt;AUTO_INCREMENT&lt;&#x2F;code&gt;. I did not use &lt;code&gt;UUID&lt;&#x2F;code&gt;. Here is why neither worked for me.&lt;&#x2F;p&gt;
&lt;p&gt;A UUID is a 128-bit number, not a string. The mistake most people make is storing it as &lt;code&gt;VARCHAR(36)&lt;&#x2F;code&gt; (the human-readable hyphenated form) instead of &lt;code&gt;BINARY(16)&lt;&#x2F;code&gt;. If you store a UUID as &lt;code&gt;BINARY(16)&lt;&#x2F;code&gt;, comparisons are fast and the index stays compact. But the real problem is still randomness. UUID v4 is randomly generated, so every insert lands at a random position in the B-tree, not the end. That causes node splits, which scatter data across disk pages. At millions of rows a randomly-keyed table fragments badly, and reads that miss the buffer pool pay disk seek latency.&lt;&#x2F;p&gt;
&lt;p&gt;UUIDv7 is worth knowing about. It is time-ordered with a 48-bit millisecond timestamp prefix, standardized in RFC 9562, and eliminates the fragmentation problem entirely. If I were starting fresh and wanted a 128-bit ID space without building my own generator, UUIDv7 is the honest answer. MySQL and Postgres support it natively as of recent versions.&lt;&#x2F;p&gt;
&lt;p&gt;I still went with Snowflake-style IDs because the shard ID is baked into every key. You can look at any &lt;code&gt;internal_id&lt;&#x2F;code&gt; and immediately know which machine generated it, which is useful for debugging and operational routing. UUIDv7 does not give you that without a separate column.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;AUTO_INCREMENT&lt;&#x2F;code&gt; is sequential and avoids fragmentation. But it couples your ID space to a single database node. The moment you shard, you have a coordination problem.&lt;&#x2F;p&gt;
&lt;p&gt;So I use a Snowflake-inspired 64-bit integer that is sequential, distributed, and carries operational metadata inside the number itself:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  Timestamp (41 bits)  |  ShardID (10 bits)  |  Seq (12 bits) |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|          63           |         22          |       12       |  &amp;lt;- bit positions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;41 bits of milliseconds&lt;&#x2F;strong&gt; since a custom epoch (2023-01-01 00:00:00 UTC). About 69.7 years of headroom before the timestamp field overflows.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;10 bits of shard ID.&lt;&#x2F;strong&gt; 1024 unique shard identifiers embedded in every key. Reading bits 12 through 21 tells you which machine generated the ID.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;12 bits of sequence.&lt;&#x2F;strong&gt; 4096 unique IDs per millisecond per shard before rollover.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-actual-implementation&quot;&gt;The actual implementation:&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; synchronized&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; generateInternalId&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; shardId&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    long&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; System&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;currentTimeMillis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; epoch&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sequenceNumber&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sequence&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getAndIncrement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0xFFF&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;timestamp &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;shardId &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt; sequenceNumber&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Two things worth understanding here.&lt;&#x2F;p&gt;
&lt;p&gt;First, &lt;code&gt;timestamp &amp;lt;&amp;lt; 22&lt;&#x2F;code&gt;. Shifting left by 22 puts the timestamp in the most significant bits of the 64-bit integer. Since timestamp dominates the value numerically, IDs generated later are always larger numbers than IDs generated earlier regardless of shard or sequence. A quick example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;timestamp = 100  -&amp;gt;  100 &amp;lt;&amp;lt; 22  =  419,430,400&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;timestamp = 101  -&amp;gt;  101 &amp;lt;&amp;lt; 22  =  423,624,704&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The second ID is always bigger. That is why every new insert goes to the rightmost leaf of the B-tree and index fragmentation is essentially zero.&lt;&#x2F;p&gt;
&lt;p&gt;Second, &lt;code&gt;&amp;amp; 0xFFF&lt;&#x2F;code&gt;. The sequence counter keeps incrementing forever, but we only have 12 bits reserved for it. &lt;code&gt;&amp;amp; 0xFFF&lt;&#x2F;code&gt; is just a cheap way to wrap it. &lt;code&gt;0xFFF&lt;&#x2F;code&gt; in binary is twelve consecutive 1s. ANDing any number with it throws away everything above bit 11:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4095 &amp;amp; 0xFFF = 4095   &#x2F;&#x2F; still in range&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4096 &amp;amp; 0xFFF = 0      &#x2F;&#x2F; wraps back cleanly&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No if-statement, no modulo, just a single bitwise AND.&lt;&#x2F;p&gt;
&lt;p&gt;The method is &lt;code&gt;synchronized&lt;&#x2F;code&gt;, so one thread enters at a time on this service instance. The &lt;code&gt;AtomicLong&lt;&#x2F;code&gt; on the sequence counter is belt-and-suspenders given the lock already serializes access.&lt;&#x2F;p&gt;
&lt;p&gt;Once the 64-bit integer is generated it gets Base62-encoded into the short code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; final&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ALPHABET&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; encode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;long&lt;&#x2F;span&gt;&lt;span&gt; id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    StringBuilder&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sb&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; StringBuilder&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        sb&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ALPHABET&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;charAt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 62&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&#x2F;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 62&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sb&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reverse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;toString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A typical Snowflake ID is on the order of 10¹⁸. That encodes to 7 or 8 Base62 characters. Short enough to be a URL slug, and unique enough to never collide across shards.&lt;&#x2F;p&gt;
&lt;p&gt;The end result is a query like this resolving in O(log n):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; long_url &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; short_urls &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; internal_id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 286435872092454913&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because &lt;code&gt;internal_id&lt;&#x2F;code&gt; is a sequential BIGINT primary key, MySQL’s InnoDB clustered index keeps rows physically ordered on disk. The B-tree traversal is fast, page cache hit rates are high, and there is no fragmentation from random insertions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-hard-parts&quot;&gt;The Hard Parts&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Sequence overflow, known and unhandled.&lt;&#x2F;strong&gt; The current code does not handle generating more than 4,096 IDs within the same millisecond on the same shard. The &lt;code&gt;&amp;amp; 0xFFF&lt;&#x2F;code&gt; mask wraps the counter silently back to zero, which means two calls can produce the same ID if the rate exceeds 4M&#x2F;s on one shard. The fix is straightforward:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;sequenceNumber &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;System&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;currentTimeMillis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; lastTimestamp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; spin until the clock moves forward&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have documented this in the source. At current volume it does not trigger. I am not pretending it is solved.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Clock drift, also unhandled.&lt;&#x2F;strong&gt; If the system clock moves backward due to an NTP correction or VM live migration, &lt;code&gt;System.currentTimeMillis() - epoch&lt;&#x2F;code&gt; shrinks. The timestamp bits in the new ID become smaller than in the previous one, monotonicity breaks, and you can get duplicate IDs. The standard fix is to track &lt;code&gt;lastTimestamp&lt;&#x2F;code&gt; and throw or wait if the clock regresses. Not implemented. Documented.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Duplicate long URLs.&lt;&#x2F;strong&gt; Two users submitting the same long URL should get the same short code. Before generating a new ID, the service checks for an existing &lt;code&gt;long_url&lt;&#x2F;code&gt; record. The lookup is on an indexed column so it is cheap, but it is a read-before-write that adds a round trip on every URL creation. A unique constraint on &lt;code&gt;long_url&lt;&#x2F;code&gt; would make this airtight.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Click tracking on the redirect path.&lt;&#x2F;strong&gt; Every redirect needs to increment &lt;code&gt;click_count&lt;&#x2F;code&gt;. Doing that synchronously stalls the redirect on an UPDATE with a row-level lock. Instead, click increments go into a thread pool and get processed asynchronously. The 302 returns immediately and the counter catches up in the background. The tradeoff is honest: if the JVM dies between the redirect and the write, that click is gone. A click counter is an approximation, not an accounting ledger. I accepted that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Index strategy on redirects.&lt;&#x2F;strong&gt; &lt;code&gt;short_code&lt;&#x2F;code&gt; has a unique secondary index and &lt;code&gt;internal_id&lt;&#x2F;code&gt; is the clustered primary key. A redirect traverses the &lt;code&gt;short_code&lt;&#x2F;code&gt; index to locate the row, then does a bookmark lookup into the clustered index to fetch &lt;code&gt;long_url&lt;&#x2F;code&gt;. Two B-tree traversals is the floor for this query shape without a covering index or an in-memory cache in front. If this were serving serious traffic, a Redis layer on &lt;code&gt;short_code -&amp;gt; long_url&lt;&#x2F;code&gt; would collapse the redirect to a single memory read. Not added yet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-it&quot;&gt;Running It&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;siddharth1729&#x2F;clik.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; clik&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;.&#x2F;mvnw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; spring-boot:run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Update &lt;code&gt;src&#x2F;main&#x2F;resources&#x2F;profiles&#x2F;dev.application.properties&lt;&#x2F;code&gt; with your MySQL credentials. The schema bootstraps itself via Hibernate DDL on first boot.&lt;&#x2F;p&gt;
&lt;p&gt;API surface:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;POST &#x2F;api&#x2F;shorten                         shorten a URL (anonymous)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;POST &#x2F;api&#x2F;shorten  + Authorization Bearer shorten a URL (authenticated)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GET  &#x2F;{shortCode}                         redirect to long URL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;POST &#x2F;api&#x2F;users&#x2F;register                  create an account&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;why-i-built-it&quot;&gt;Why I Built It&lt;&#x2F;h2&gt;
&lt;p&gt;Every explanation of this system at the design level gestures at Base62 encoding and sharding and then moves on. I wanted to know what actually breaks when you implement those things.&lt;&#x2F;p&gt;
&lt;p&gt;The ID generator is the crux. Get the bit layout wrong and your index degrades. Miss the sequence overflow case and you silently produce duplicate keys under load. Handle click tracking synchronously and your redirect latency spikes under write contention.&lt;&#x2F;p&gt;
&lt;p&gt;None of that shows up on a whiteboard. All of it matters in the code.&lt;&#x2F;p&gt;
&lt;p&gt;Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;siddharth1729&#x2F;clik&quot;&gt;github.com&#x2F;siddharth1729&#x2F;clik&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Connect with me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;LinkedIn&lt;&#x2F;a&gt;
Follow on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Legion: An Ultra-Fast, Multi-Threaded Logging Library</title>
        <published>2025-06-14T00:00:00+00:00</published>
        <updated>2025-06-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/projects/logger-library/"/>
        <id>https://siddharthsabron.in/projects/logger-library/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/projects/logger-library/">&lt;p&gt;&lt;em&gt;By Siddharth Sabron, June 14, 2025&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1749908511482-d9563e1217e2?q=80&amp;amp;w=2940&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;View of McLeodganj photographed by Siddharth Sabron&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Mcleodganj&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;4J0SZhPIqFM&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;This article presents a comprehensive design document for a high-performance Java logging library, based on deep research and proven architectural patterns.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The development of an &lt;code&gt;ultra-fast&lt;&#x2F;code&gt;, &lt;code&gt;high-throughput&lt;&#x2F;code&gt;, &lt;code&gt;low-dependency&lt;&#x2F;code&gt; logging library for Java applications, particularly for Spring environments, necessitates a rigorous architectural approach. The core value proposition of such a library lies in its ability to minimize performance overhead on application threads while ensuring comprehensive log capture, request tracing, and visualization-friendly JSON output. This objective is achieved through fundamental principles such as asynchronous processing, meticulous zero-allocation strategies, and intelligent concurrency management. The design emphasizes leveraging core Java constructs where possible, while pragmatically acknowledging the irreplaceable role of battle-tested components like the LMAX Disruptor for achieving truly “ultra-fast” performance characteristics. The success of this endeavor hinges on a deep understanding of JVM optimization, concurrent programming paradigms, and rigorous benchmarking.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-core-design-foundation-high-level-architecture&quot;&gt;1. Core Design &amp;amp; Foundation: High Level Architecture&lt;&#x2F;h3&gt;
&lt;p&gt;The pursuit of an “ultra-fast” logging library begins with foundational architectural principles that dictate how log events are handled from their inception to their persistence. These principles are designed to ensure minimal impact on the application’s critical path and maximize logging throughput.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;asynchronous-processing-decoupling-for-minimal-caller-impact&quot;&gt;Asynchronous Processing: Decoupling for Minimal Caller Impact&lt;&#x2F;h4&gt;
&lt;p&gt;A cornerstone for achieving “ultra-fast” performance is the immediate decoupling of logging events from the caller thread. This means that the application thread, upon initiating a log request, should relinquish control as quickly as possible, allowing the core business logic to proceed without delay. This asynchronous approach is widely recognized as a technique to significantly improve application logging performance by offloading all I&#x2F;O operations to separate threads. For instance, Log4j 2’s asynchronous loggers are specifically designed to return control to the application with minimal delay.&lt;&#x2F;p&gt;
&lt;p&gt;The underlying reason for this design choice is rooted in the nature of I&#x2F;O operations. Synchronous I&#x2F;O, whether to disk or network, inherently blocks the executing thread until the operation completes. If logging were synchronous, the application’s responsiveness and overall throughput would be directly constrained by the speed of log persistence. By immediately handing off the log event to a dedicated queue and returning control, the application thread is shielded from these I&#x2F;O latencies, thereby maintaining high responsiveness and throughput for its primary functions. This fundamental decoupling is a direct driver for achieving minimal overhead on the main application threads.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;batching-amortizing-i-o-costs-for-high-throughput&quot;&gt;Batching: Amortizing I&#x2F;O Costs for High Throughput&lt;&#x2F;h4&gt;
&lt;p&gt;To further optimize I&#x2F;O operations, log events should be processed and written in batches. The cost associated with initiating an I&#x2F;O operation (e.g., a system call for a file write or a network packet transmission) often has a fixed overhead, regardless of the amount of data being transferred (up to a certain point). By accumulating multiple log events into a single, larger batch before writing, this fixed overhead is amortized over numerous log entries. This significantly reduces the number of I&#x2F;O calls, leading to a substantial increase in overall logging throughput.&lt;&#x2F;p&gt;
&lt;p&gt;For example, asynchronous appenders in Log4j2 are designed to flush to disk at the end of a batch, which is more efficient than immediate flushing for each log event. While batching enhances throughput by reducing the frequency of costly I&#x2F;O operations, it introduces a slight increase in latency for individual log events. Each event must wait in the buffer until a batch is full or a timeout occurs. This represents a classic trade-off between maximizing throughput and minimizing individual log event latency, a balance that requires careful tuning.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;zero-allocation-garbage-free-where-possible-minimizing-gc-pressure-in-the-critical-path&quot;&gt;Zero-Allocation (Garbage-Free where possible): Minimizing GC Pressure in the Critical Path&lt;&#x2F;h4&gt;
&lt;p&gt;A critical aspect of “ultra-fast” performance and consistent low latency is the minimization of new object allocations during the logging critical path. Excessive object creation leads to increased pressure on the Java Garbage Collector (GC), resulting in more frequent and potentially longer GC pauses, which can manifest as latency spikes. Libraries like ZeroLog, though a .NET library, exemplify this principle by aiming for a “complete zero-allocation manner” after initialization to prevent GC triggers. Log4j2 also implements a “garbage-free mode” by reusing objects and buffers to reduce GC pressure.&lt;&#x2F;p&gt;
&lt;p&gt;It is important to understand the practical implications of “zero-allocation.” While the aspiration is to eliminate all new object allocations after initialization, achieving this absolutely in a feature-rich logging library can be exceptionally challenging. Log4j2’s “garbage-free mode” demonstrates this nuance, noting that certain scenarios, such as logging messages exceeding a specific character limit, logging numerous parameters, or using certain lambda expressions, may still result in temporary object allocations. This suggests that “garbage-free” in a real-world context often translates to “minimal garbage” or “garbage-free under ideal, frequently occurring conditions.” The design should therefore prioritize object reuse in the most performance-critical paths, such as LogEvent creation and population, while acknowledging and documenting scenarios where some allocation might be unavoidable, or where pooling mechanisms can mitigate their impact.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;thread-isolation-dedicated-logging-workers-for-application-stability&quot;&gt;Thread Isolation: Dedicated Logging Workers for Application Stability&lt;&#x2F;h4&gt;
&lt;p&gt;To prevent logging operations from adversely affecting the main application’s responsiveness or stability, the threads responsible for processing and writing logs must be isolated from the application’s core threads. This separation ensures that even if logging operations encounter bottlenecks (e.g., slow disk writes, network congestion), the main application threads remain unblocked and continue executing business logic without interruption.&lt;&#x2F;p&gt;
&lt;p&gt;Asynchronous logging inherently promotes this thread isolation. The &lt;code&gt;ExecutorService&lt;&#x2F;code&gt; is a fundamental Java utility for managing thread execution and task scheduling, facilitating the creation of dedicated thread pools for logging activities. This approach to thread pool isolation prevents resource exhaustion within the logging subsystem from cascading and affecting other critical services within the application. Similarly, &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; variables contribute to thread isolation by providing each thread with its own independent storage, preventing data interference between concurrent operations. By containing logging-related performance fluctuations or failures within their own isolated thread pool, the overall system gains improved stability and resilience.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-2-core-components-overview&quot;&gt;1.2. Core Components Overview&lt;&#x2F;h3&gt;
&lt;p&gt;The architecture of this ultra-fast logging library is composed of several interconnected components, each designed for optimal performance and specific responsibilities:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LogEvent (Data Carrier):&lt;&#x2F;strong&gt; This Plain Old Java Object (POJO) encapsulates all information pertinent to a single log entry. Its fields include &lt;code&gt;timestampMillis&lt;&#x2F;code&gt;, &lt;code&gt;LogLevel&lt;&#x2F;code&gt;, &lt;code&gt;message&lt;&#x2F;code&gt;, &lt;code&gt;mdcContext&lt;&#x2F;code&gt; (for Mapped Diagnostic Context data), &lt;code&gt;customData&lt;&#x2F;code&gt; (for structured log data), &lt;code&gt;throwable&lt;&#x2F;code&gt; (for exception details), &lt;code&gt;threadName&lt;&#x2F;code&gt;, &lt;code&gt;loggerName&lt;&#x2F;code&gt;, &lt;code&gt;serviceName&lt;&#x2F;code&gt;, and &lt;code&gt;hostName&lt;&#x2F;code&gt;. A critical design consideration for LogEvent is its reusability through pooling, which necessitates a &lt;code&gt;reset()&lt;&#x2F;code&gt; method to clear its state for subsequent use, thereby contributing to garbage-free operation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;LogBuffer (Concurrent Queue):&lt;&#x2F;strong&gt; This is the high-performance conduit between producer (application) threads and consumer (logging worker) threads. It is designed as a highly concurrent, non-blocking queue for &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instances. The LMAX Disruptor pattern is the primary candidate for achieving extreme throughput, given its proven capabilities in high-performance inter-thread communication. Alternatively, a carefully tuned &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt; could serve as a high-performance option if the Disruptor’s external dependency is deemed too significant.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;LogProcessor (Worker Thread Pool):&lt;&#x2F;strong&gt; This component comprises a pool of dedicated threads. Their primary responsibilities include continuously polling or consuming &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instances from the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt;, formatting these events into the specified JSON schema, and writing the formatted events to designated sinks (e.g., file, console, network). The &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; also manages batching of writes to optimize I&#x2F;O operations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Logger Facade:&lt;&#x2F;strong&gt; This is the public-facing API that application code interacts with (e.g., &lt;code&gt;MyLogger.info()&lt;&#x2F;code&gt;, &lt;code&gt;MyLogger.error()&lt;&#x2F;code&gt;). It is designed to be exceptionally lightweight, ensuring minimal overhead on the caller thread. Its primary function is to quickly capture log parameters, populate a &lt;code&gt;LogEvent&lt;&#x2F;code&gt;, and offer it to the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Custom MDC (Mapped Diagnostic Context):&lt;&#x2F;strong&gt; A custom, high-performance implementation of a thread-local mechanism. It is used to store request-specific contextual data, such as a unique &lt;code&gt;requestId&lt;&#x2F;code&gt;, which is essential for comprehensive request tracing across distributed systems.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Request Correlation Filter&#x2F;Interceptor:&lt;&#x2F;strong&gt; This is a Spring-specific component responsible for generating and managing the &lt;code&gt;requestId&lt;&#x2F;code&gt; within the custom MDC. It ensures that a unique identifier is associated with each incoming request and propagated throughout its lifecycle, enabling end-to-end traceability of log events.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1-3-dependency-strategy-the-less-libraries-imperative&quot;&gt;1.3. Dependency Strategy: The “Less Libraries” Imperative&lt;&#x2F;h3&gt;
&lt;p&gt;A core tenet of this project is to minimize external dependencies, thereby reducing the library’s footprint, potential for dependency conflicts, and overall complexity.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Core Java:&lt;&#x2F;strong&gt; The design heavily relies on fundamental Java APIs, particularly &lt;code&gt;java.util.concurrent&lt;&#x2F;code&gt; for robust concurrency primitives. This approach leverages the highly optimized and battle-tested components within the Java Development Kit (JDK).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;JSON Serialization:&lt;&#x2F;strong&gt; For structured logging, JSON serialization is often unavoidable. While a strict “zero external dependencies” approach might suggest hand-rolling JSON serialization, this introduces significant complexity and risk in handling edge cases, escaping, and performance. Therefore, a fast, lightweight JSON library like Jackson (specifically its core modules) or Gson is considered. Jackson is generally preferred for its superior performance in high-throughput and multi-threaded scenarios. Limiting to “core modules only” helps maintain the low-dependency objective.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;LMAX Disruptor (Conditional):&lt;&#x2F;strong&gt; The LMAX Disruptor library is acknowledged as a near necessity if the “ultra-fast” claim requires performance that significantly surpasses traditional queue-based asynchronous logging, akin to Log4j2’s asynchronous capabilities. Building a true Disruptor from scratch is a non-trivial undertaking. However, if careful tuning of a &lt;code&gt;java.util.concurrent.ArrayBlockingQueue&lt;&#x2F;code&gt; proves “fast enough” for the target application’s requirements, prioritizing this built-in Java component would align more closely with the “less libraries” objective.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;No other logging frameworks:&lt;&#x2F;strong&gt; This library is explicitly designed to &lt;em&gt;be&lt;&#x2F;em&gt; the logging framework, precluding the inclusion of Log4j2, Logback, SLF4J, or any other existing logging solutions as dependencies.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;2-low-level-design-implementation-details-engineering-for-speed&quot;&gt;2. Low-Level Design &amp;amp; Implementation Details: Engineering for Speed&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;2-1-logevent-class-object-pooling-and-reset-for-garbage-free-operation&quot;&gt;2.1. LogEvent Class: Object Pooling and reset() for Garbage-Free Operation&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;LogEvent&lt;&#x2F;code&gt; class serves as the data carrier for each log entry. Its design is critical for achieving garbage-free logging.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fields:&lt;&#x2F;strong&gt; The &lt;code&gt;LogEvent&lt;&#x2F;code&gt; should encapsulate comprehensive data: &lt;code&gt;long timestampMillis&lt;&#x2F;code&gt;, &lt;code&gt;LogLevel level&lt;&#x2F;code&gt;, &lt;code&gt;String message&lt;&#x2F;code&gt;, &lt;code&gt;Map&amp;lt;String, String&amp;gt; mdcContext&lt;&#x2F;code&gt;, &lt;code&gt;Map&amp;lt;String, Object&amp;gt; customData&lt;&#x2F;code&gt;, &lt;code&gt;Throwable throwable&lt;&#x2F;code&gt;, &lt;code&gt;String threadName&lt;&#x2F;code&gt;, &lt;code&gt;String loggerName&lt;&#x2F;code&gt;, &lt;code&gt;String serviceName&lt;&#x2F;code&gt;, and &lt;code&gt;String hostName&lt;&#x2F;code&gt;. These fields provide the necessary context for rich, visualization-friendly JSON output.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Pooling Mechanism:&lt;&#x2F;strong&gt; To minimize new object allocations and reduce GC pressure, a pooling mechanism for &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instances is essential. A &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; pool of &lt;code&gt;LogEvent&lt;&#x2F;code&gt; objects is a viable approach. When a log method is invoked, an &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instance is retrieved from this thread-local pool, populated with the current log data, and then offered to the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt;. Once the &lt;code&gt;LogEvent&lt;&#x2F;code&gt; has been processed by the &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; (i.e., formatted and written to a sink), it should be returned to the pool for reuse. This recycling process is fundamental to the garbage-free strategy. A crucial aspect of object pooling is the &lt;code&gt;reset()&lt;&#x2F;code&gt; method. Before a &lt;code&gt;LogEvent&lt;&#x2F;code&gt; is reused from the pool, its previous state must be completely cleared to prevent data contamination from prior log entries. This explicit state management is a trade-off: while it reduces GC overhead, it introduces the complexity of manual memory-like management. The benefits of reduced GC pressure, especially for short-lived, frequently created objects, generally outweigh these complexities in performance-critical applications. However, the implementation must be meticulous to avoid pitfalls such as reference leaks (where objects are not returned to the pool) or premature recycling (where objects are returned too early while still referenced), which can lead to hard-to-debug memory issues.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;2-2-custom-mdc-implementation-mymdc-efficient-threadlocal-management-and-map-reuse&quot;&gt;2.2. Custom MDC Implementation (MyMDC): Efficient ThreadLocal Management and Map Reuse&lt;&#x2F;h4&gt;
&lt;p&gt;The Mapped Diagnostic Context (MDC) provides a mechanism to inject contextual information into log entries, such as a &lt;code&gt;requestId&lt;&#x2F;code&gt; for tracing. The custom &lt;code&gt;MyMDC&lt;&#x2F;code&gt; implementation will leverage &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; for this purpose.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mechanism:&lt;&#x2F;strong&gt; &lt;code&gt;MyMDC&lt;&#x2F;code&gt; will internally use a &lt;code&gt;ThreadLocal&amp;lt;Map&amp;lt;String, String&amp;gt;&amp;gt;&lt;&#x2F;code&gt; to store key-value pairs of contextual data. Each thread will have its own isolated &lt;code&gt;Map&lt;&#x2F;code&gt; instance, ensuring thread safety without explicit synchronization.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Methods:&lt;&#x2F;strong&gt; Essential methods for &lt;code&gt;MyMDC&lt;&#x2F;code&gt; include &lt;code&gt;put(key, value)&lt;&#x2F;code&gt;, &lt;code&gt;get(key)&lt;&#x2F;code&gt;, &lt;code&gt;remove(key)&lt;&#x2F;code&gt;, &lt;code&gt;clear()&lt;&#x2F;code&gt;, and &lt;code&gt;getCopyOfContextMap()&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Optimization:&lt;&#x2F;strong&gt; A primary focus for &lt;code&gt;MyMDC&lt;&#x2F;code&gt; is minimizing Map re-creations. Instead of creating a new Map for each &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; access or for each &lt;code&gt;LogEvent&lt;&#x2F;code&gt;, the design should aim to reuse the &lt;code&gt;Map&lt;&#x2F;code&gt; instance associated with the &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt;. This can involve clearing and repopulating the existing map. When capturing the MDC context for a &lt;code&gt;LogEvent&lt;&#x2F;code&gt;, a choice must be made: either provide a read-only “view” of the &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; map or create a defensive copy. Providing a view would eliminate the allocation of a new &lt;code&gt;Map&lt;&#x2F;code&gt; object, directly contributing to garbage-free operation. However, this approach introduces a risk: if the &lt;code&gt;LogEvent&lt;&#x2F;code&gt; is processed asynchronously by a different thread, and the original &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; map is modified by the application thread &lt;em&gt;before&lt;&#x2F;em&gt; the &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; consumes the event, the log data could become inconsistent. For scenarios demanding absolute immutability of the log event’s context, a defensive copy is safer, albeit at the cost of object allocation. For internal processing where the &lt;code&gt;LogEvent&lt;&#x2F;code&gt; is consumed very quickly and its lifecycle is tightly controlled, a view might be considered for extreme performance, but with rigorous validation. Proper cleanup of &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; variables is paramount, especially in environments utilizing thread pools (common in Spring applications). Failure to call &lt;code&gt;MyMDC.remove()&lt;&#x2F;code&gt; or &lt;code&gt;MyMDC.clear()&lt;&#x2F;code&gt; in a &lt;code&gt;finally&lt;&#x2F;code&gt; block after a request completes can lead to memory leaks and, critically, data pollution where stale &lt;code&gt;requestIds&lt;&#x2F;code&gt; or other context from a previous request are inadvertently carried over to a new request processed by the same reused thread.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;2-3-logbuffer-deep-dive-achieving-extreme-throughput&quot;&gt;2.3. LogBuffer Deep Dive: Achieving Extreme Throughput&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;LogBuffer&lt;&#x2F;code&gt; is the central component for inter-thread communication, directly influencing the “ultra-fast” performance claim.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Option A (Extreme - LMAX Disruptor)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For achieving the highest possible throughput and lowest latency, especially in high-volume logging scenarios, integrating the LMAX Disruptor library is often considered a necessity. The Disruptor is not merely a queue; it is a concurrency pattern designed for “mechanical sympathy” with modern hardware, minimizing cache contention and false sharing.&lt;&#x2F;p&gt;
&lt;p&gt;Its core components include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ring Buffer:&lt;&#x2F;strong&gt; A pre-allocated, fixed-size circular array that stores &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instances, avoiding runtime memory allocations and contributing to garbage-free operation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sequencer:&lt;&#x2F;strong&gt; Manages the allocation of slots in the Ring Buffer and ensures producers do not overrun consumers. It comes in single-producer and multi-producer implementations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sequence:&lt;&#x2F;strong&gt; A counter used by producers and consumers to track their progress, optimized to prevent false sharing.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sequence Barrier:&lt;&#x2F;strong&gt; Coordinates dependencies between consumers and determines event availability.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Wait Strategy:&lt;&#x2F;strong&gt; Defines how consumers wait for new events, offering trade-offs between CPU utilization and latency (e.g., &lt;code&gt;BusySpinWaitStrategy&lt;&#x2F;code&gt; for lowest latency but high CPU, &lt;code&gt;BlockingWaitStrategy&lt;&#x2F;code&gt; for lower CPU but higher latency).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To integrate, a &lt;code&gt;LogEvent&lt;&#x2F;code&gt; factory would be defined for the Disruptor to pre-allocate &lt;code&gt;LogEvent&lt;&#x2F;code&gt; objects. &lt;code&gt;EventTranslator&lt;&#x2F;code&gt; instances would be used by producer threads to publish &lt;code&gt;LogEvent&lt;&#x2F;code&gt; data to the Ring Buffer, and &lt;code&gt;EventHandler&lt;&#x2F;code&gt; implementations would be used by &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; threads to consume and process these events. Log4j2’s asynchronous loggers leverage the Disruptor, demonstrating its capability to achieve significantly higher throughput and lower latency compared to &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt;-based solutions.&lt;&#x2F;p&gt;
&lt;p&gt;However, the Disruptor’s performance is highly context-dependent. While it excels in single-producer, single-consumer scenarios, its advantages in multi-producer environments, especially without explicit bulk operations, can be less pronounced and even worse than a well-optimized &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt;. The Disruptor also requires a substantial upfront memory allocation for its ring buffer (e.g., 80-140MB for Log4j2), which is a trade-off for its garbage-free design. This memory footprint must be considered for microservices or memory-constrained environments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Option B (High Performance - Custom &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt;)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As an alternative to the Disruptor, a &lt;code&gt;java.util.concurrent.ArrayBlockingQueue&amp;lt;LogEvent&amp;gt;&lt;&#x2F;code&gt; can be used. This is a fixed-capacity, bounded blocking queue.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Producer Behavior:&lt;&#x2F;strong&gt; Application threads would use &lt;code&gt;queue.offer()&lt;&#x2F;code&gt; to non-blockingly submit &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instances. For “ultra-fast” caller performance, a discard policy is often preferred when the buffer is full, preventing the application thread from blocking. Alternatively, &lt;code&gt;queue.put()&lt;&#x2F;code&gt; could be used with a timeout for critical logs, allowing some blocking but preventing indefinite waits.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Consumer Behavior:&lt;&#x2F;strong&gt; &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; threads would use &lt;code&gt;queue.poll()&lt;&#x2F;code&gt; (non-blocking) or &lt;code&gt;queue.take()&lt;&#x2F;code&gt; (blocking) to retrieve events. The &lt;code&gt;queue.drainTo()&lt;&#x2F;code&gt; method is particularly useful for fetching multiple events at once, facilitating efficient batch processing by the &lt;code&gt;LogProcessor&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;While &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt; is simpler to implement and avoids the external Disruptor dependency, it typically does not match the peak performance of a finely tuned Disruptor for extreme throughput scenarios. Log4j2’s asynchronous appenders, which use &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt;, are demonstrably slower than its Disruptor-based asynchronous loggers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Capacity &amp;amp; Full Policies&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Determining the optimal buffer size is crucial. For the Disruptor, a power-of-two capacity (e.g., 2^N) is typically recommended. For &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt;, a reasonable fixed size must be chosen.&lt;&#x2F;p&gt;
&lt;p&gt;When the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt; is full, the library’s behavior must be explicitly defined:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Discard:&lt;&#x2F;strong&gt; The fastest option for the caller, where log events are simply dropped. This is often chosen for non-critical logs to ensure the application remains “ultra-fast”.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Block:&lt;&#x2F;strong&gt; The caller thread waits until space becomes available in the buffer. This ensures data integrity but directly impacts application performance if the logging subsystem cannot keep up.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Log a warning:&lt;&#x2F;strong&gt; An internal log message can be generated to indicate that the buffer is full and events are being discarded or blocked.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A hybrid approach might be implemented, where low-priority logs are discarded when the buffer is full, while high-priority logs might block or be buffered to a secondary, smaller critical buffer.&lt;&#x2F;p&gt;
&lt;!-- **Table: LogBuffer Performance Characteristics (Comparative Overview)**

| Characteristic | LMAX Disruptor | ArrayBlockingQueue (Optimized) |
| :--- | :--- | :--- |
| **Throughput** | Extremely High | High (Slower than Disruptor for peak loads) |
| **Latency** | Consistently Low (Smaller spikes) | Moderate (Higher latency spikes) |
| **Memory Footprint** | High (Large pre-allocated ring buffer) | Moderate (Fixed capacity) |
| **Implementation Complexity** | High (Requires specific pattern knowledge) | Moderate (Standard Java API) |
| **Dependency** | External library required | Core Java (`java.util.concurrent`) |
| **Best Use Case** | Extreme performance, low-latency, single-producer | High performance, simpler implementation, multi-producer |
| **Multi-Producer Nuance**| Can be slower than ABQ without bulk ops | Good with bulk operations; can outperform Disruptor | --&gt;
&lt;p&gt;The choice between Disruptor and &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt; is not a simple matter of “faster is better.” While Disruptor offers unparalleled low-latency and high-throughput capabilities in specific configurations, its complexity and memory footprint are significant. For multi-producer scenarios, a well-tuned &lt;code&gt;ArrayBlockingQueue&lt;&#x2F;code&gt; with bulk operations can sometimes rival or even surpass Disruptor’s performance. This highlights that “ultra-fast” is highly dependent on the specific workload patterns and the careful tuning of the chosen concurrency mechanism.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-4-logprocessor-worker-threads-thread-management-batching-logic-and-graceful-shutdown&quot;&gt;2.4. LogProcessor (Worker Threads): Thread Management, Batching Logic, and Graceful Shutdown&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; is responsible for consuming &lt;code&gt;LogEvents&lt;&#x2F;code&gt; from the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt; and writing them to the configured sinks.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thread Management:&lt;&#x2F;strong&gt; An &lt;code&gt;ExecutorService&lt;&#x2F;code&gt;, such as a &lt;code&gt;FixedThreadPool&lt;&#x2F;code&gt;, is a suitable choice for managing the pool of worker threads. This abstracts the complexities of thread lifecycle management.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Loop:&lt;&#x2F;strong&gt; Each worker thread in the &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; continuously enters a loop, attempting to poll or consume &lt;code&gt;LogEvent&lt;&#x2F;code&gt; instances from the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Batching:&lt;&#x2F;strong&gt; To amortize I&#x2F;O costs, worker threads collect &lt;code&gt;LogEvents&lt;&#x2F;code&gt; into batches. This can be achieved by collecting a predefined number of events (&lt;code&gt;batchSize&lt;&#x2F;code&gt;) or by waiting for a specified &lt;code&gt;batchTimeout&lt;&#x2F;code&gt; before performing the actual I&#x2F;O operation. Fine-tuning these parameters is crucial to balance latency and throughput.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Error Handling:&lt;&#x2F;strong&gt; Robust error handling is essential. If writing to a sink fails (e.g., disk full, network error), the system must react gracefully. Strategies include retry for transient errors, discard for persistent errors, and internal logging for diagnostics without causing a recursive loop.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Shutdown Hook:&lt;&#x2F;strong&gt; A graceful shutdown mechanism is vital to ensure that all remaining &lt;code&gt;LogEvents&lt;&#x2F;code&gt; in the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt; are processed and flushed before the application terminates. This can be implemented by registering a shutdown hook or by using Spring’s &lt;code&gt;DisposableBean&lt;&#x2F;code&gt; interface or &lt;code&gt;@PreDestroy&lt;&#x2F;code&gt; methods.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;2-5-logformatter-crafting-visualization-friendly-json&quot;&gt;&lt;strong&gt;2.5. LogFormatter: Crafting Visualization-Friendly JSON&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;LogFormatter&lt;&#x2F;code&gt; transforms a &lt;code&gt;LogEvent&lt;&#x2F;code&gt; into a structured JSON string.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Schema Definition&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The JSON schema must be rich and consistent for external tools.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ISO_DATE_TIME&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;INFO|WARN|ERROR|DEBUG|TRACE&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;serviceName&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;hostName&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;requestId&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;UUID_STRING&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;threadName&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;loggerName&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;context&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;userId&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;123&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;sessionId&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abc&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;productId&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PROD-001&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;operationTimeMs&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 50&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;eventIdentifier&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PRODUCT_RETRIEVAL_SUCCESS&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;exception&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;stackTrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Optimization: &lt;code&gt;StringBuilder&lt;&#x2F;code&gt; and &lt;code&gt;ByteArrayOutputStream&lt;&#x2F;code&gt; Reuse&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To minimize object allocations, reusing mutable buffers is crucial.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;StringBuilder&lt;&#x2F;code&gt; Reuse:&lt;&#x2F;strong&gt; A &lt;code&gt;StringBuilder&lt;&#x2F;code&gt; instance should be reused per thread. The most efficient way to clear it is &lt;code&gt;setLength(0)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ByteArrayOutputStream&lt;&#x2F;code&gt; Reuse:&lt;&#x2F;strong&gt; If converting to bytes, a &lt;code&gt;ByteArrayOutputStream&lt;&#x2F;code&gt; can also be reused by resetting its internal buffer.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Jackson vs. Gson&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jackson:&lt;&#x2F;strong&gt; Widely regarded as the fastest JSON library in Java, particularly for high-throughput, multi-threaded scenarios. Its performance and memory efficiency make it ideal for logging.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Gson:&lt;&#x2F;strong&gt; Simpler API but generally slower due to its reliance on reflection.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Given the “ultra-fast” requirement, &lt;strong&gt;Jackson&lt;&#x2F;strong&gt; is the preferred choice, using only its core modules to maintain the “less libraries” goal.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-6-logsink-interface-and-implementations-efficient-data-persistence&quot;&gt;2.6. LogSink Interface and Implementations: Efficient Data Persistence&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;LogSink&lt;&#x2F;code&gt; interface defines the contract for writing log entries.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;interface&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; LogSink&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;List&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; batchedLogEntries&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; flush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;FileLogSink&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Buffered I&#x2F;O:&lt;&#x2F;strong&gt; &lt;code&gt;BufferedWriter&lt;&#x2F;code&gt; is a standard, efficient choice.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Log Rotation:&lt;&#x2F;strong&gt; Simple size- or time-based rotation should be implemented.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Advanced I&#x2F;O (&lt;code&gt;java.nio&lt;&#x2F;code&gt;):&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;FileChannel&lt;&#x2F;code&gt; and &lt;code&gt;ByteBuffer&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; Excellent for high-performance writes with durability control via &lt;code&gt;force()&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MappedByteBuffer&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; Can be “ultra-fast” for &lt;em&gt;frequent writes to large files&lt;&#x2F;em&gt;, but is complex, OS-dependent, and &lt;em&gt;not&lt;&#x2F;em&gt; ideal for the small, frequent appends typical of logging.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;AsynchronousFileChannel&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; Adds complexity (callbacks, &lt;code&gt;Future&lt;&#x2F;code&gt;s) that may offer marginal benefit in a dedicated worker thread model.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- **Table: File I&#x2F;O Mechanism Comparison**

&lt;div class=&quot;table-responsive&quot;&gt;

| Method           | Buffered? | Appends? | Durability Control? | Performance (Relative) | Best Use Case                                | Key Pitfalls                                      |
| :--------------- | :-------: | :------: | :-----------------: | :--------------------: | :------------------------------------------- | :------------------------------------------------ |
| `BufferedWriter` | ✅ Yes    | ✅ Yes   | ❌ No (OS flushes)  | 🟡 Medium              | General logging, large text files            | No explicit durability control                    |
| `FileChannel`      | ✅ Yes    | ✅ Yes   | ✅ Yes (`force()`)  | 🟢 Fast                | High-performance I&#x2F;O, commit logs            | More complex than streams                         |
| `MappedByteBuffer` | ✅ Yes    | ❌ No    | ❌ No (OS flushes)  | 🟢 Very Fast           | Frequent writes to *very* large files, random access | Not for small appends, complex, OS-dependent      |
| `RandomAccessFile` | ❌ No     | ✅ Yes   | ✅ Yes (`sync()`)   | 🟢 Fast                | Append-heavy workloads with durability needs | Less flexible than `FileChannel`                  |

&lt;&#x2F;div&gt; --&gt;
&lt;p&gt;&lt;strong&gt;NetworkLogSink (e.g., HTTP&#x2F;Kafka)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Minimal Libraries (&lt;code&gt;HttpURLConnection&lt;&#x2F;code&gt;, Sockets):&lt;&#x2F;strong&gt; Adheres to “zero dependencies” but requires a massive effort to build a reliable, high-performance client.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Kafka Integration (&lt;code&gt;KafkaProducer&lt;&#x2F;code&gt;):&lt;&#x2F;strong&gt; The industry-standard client. While an external dependency, it is essential for reliable, high-performance Kafka integration. It’s highly optimized with features for batching, compression, and durability.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Retry Mechanisms and Backpressure:&lt;&#x2F;strong&gt; For any network sink, robust retry mechanisms (e.g., exponential backoff with jitter) and backpressure handling are crucial for resilience against network failures.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;2-7-mylogger-facade-the-ultra-lightweight-entry-point&quot;&gt;2.7. MyLogger Facade: The Ultra-Lightweight Entry Point&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;MyLogger&lt;&#x2F;code&gt; facade is the public API. It must be exceptionally fast.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Caching:&lt;&#x2F;strong&gt; &lt;code&gt;MyLogger&lt;&#x2F;code&gt; instances should be cached in a &lt;code&gt;ConcurrentHashMap&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Methods:&lt;&#x2F;strong&gt; &lt;code&gt;info()&lt;&#x2F;code&gt;, &lt;code&gt;warn()&lt;&#x2F;code&gt;, &lt;code&gt;error()&lt;&#x2F;code&gt;, &lt;code&gt;debug()&lt;&#x2F;code&gt;, &lt;code&gt;trace()&lt;&#x2F;code&gt;, with overloads for structured data.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Core Logic:&lt;&#x2F;strong&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Level Check:&lt;&#x2F;strong&gt; The first and most critical step is an efficient &lt;code&gt;if (logger.isInfoEnabled())&lt;&#x2F;code&gt; check to prevent any work for disabled log levels.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;LogEvent Reuse:&lt;&#x2F;strong&gt; Retrieve a &lt;code&gt;LogEvent&lt;&#x2F;code&gt; from a pool.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Population:&lt;&#x2F;strong&gt; Populate the event with data.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Buffer Offer:&lt;&#x2F;strong&gt; Non-blockingly offer the event to the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;2-8-spring-integration-requestidfilter-and-lifecycle-hooks&quot;&gt;2.8. Spring Integration: &lt;code&gt;RequestIdFilter&lt;&#x2F;code&gt; and Lifecycle Hooks&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;RequestIdFilter&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; A Spring &lt;code&gt;WebFilter&lt;&#x2F;code&gt; should:
&lt;ol&gt;
&lt;li&gt;Check for an &lt;code&gt;X-Request-ID&lt;&#x2F;code&gt; header; if not present, generate a new UUID.&lt;&#x2F;li&gt;
&lt;li&gt;Store the ID in &lt;code&gt;MyMDC&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Crucially&lt;&#x2F;strong&gt;, clear the ID from &lt;code&gt;MyMDC&lt;&#x2F;code&gt; in a &lt;code&gt;finally&lt;&#x2F;code&gt; block to prevent thread pollution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Asynchronous Context Propagation:&lt;&#x2F;strong&gt; &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt;-based MDC context does &lt;em&gt;not&lt;&#x2F;em&gt; automatically propagate to new threads (e.g., in a &lt;code&gt;CompletableFuture&lt;&#x2F;code&gt;). Explicit context transfer is required, typically by wrapping the &lt;code&gt;Runnable&lt;&#x2F;code&gt; or &lt;code&gt;Callable&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Startup&#x2F;Shutdown:&lt;&#x2F;strong&gt; Use Spring’s &lt;code&gt;ApplicationRunner&lt;&#x2F;code&gt; for initialization and &lt;code&gt;DisposableBean&lt;&#x2F;code&gt; or &lt;code&gt;@PreDestroy&lt;&#x2F;code&gt; for graceful shutdown to flush all logs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;3-deep-research-advanced-optimization-pushing-the-performance-envelope&quot;&gt;3. Deep Research &amp;amp; Advanced Optimization: Pushing the Performance Envelope&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;3-1-comprehensive-garbage-free-strategies&quot;&gt;3.1. Comprehensive Garbage-Free Strategies&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LogEvent Pooling:&lt;&#x2F;strong&gt; Consider a global, concurrent object pool if &lt;code&gt;LogEvent&lt;&#x2F;code&gt; objects are returned by consumer threads, which can simplify cleanup and avoid &lt;code&gt;ThreadLocal&lt;&#x2F;code&gt; leak issues.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;MDC Map Reuse:&lt;&#x2F;strong&gt; Re-evaluate the “view vs. copy” trade-off. A read-only view offers zero allocation but carries risks if the underlying map changes. A defensive copy is safer but incurs an allocation. The choice depends on the internal data flow and immutability guarantees.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;3-2-concurrency-model-deep-dive&quot;&gt;3.2. Concurrency Model Deep Dive&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LMAX Disruptor Mastery:&lt;&#x2F;strong&gt; A deep understanding of the Disruptor’s “mechanical sympathy” and its various &lt;code&gt;WaitStrategy&lt;&#x2F;code&gt; options is key to tuning the trade-off between CPU usage and latency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Contention Analysis:&lt;&#x2F;strong&gt; Use profilers (JVisualVM, YourKit, Async-profiler) to identify real-world bottlenecks like lock contention, GC pauses, and I&#x2F;O constraints.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Backpressure:&lt;&#x2F;strong&gt; A robust library must gracefully handle overload. The &lt;code&gt;LogBuffer&lt;&#x2F;code&gt; full policy (discard, block, hybrid) is the primary mechanism for this.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;3-3-i-o-optimization-advanced-nio-nuances&quot;&gt;3.3. I&#x2F;O Optimization: Advanced NIO Nuances&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;FileChannel&lt;&#x2F;code&gt; and &lt;code&gt;ByteBuffer&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; Reusing &lt;code&gt;ByteBuffer&lt;&#x2F;code&gt; instances, especially direct buffers, is critical to avoid the “ridiculously slow” performance of frequent allocations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MappedByteBuffer&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; Re-emphasize that for typical sequential logging, &lt;code&gt;MappedByteBuffer&lt;&#x2F;code&gt; is often &lt;em&gt;not&lt;&#x2F;em&gt; the optimal choice and can be slower and more complex than alternatives.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;AsynchronousFileChannel&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; Its benefits may be marginal for a logging library that already offloads I&#x2F;O to a dedicated worker pool.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Batching Strategies:&lt;&#x2F;strong&gt; Fine-tuning &lt;code&gt;batchSize&lt;&#x2F;code&gt; and &lt;code&gt;batchTimeout&lt;&#x2F;code&gt; through empirical testing is crucial for balancing latency and throughput.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;3-4-logging-levels-filtering&quot;&gt;3.4. Logging Levels &amp;amp; Filtering&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Facade-Level Checks:&lt;&#x2F;strong&gt; The &lt;code&gt;if (logger.is...Enabled())&lt;&#x2F;code&gt; guard clause is the single most important performance optimization on the application thread.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Configurable Levels:&lt;&#x2F;strong&gt; Allow granular, dynamic configuration of log levels per logger name, stored in a &lt;code&gt;ConcurrentHashMap&lt;&#x2F;code&gt; for fast lookups.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;3-5-visualization-schema-refinement&quot;&gt;3.5. Visualization &amp;amp; Schema Refinement&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Event-Driven Logging:&lt;&#x2F;strong&gt; Encourage using an &lt;code&gt;eventIdentifier&lt;&#x2F;code&gt; field to transform logs into a stream of actionable business or system events for better dashboarding.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Metric Extraction:&lt;&#x2F;strong&gt; Ensure numerical fields (&lt;code&gt;operationTimeMs&lt;&#x2F;code&gt;) are logged as numbers, not strings, to facilitate direct aggregation and analysis.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Field Naming Consistency:&lt;&#x2F;strong&gt; Adhere to a consistent naming convention (e.g., camelCase) for all JSON fields.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;3-6-request-unique-id-lifecycle-traceability&quot;&gt;3.6. Request Unique ID Lifecycle (Traceability)&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Generation:&lt;&#x2F;strong&gt; A &lt;code&gt;RequestIdFilter&lt;&#x2F;code&gt; should check for an existing &lt;code&gt;X-Request-ID&lt;&#x2F;code&gt; header before generating a new UUID to maintain trace continuity.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Propagation:&lt;&#x2F;strong&gt; The &lt;code&gt;requestId&lt;&#x2F;code&gt; must be propagated across all communication layers: outgoing HTTP requests, message queues (Kafka, RabbitMQ), and RPC frameworks.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Clearing:&lt;&#x2F;strong&gt; The most critical step is clearing the &lt;code&gt;requestId&lt;&#x2F;code&gt; from &lt;code&gt;MyMDC&lt;&#x2F;code&gt; in a &lt;code&gt;finally&lt;&#x2F;code&gt; block to prevent thread pollution and incorrect log correlation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;4-rigorous-testing-reliability-ensuring-production-readiness&quot;&gt;4. Rigorous Testing &amp;amp; Reliability: Ensuring Production Readiness&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;4-1-benchmarking-measuring-ultra-fast-performance&quot;&gt;4.1. Benchmarking: Measuring “Ultra-Fast” Performance&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JMH (Java Microbenchmark Harness):&lt;&#x2F;strong&gt; Use JMH with proper &lt;code&gt;@Fork&lt;&#x2F;code&gt;, &lt;code&gt;@Warmup&lt;&#x2F;code&gt;, and &lt;code&gt;@Measurement&lt;&#x2F;code&gt; configurations. Use &lt;code&gt;@Threads&lt;&#x2F;code&gt; to simulate concurrent load.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Metrics:&lt;&#x2F;strong&gt; Focus on &lt;strong&gt;tail latencies (p99, p99.9)&lt;&#x2F;strong&gt;, not just average latency, as they reveal performance spikes. Also monitor throughput, CPU, and memory.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Realistic Simulations:&lt;&#x2F;strong&gt; Benchmark against a known baseline like &lt;strong&gt;Log4j2’s AsyncLogger&lt;&#x2F;strong&gt; under realistic, bursty load conditions to validate performance claims.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- &lt;div class=&quot;table-responsive&quot;&gt;

| Test Scenario                           | Library      | Throughput (Ops&#x2F;sec) | Latency (p50 µs) | Latency (p90 µs) | Latency (p99 µs) | Latency (p99.9 µs) |
| :-------------------------------------- | :----------- | :------------------: | :--------------: | :--------------: | :--------------: | :----------------: |
| Single Producer, Light Message          | Your Library |       [Value]        |     [Value]      |     [Value]      |     [Value]      |      [Value]       |
| Single Producer, Light Message          | Log4j2 Async |       [Value]        |     [Value]      |     [Value]      |     [Value]      |      [Value]       |
| Multi-Producer (16), Light Message      | Your Library |       [Value]        |     [Value]      |     [Value]      |     [Value]      |      [Value]       |
| Multi-Producer (16), Light Message      | Log4j2 Async |       [Value]        |     [Value]      |     [Value]      |     [Value]      |      [Value]       |
| Multi-Producer (16), Heavy Msg (w&#x2F; exc) | Your Library |       [Value]        |     [Value]      |     [Value]      |     [Value]      |      [Value]       |
| Multi-Producer (16), Heavy Msg (w&#x2F; exc) | Log4j2 Async |       [Value]        |     [Value]      |     [Value]      |     [Value]      |      [Value]       |

&lt;&#x2F;div&gt; --&gt;
&lt;h4 id=&quot;4-2-failure-modes-graceful-degradation-resilience-in-adversity&quot;&gt;4.2. Failure Modes &amp;amp; Graceful Degradation: Resilience in Adversity&lt;&#x2F;h4&gt;
&lt;p&gt;A production-ready library must degrade gracefully without crashing the application.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Disk Full Scenarios:&lt;&#x2F;strong&gt; Detect disk full conditions, stop writing, log a warning to a fallback sink (like the console), and start discarding messages.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Network Sink Unavailability:&lt;&#x2F;strong&gt; Use robust retry policies with exponential backoff and jitter. If retries fail, buffer locally (with a bounded buffer) or discard logs to prevent blocking.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Backpressure:&lt;&#x2F;strong&gt; Use the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt;’s full policy (discard, block, hybrid) to ensure application threads are not affected by a slow logging subsystem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;4-3-configuration-custom-parser-vs-standard-properties-yaml&quot;&gt;4.3. Configuration: Custom Parser vs. Standard Properties&#x2F;YAML&lt;&#x2F;h4&gt;
&lt;p&gt;For a low-dependency library, avoid heavy configuration frameworks.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Custom Configuration Parser:&lt;&#x2F;strong&gt; Leverage &lt;code&gt;java.util.Properties&lt;&#x2F;code&gt; for simple key-value configs or a minimal, zero-dependency JSON parser for more structured configurations. This provides full control without introducing bloat.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;4-4-testability-unit-testing-performance-critical-paths&quot;&gt;4.4. Testability: Unit Testing Performance-Critical Paths&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JMH for Micro-benchmarking:&lt;&#x2F;strong&gt; Use JMH to unit test performance-critical code paths, not just for overall system benchmarking.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Concurrency Testing:&lt;&#x2F;strong&gt; Rigorously test the &lt;code&gt;LogBuffer&lt;&#x2F;code&gt; and &lt;code&gt;LogProcessor&lt;&#x2F;code&gt; for thread safety, deadlocks, and race conditions under high contention.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;conclusion-future-outlook&quot;&gt;Conclusion &amp;amp; Future Outlook&lt;&#x2F;h3&gt;
&lt;p&gt;The development of an “ultra-fast,” low-dependency, multi-threaded Java logging library is a challenging but achievable endeavor. The core principles of asynchronous processing, rigorous zero-allocation strategies, intelligent concurrency management, and dedicated thread isolation are fundamental to achieving minimal overhead and high throughput.&lt;&#x2F;p&gt;
&lt;p&gt;The success of such a library is measured by its empirical performance and resilience. This necessitates continuous, rigorous benchmarking using tools like JMH, focusing on tail latencies. Furthermore, the library must be designed with robust failure modes and graceful degradation strategies, ensuring that logging issues never compromise the main application’s stability.&lt;&#x2F;p&gt;
&lt;p&gt;Future enhancements could include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Expansion of &lt;code&gt;LogSink&lt;&#x2F;code&gt; types (e.g., cloud-specific sinks).&lt;&#x2F;li&gt;
&lt;li&gt;More sophisticated filtering and routing capabilities.&lt;&#x2F;li&gt;
&lt;li&gt;Deeper integration with distributed tracing systems like OpenTelemetry.&lt;&#x2F;li&gt;
&lt;li&gt;Dynamic configuration reloading without application restarts.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By adhering to these principles, a truly “ultra-fast,” high-throughput, low-dependency logging library can be realized, providing invaluable observability for performance-critical Java applications.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;works-cited&quot;&gt;Works Cited&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logging.apache.org&#x2F;log4j&#x2F;2.x&#x2F;manual&#x2F;async.html&quot;&gt;Asynchronous loggers :: Apache Log4j - Apache Logging Services&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.bluepeople.com&#x2F;java-asynchronous-programming-unlocking-efficiency-in-modern-applications&#x2F;&quot;&gt;Unlocking Java Asynchronous Programming: Key Concepts, Tools, and Benefits&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logging.apache.org&#x2F;log4j&#x2F;2.12.x&#x2F;manual&#x2F;async.html&quot;&gt;Log4j 2 Lock-free Asynchronous Loggers for Low-Latency Logging&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nuget.org&#x2F;packages&#x2F;ZeroLog&quot;&gt;ZeroLog 2.2.0 - NuGet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Abc-Arbitrage&#x2F;ZeroLog&quot;&gt;Abc-Arbitrage&#x2F;ZeroLog: A high-performance, zero … - GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logging.apache.org&#x2F;log4j&#x2F;3.x&#x2F;manual&#x2F;garbagefree.html&quot;&gt;Garbage-free logging :: Apache Log4j&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logging.apache.org&#x2F;log4j&#x2F;2.12.x&#x2F;manual&#x2F;garbagefree.html&quot;&gt;Log4j – Garbage-free Steady State Logging - Apache Log4j 2&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.dash0.com&#x2F;faq&#x2F;log4j-2-the-complete-guide-to-modern-java-logging&quot;&gt;Log4j 2: The Complete Guide to Modern Java Logging - Dash0&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dubbo.apache.org&#x2F;en&#x2F;docs3-v2&#x2F;java-sdk&#x2F;advanced-features-and-usage&#x2F;service&#x2F;isolation-executor&#x2F;&quot;&gt;Thread Pool Isolation | Apache Dubbo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dzone.com&#x2F;articles&#x2F;mastering-thread-local-variables-in-java-a-compreh&quot;&gt;Java Thread-Local Variables: Explained - DZone&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeline24.com&#x2F;introduction-to-threadlocal&#x2F;&quot;&gt;Java ThreadLocal - Java and Spring Trends&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.baeldung.com&#x2F;java-threadlocal&quot;&gt;An Introduction to ThreadLocal in Java | Baeldung&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dzone.com&#x2F;articles&#x2F;jackson-vs-gson-edge-cases-json-parsing-java&quot;&gt;Jackson vs Gson: Edge Cases in JSON Parsing for Java Apps - DZone&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.javacodegeeks.com&#x2F;2024&#x2F;12&#x2F;efficient-json-parsing-in-java-jackson-vs-gson-vs-json-b.html&quot;&gt;Efficient JSON Parsing in Java: Jackson vs. Gson vs. JSON-B - Java …&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;63859574&#x2F;why-did-log4j2-used-lmax-disruptor-in-async-logger-instead-of-any-other-built-in&quot;&gt;Why did log4j2 used LMAX Disruptor in Async logger instead of any other built in non blocking data structure? - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;highscalability.com&#x2F;a-well-known-but-forgotten-trick-object-pooling&#x2F;&quot;&gt;A Well Known But Forgotten Trick: Object Pooling - High Scalability -&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;680514&#x2F;object-pooling-in-java&quot;&gt;Object Pooling in Java - memory management - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cloudastra.co&#x2F;blogs&#x2F;logback-mdc-an-essential-tool-for-effective-logging-in-java&quot;&gt;Logback MDC: An Essential Tool For Effective Logging In Java&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logging.apache.org&#x2F;log4j&#x2F;2.12.x&#x2F;manual&#x2F;thread-context.html&quot;&gt;Log4j 2 Thread Context - Apache Logging Services&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.devzery.com&#x2F;post&#x2F;java-threadlocal-unveiling-the-power-of-thread-specific-data&quot;&gt;Java ThreadLocal: Unveiling the Power of Thread-Specific Data - Devzery&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;3869026&#x2F;how-to-clean-up-threadlocals&quot;&gt;How to clean up ThreadLocals - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;trifork.nl&#x2F;blog&#x2F;adding-user-info-to-log-entries-in-a-multi-user-app-using-mapped-diagnostic-context&#x2F;&quot;&gt;Adding user info to log entries in a multi-user app using Mapped Diagnostic Context&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;richardmr36&#x2F;correlation-in-logging-4ef4&quot;&gt;Correlation in logging - DEV Community&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kapresoft.com&#x2F;java&#x2F;2023&#x2F;12&#x2F;19&#x2F;java-threadlocal-best-practices.html&quot;&gt;Java • ThreadLocal Best Practices - KapreSoft&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lmax-exchange.github.io&#x2F;disruptor&#x2F;user-guide&#x2F;index.html&quot;&gt;LMAX Disruptor User Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;groups.google.com&#x2F;g&#x2F;lmax-disruptor&#x2F;c&#x2F;EBSX14ptenY&quot;&gt;Re: Disruptor vs ArrayBlockingQueue tests. Disruptor is better only …&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apache&#x2F;logging-log4j2&#x2F;issues&#x2F;2220&quot;&gt;Create an alternative async logger implementation using JCTools · Issue #2220 · apache&#x2F;logging-log4j2 - GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.alibabacloud.com&#x2F;blog&#x2F;analysis-of-performance-practices-in-java-log-and-principle-interpretation_600797&quot;&gt;Analysis of Performance Practices in Java Log and Principle Interpretation - Alibaba Cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;46518006&#x2F;what-does-the-term-backpressure-mean-in-rxjava&quot;&gt;What does the term “backpressure” mean in Rxjava? - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logging.apache.org&#x2F;log4j&#x2F;2.x&#x2F;javadoc&#x2F;log4j-core&#x2F;org&#x2F;apache&#x2F;logging&#x2F;log4j&#x2F;core&#x2F;async&#x2F;DiscardingAsyncQueueFullPolicy.html&quot;&gt;DiscardingAsyncQueueFullPolicy (Apache Log4j Core 2.24.3 API)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dataflow.spring.io&#x2F;docs&#x2F;batch-developer-guides&#x2F;troubleshooting&#x2F;debugging-task-apps&#x2F;&quot;&gt;Debugging Batch Applications - Documentation | Spring Cloud Data Flow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.baeldung.com&#x2F;java-reuse-stringbuilder-for-efficiency&quot;&gt;Reuse StringBuilder for Efficiency | Baeldung&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webreference.com&#x2F;xml&#x2F;advanced&#x2F;performance&quot;&gt;XML Performance Optimization - Speed and Memory Efficiency - Web Reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tmsvr.com&#x2F;java-file-writing-i-o-performance&#x2F;&quot;&gt;Java File writing I&#x2F;O performance - TMSVR&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.javacodegeeks.com&#x2F;2016&#x2F;01&#x2F;readingwriting-tofrom-files-using-filechannel-bytebuffer-java.html&quot;&gt;Reading&#x2F;Writing to&#x2F;from Files using FileChannel and ByteBuffer in Java - Java Code Geeks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;transloadit.com&#x2F;devtips&#x2F;boost-java-performance-with-memory-mapped-files&#x2F;&quot;&gt;Boost Java performance with memory-mapped files | Transloadit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;28421810&#x2F;mappedbytebuffer-throwing-a-java-nio-bufferoverflowexception&quot;&gt;asynchronous - MappedByteBuffer throwing a java.nio …&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;7738735&#x2F;java-bytebuffer-performance-issue&quot;&gt;Java ByteBuffer performance issue - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.jboss.org&#x2F;thread&#x2F;82231&quot;&gt;ByteBuffer.allocateDirect ridiculously slow| JBoss.org Content Archive (Read Only)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;7611152&#x2F;nio-performance-improvement-compared-to-traditional-io-in-java&quot;&gt;NIO Performance Improvement compared to traditional IO in Java - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;16058938&#x2F;io-and-nio-performance-difference-and-example&quot;&gt;IO and NIO performance difference and example - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jenkov.com&#x2F;tutorials&#x2F;java-nio&#x2F;asynchronousfilechannel.html&quot;&gt;Java NIO AsynchronousFileChannel - Jenkov.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;javanexus.com&#x2F;blog&#x2F;troubleshooting-java-nio-performance-pitfalls&quot;&gt;Troubleshooting Java NIO Non-Blocking IO Performance Pitfalls - Java Tech Blog&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;dnetix&#x2F;db23658cb308a0f2ac1b09f2ddb726d3&quot;&gt;Simple Java Rest Client posting JSON to a server - GitHub Gist&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;21404252&#x2F;post-request-send-json-data-java-httpurlconnection&quot;&gt;POST request send JSON data Java HttpUrlConnection - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;34797165&#x2F;how-can-i-use-java-to-send-http-post-request-of-a-json-array-of-strings&quot;&gt;How can I use java to send HTTP post request of a JSON array of strings? - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dev.splunk.com&#x2F;view&#x2F;splunk-logging-java&#x2F;SP-CAAAE3R&quot;&gt;Enable logging to TCP inputs in your Java project - Splunk Dev&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.opensourceforu.com&#x2F;2015&#x2F;03&#x2F;a-guide-to-using-raw-sockets&#x2F;&quot;&gt;A Guide to Using Raw Sockets - Open Source For You&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codemia.io&#x2F;knowledge-hub&#x2F;path&#x2F;basic_distributed_counter_using_java_sockets&quot;&gt;Basic Distributed Counter using Java Sockets - Codemia&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mirsamantajbakhsh&#x2F;RawSocket&quot;&gt;mirsamantajbakhsh&#x2F;RawSocket: A simple code for raw socket in Java using JNetPCAP. - GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.instaclustr.com&#x2F;education&#x2F;apache-kafka&#x2F;kafka-performance-7-critical-best-practices&#x2F;&quot;&gt;Kafka performance: 7 critical best practices - NetApp Instaclustr&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;community.ibm.com&#x2F;community&#x2F;user&#x2F;blogs&#x2F;devesh-singh&#x2F;2024&#x2F;09&#x2F;26&#x2F;how-to-improve-kafka-performance-a-comprehensive-g&quot;&gt;How to Improve Kafka Performance: A Comprehensive Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dzone.com&#x2F;articles&#x2F;failure-handling-mechanisms-in-microservices&quot;&gt;Failure Handling Mechanisms in Microservices and Their Importance - DZone&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;javadzone.com&#x2F;how-do-i-handle-failures-in-microservices&#x2F;&quot;&gt;How Do I Handle Failures in Microservices? - JavaDZone&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.datastax.com&#x2F;en&#x2F;drivers&#x2F;java&#x2F;2.1&#x2F;com&#x2F;datastax&#x2F;driver&#x2F;core&#x2F;policies&#x2F;LoggingRetryPolicy.html&quot;&gt;LoggingRetryPolicy (DataStax Java Driver for Apache Cassandra - Binary distribution 2.1.10 API)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gridgain.com&#x2F;docs&#x2F;gridgain9&#x2F;latest&#x2F;developers-guide&#x2F;clients&#x2F;java&quot;&gt;Java Client | GridGain Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;builders-library&#x2F;timeouts-retries-and-backoff-with-jitter&#x2F;&quot;&gt;Timeouts, retries and backoff with jitter - AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;41678918&#x2F;exponential-backoff-in-rxjava&quot;&gt;Exponential Backoff in RxJava - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;javanexus.com&#x2F;blog&#x2F;mastering-backpressure-project-reactor-pitfalls&quot;&gt;Mastering Backpressure in Project Reactor: Common Pitfalls | Java Tech Blog&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;last9.io&#x2F;blog&#x2F;java-logging-troubleshooting-tips-and-best-practices&#x2F;&quot;&gt;Java Logging: Troubleshooting Tips and Best Practices - Last9&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dzone.com&#x2F;articles&#x2F;implementing-correlation-ids&quot;&gt;Implementing Correlation ids in Spring Boot (for Distributed Tracing in SOA&#x2F;Microservices)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;SpringBoot&#x2F;comments&#x2F;1l7tnyu&#x2F;threadpool_with_completablefuture_need_mdc&#x2F;&quot;&gt;ThreadPool with CompletableFuture (need MDC propagation) : r&#x2F;SpringBoot - Reddit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.geeksforgeeks.org&#x2F;java-microbenchmark-harness-jmh&#x2F;&quot;&gt;Java Microbenchmark Harness (JMH) - GeeksforGeeks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;72529842&#x2F;executorservice-with-backpressure&quot;&gt;ExecutorService with backpressure - java - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kapresoft.com&#x2F;java&#x2F;2023&#x2F;12&#x2F;18&#x2F;java-logback-mdc-in-action.html&quot;&gt;Java • Logback Mapped Diagnostic Context (MDC) in Action | KapreSoft&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;OpenElements&#x2F;java-logger-benchmark&quot;&gt;OpenElements&#x2F;java-logger-benchmark: A benchmark for … - GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;swiftpackageindex.com&#x2F;ordo-one&#x2F;package-benchmark&quot;&gt;Benchmark - Swift Package Index&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thebackendguy.com&#x2F;posts&#x2F;performance-analysis-using-jmh&#x2F;&quot;&gt;Performance Analysis using JMH | The Backend Guy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;39644383&#x2F;jmh-run-benchmark-concurrently&quot;&gt;jmh: Run benchmark concurrently - java - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;69760827&#x2F;jmh-how-to-correctly-benchmark-thread-pools&quot;&gt;java - JMH - How to correctly benchmark Thread Pools? - Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kodewerk.com&#x2F;java&#x2F;performance&#x2F;2023&#x2F;08&#x2F;23&#x2F;wheres_the_latency.html&quot;&gt;Is your reported p99 wrong? - Random Notes and Cheat Sheets - Kirk Pepperdine&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;architecture&#x2F;framework&#x2F;reliability&#x2F;graceful-degradation&quot;&gt;Design for graceful degradation | Cloud Architecture Center | Google …&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.logrocket.com&#x2F;guide-graceful-degradation-web-development&#x2F;&quot;&gt;A guide to graceful degradation in web development - LogRocket Blog&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;last9.io&#x2F;blog&#x2F;logging-best-practices&#x2F;&quot;&gt;Logging Best Practices to Reduce Noise and Improve Insights - Last9&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ralfstx&#x2F;minimal-json&quot;&gt;ralfstx&#x2F;minimal-json: A fast and small JSON parser and … - GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mmastrac&#x2F;nanojson&quot;&gt;mmastrac&#x2F;nanojson: A tiny, compliant JSON parser and … - GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>64 Bit Distributed ID Generator</title>
        <published>2025-03-01T00:00:00+00:00</published>
        <updated>2025-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/blog/id-generator/"/>
        <id>https://siddharthsabron.in/blog/id-generator/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/blog/id-generator/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1764356806873-034b6986ac65?q=80&amp;amp;w=3132&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;LLandor, Mussoorie clicked by siddharth sabron &quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Landor ❤️&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;_1jTELy0VsY&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h3&gt;
&lt;p&gt;Unique &lt;code&gt;ID&lt;&#x2F;code&gt; generation is a crucial part of any application, because it is used to represents a single unique row in the table. Furthermore, this &lt;code&gt;ID&lt;&#x2F;code&gt; is often used as the &lt;code&gt;primary-key&lt;&#x2F;code&gt; of the table and heavily used in searching a specific row uniquely.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example Query:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;select&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;  *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt;  short_urls &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; internal_id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 286435872092454913&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You might wonder why we are emphasizing the ID so much ?. Couldn’t we just generate a unique value using something like &lt;code&gt;Math.random() + epoch&lt;&#x2F;code&gt; or some &lt;code&gt;random_string_of_some_size + epoch&lt;&#x2F;code&gt; While that &lt;em&gt;could&lt;&#x2F;em&gt; produce unique values, but it would be a poor choice for several reasons, especially at scale:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Meaningful Data:&lt;&#x2F;strong&gt; A simple timestamp (or a random number) doesn’t convey any useful information &lt;em&gt;other&lt;&#x2F;em&gt; than the time of creation.  Our Snowflake-like approach embeds a timestamp &lt;em&gt;and&lt;&#x2F;em&gt; a shard ID, which can be useful for operational purposes (e.g., identifying which shard a URL was created on).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Database Performance (Crucially):&lt;&#x2F;strong&gt;  The data type of the primary key has a &lt;em&gt;major&lt;&#x2F;em&gt; impact on database performance, particularly for search operations.  Purely numeric IDs (integers or long integers) are vastly superior to strings for primary keys and indexed columns or both as well(A Indexed Primary).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;why-not-random-strings&quot;&gt;Why Not Random Strings?&lt;&#x2F;h3&gt;
&lt;p&gt;Using random strings (e.g., generated by &lt;code&gt;Math.random() + epoch&lt;&#x2F;code&gt; or random string of some size) as primary keys is generally a &lt;em&gt;bad&lt;&#x2F;em&gt; idea for performance reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Slower Comparisons:&lt;&#x2F;strong&gt; String comparisons are inherently slower than numeric comparisons. Databases can compare integers much more efficiently at the hardware level.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Larger Index Size:&lt;&#x2F;strong&gt; String primary keys create larger database indexes. Indexes are data structures (usually B-trees or B+trees) that speed up lookups. A larger index means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;More &lt;code&gt;disk I&#x2F;O&lt;&#x2F;code&gt; to read the index.&lt;&#x2F;li&gt;
&lt;li&gt;More memory consumption to keep parts of the &lt;code&gt;index&lt;&#x2F;code&gt; in &lt;code&gt;cache&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Slower query performance.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Index Fragmentation:&lt;&#x2F;strong&gt; Inserting random strings into a B-tree index leads to &lt;em&gt;fragmentation&lt;&#x2F;em&gt;.  A fragmented index has its data scattered across the disk. This requires more disk seeks (which are slow) to retrieve data. Numeric, &lt;em&gt;sequential&lt;&#x2F;em&gt; IDs minimize fragmentation because new entries are usually appended to the &lt;em&gt;end&lt;&#x2F;em&gt; of the index.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Poor Locality of Reference:&lt;&#x2F;strong&gt; Random strings have poor &lt;em&gt;locality of reference&lt;&#x2F;em&gt;. Successive ID lookups are likely to access very different parts of the index and the table data, leading to more disk seeks and cache misses.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;why-numeric-sequential-ids-are-better&quot;&gt;Why Numeric, Sequential IDs are Better:&lt;&#x2F;h3&gt;
&lt;p&gt;Numeric IDs, especially when generated in a roughly sequential manner (like our Snowflake-like approach), offer substantial advantages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast Comparisons:&lt;&#x2F;strong&gt; Databases can compare numbers extremely quickly.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Smaller Indexes:&lt;&#x2F;strong&gt; Numeric IDs (e.g., 64-bit integers) take up less space than long, random strings, resulting in smaller, faster indexes.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Fragmentation:&lt;&#x2F;strong&gt; Sequential IDs cause new rows to be inserted at the end of the B-tree index, minimizing fragmentation and improving write performance.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Improved Locality of Reference:&lt;&#x2F;strong&gt; Sequential IDs tend to be clustered together in the index and on disk. This improves cache utilization and reduces disk seeks, speeding up both reads and writes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;database-internals-b-trees-simplified&quot;&gt;Database Internals: B-Trees (Simplified)&lt;&#x2F;h3&gt;
&lt;p&gt;Most relational databases (MySQL, PostgreSQL, etc.) use B-trees (or variants like B+trees) to implement indexes. Here’s a simplified explanation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Structure:&lt;&#x2F;strong&gt; A B-tree is a self-balancing tree data structure.  Data is kept sorted, and searches, insertions, and deletions can be performed in logarithmic time (O(log n)).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nodes:&lt;&#x2F;strong&gt; Each node in the B-tree contains multiple &lt;em&gt;keys&lt;&#x2F;em&gt; (in our case, the &lt;code&gt;internal_id&lt;&#x2F;code&gt; values) and &lt;em&gt;pointers&lt;&#x2F;em&gt; to child nodes.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Searching:&lt;&#x2F;strong&gt; To find a specific ID, the database:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Starts at the root node.&lt;&#x2F;li&gt;
&lt;li&gt;Compares the target ID with the keys in the node.&lt;&#x2F;li&gt;
&lt;li&gt;Follows the appropriate pointer to a child node.&lt;&#x2F;li&gt;
&lt;li&gt;Repeats this process until it finds the ID or determines it doesn’t exist.  Because the keys are sorted &lt;em&gt;within each node&lt;&#x2F;em&gt;, the database can very efficiently narrow down the search.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Insertions:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sequential IDs:&lt;&#x2F;strong&gt; New keys are usually added to the &lt;em&gt;rightmost&lt;&#x2F;em&gt; leaf node of the B-tree. This is very efficient.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Random Strings:&lt;&#x2F;strong&gt; The new key could need to be inserted &lt;em&gt;anywhere&lt;&#x2F;em&gt; in the B-tree. This might require splitting nodes (if a node is full), leading to multiple write operations and fragmentation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;&#x2F;strong&gt; The Time complexity for searching using the &lt;code&gt;internal_id&lt;&#x2F;code&gt; which is primary key, will be &lt;strong&gt;O(log n)&lt;&#x2F;strong&gt;. Where ‘n’ is the number of rows in your table. And, If we had chosen a string-based ID, and even if that string column were indexed, the search complexity &lt;em&gt;within the index itself&lt;&#x2F;em&gt; would still involve string comparisons, which are slower than integer comparisons. The complexity would still be logarithmic (O(log n)) in terms of the number of index nodes accessed, &lt;em&gt;but&lt;&#x2F;em&gt; each node comparison would take longer. And, if your are quering on non-indexed string column then it will be &lt;strong&gt;O(n*m)&lt;&#x2F;strong&gt;, Where ‘n’ is the number of rows, and ‘m’ is the average length of your string ID.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;method-generateinternalid-int-shardid&quot;&gt;Method: &lt;code&gt;generateInternalId(int shardId)&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;generateInternalId&lt;&#x2F;code&gt; method creates unique IDs without relying on a central coordinating service (like a database auto-increment).  It achieves this by combining a timestamp, a shard ID, and a sequence number into a single 64-bit integer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;id-structure&quot;&gt;ID Structure&lt;&#x2F;h3&gt;
&lt;p&gt;The generated ID is a 64-bit long integer, structured as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-------------------------------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|    Timestamp (41 bits)   |   ShardID(10) |   Sequence(12)   |      extra bit        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------+---------------+------------------+-----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|            63            |      22       |        12        |  0  (Bit positions)   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-------------------------------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Timestamp (41 bits):&lt;&#x2F;strong&gt;  Represents the number of milliseconds since a custom &lt;em&gt;epoch&lt;&#x2F;em&gt;.  The epoch in this implementation is &lt;code&gt;2023-01-01 00:00:00 UTC&lt;&#x2F;code&gt; (defined by the &lt;code&gt;epoch&lt;&#x2F;code&gt; variable).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Calculation:&lt;&#x2F;strong&gt; &lt;code&gt;System.currentTimeMillis() - epoch&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Capacity:&lt;&#x2F;strong&gt; 41 bits allow for 2&lt;sup&gt;41&lt;&#x2F;sup&gt; milliseconds, which is approximately 69.7 years:
&lt;ul&gt;
&lt;li&gt;2&lt;sup&gt;41&lt;&#x2F;sup&gt; milliseconds = 2,199,023,255,552 milliseconds&lt;&#x2F;li&gt;
&lt;li&gt;2,199,023,255,552 ms &#x2F; 1000 ms&#x2F;s &#x2F; 60 s&#x2F;min &#x2F; 60 min&#x2F;hr &#x2F; 24 hr&#x2F;day &#x2F; 365 days&#x2F;year ≈ 69.7 years&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lifespan:&lt;&#x2F;strong&gt;  The system can generate unique IDs for about 69.7 years. After this, the timestamp would wrap around, potentially causing ID collisions.  To prevent this, you’d need a strategy like re-sharding with a new epoch or implementing collision detection (not done in this simplified version).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Shard ID (10 bits):&lt;&#x2F;strong&gt; Identifies the specific database shard or application instance that generated the ID.  This is &lt;em&gt;essential&lt;&#x2F;em&gt; for distributed systems.  10 bits allow for 2&lt;sup&gt;10&lt;&#x2F;sup&gt; = 1024 unique shard IDs.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sequence Number (12 bits):&lt;&#x2F;strong&gt; A counter that increments for each ID generated within the &lt;em&gt;same millisecond&lt;&#x2F;em&gt; on the &lt;em&gt;same shard&lt;&#x2F;em&gt;. 12 bits allow for 2&lt;sup&gt;12&lt;&#x2F;sup&gt; = 4096 unique sequence numbers per millisecond per shard. This handles situations where many IDs are generated very quickly.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Atomic Increment:&lt;&#x2F;strong&gt;  &lt;code&gt;sequence.getAndIncrement()&lt;&#x2F;code&gt; ensures the sequence number is incremented atomically, preventing race conditions in a multi-threaded environment.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Bitwise AND (&lt;code&gt;&amp;amp; 0xFFF&lt;&#x2F;code&gt;):&lt;&#x2F;strong&gt; Keeps the sequence number within the 12-bit range (0-4095). &lt;code&gt;0xFFF&lt;&#x2F;code&gt; is the hexadecimal representation of 4095 (binary &lt;code&gt;111111111111&lt;&#x2F;code&gt;). The bitwise AND effectively masks all but the last 12 bits.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;bitwise-operations&quot;&gt;Bitwise Operations&lt;&#x2F;h3&gt;
&lt;p&gt;The code uses bitwise operations to combine the timestamp, shard ID, and sequence number:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Left Shift (&lt;code&gt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt;)&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;timestamp &amp;lt;&amp;lt; 22&lt;&#x2F;code&gt;:  Shifts the timestamp 22 bits to the left.  This creates 22 empty bits (filled with zeros) on the right-hand side.  These bits are reserved for the shard ID (10 bits) and sequence number (12 bits).  Left shifting by &lt;em&gt;n&lt;&#x2F;em&gt; bits is equivalent to multiplying by 2&lt;sup&gt;&lt;em&gt;n&lt;&#x2F;em&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Timestamp (binary, simplified): 1001...00100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Timestamp &amp;lt;&amp;lt; 22:                1001...00100000000000000000000000000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;shardId &amp;lt;&amp;lt; 12&lt;&#x2F;code&gt;: Shifts the shard ID 12 bits to the left, creating 12 empty bits on the right for the sequence number (multiplying by 2&lt;sup&gt;12&lt;&#x2F;sup&gt;).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Shard ID (binary): 0000000101&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Shard ID &amp;lt;&amp;lt; 12:    0000000101000000000000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bitwise OR (&lt;code&gt;|&lt;&#x2F;code&gt;)&lt;&#x2F;strong&gt;: Combines the shifted timestamp, shifted shard ID, and sequence number.  Because the left shifts created non-overlapping sections, the bitwise OR effectively concatenates the three values.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------------------------------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|       (timestamp &amp;lt;&amp;lt; 22)               |       (shardId &amp;lt;&amp;lt; 12)    | sequenceNumber  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+---------------------------------------+--------------------------+-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  1001...0010000000000000000000000000  |  0000000101000000000000  | 000001111011    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------------------------------------------------------------------------------------+ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Resulting 64-bit ID: 1001…001000000000101000001111011&lt;&#x2F;p&gt;
&lt;h3 id=&quot;visual-representation&quot;&gt;Visual Representation&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|                                         ID (64 bits)                                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------------------------------------------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|      Timestamp (41 bits)        |      Shard ID (10 bits)     |    Seq (12 bits)     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+---------------------------------+-----------------------------+----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 10010011...00100000000000       |          0000000101         |      000001111011    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+---------------------------------+-----------------------------+----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;example&quot;&gt;Example&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s say:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Current time: &lt;code&gt;2024-03-01 10:30:15.500 UTC&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Epoch: &lt;code&gt;2023-01-01 00:00:00.000 UTC&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Shard ID: &lt;code&gt;5&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Sequence: &lt;code&gt;123&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Timestamp:&lt;&#x2F;strong&gt; 39,486,615,500 milliseconds (difference between current time and epoch).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Binary Representations (simplified):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Timestamp: &lt;code&gt;10010011111000000110000110101100000100100&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Shard ID: &lt;code&gt;0000000101&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Sequence Number: &lt;code&gt;000001111011&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bitwise Operations:&lt;&#x2F;strong&gt; The code performs the shifts and OR as described above, resulting in the final 64-bit ID.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;code&quot;&gt;Code&lt;&#x2F;h3&gt;
&lt;p&gt;Here is the &lt;code&gt;java&lt;&#x2F;code&gt; implementation of the above explanation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; final&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; epoch&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1672531200000L&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; final&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; AtomicInteger&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sequence&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; AtomicInteger&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; synchronized&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; generateInternalId&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; shardId&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        long&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; System&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;currentTimeMillis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; epoch&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sequenceNumber&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sequence&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getAndIncrement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0xFFF&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;timestamp &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;shardId &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt; sequenceNumber&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Also i have used this in one of my personal project &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;siddharth1729&#x2F;clik.git&quot;&gt;Url Shortener&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;shardId&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt;  The ID of the database shard (an integer between 0 and 1023, inclusive).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Return Type&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; The generated 64-bit unique internal ID.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;important-considerations&quot;&gt;Important Considerations&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sequence Overflow:&lt;&#x2F;strong&gt; This code &lt;em&gt;does not&lt;&#x2F;em&gt; handle the case where more than 4096 IDs are generated within the same millisecond on the same shard.  In a production system, you &lt;em&gt;must&lt;&#x2F;em&gt; address this (e.g., by waiting for the next millisecond, throwing an exception, or using a larger sequence number space).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Clock Drift&#x2F;Jump:&lt;&#x2F;strong&gt;  This code &lt;em&gt;does not&lt;&#x2F;em&gt; handle system clock changes (clock drift or NTP adjustments).  Clock changes can cause the timestamp to go backward, potentially leading to duplicate IDs.  A production system &lt;em&gt;must&lt;&#x2F;em&gt; handle this (e.g., by tracking the last generated timestamp and waiting or throwing an exception if the clock moves backward).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Shard ID Assignment:&lt;&#x2F;strong&gt; You need a robust mechanism to assign shard IDs and to determine the shard ID for a given operation. Consistent hashing is a common approach.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This detailed explanation should cover all aspects of the &lt;code&gt;generateInternalId&lt;&#x2F;code&gt; method and the Snowflake-like ID generation strategy.  Remember to use the more robust version of this method (with clock drift and sequence overflow handling) in a production environment.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;If you like the post please connect me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;LinkedIn&lt;&#x2F;a&gt;
And &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Simple Github Report Generator</title>
        <published>2025-02-25T00:00:00+00:00</published>
        <updated>2025-02-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/projects/github-report-generator/"/>
        <id>https://siddharthsabron.in/projects/github-report-generator/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/projects/github-report-generator/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;As working in an early stage startup we(software enginners) have to work on multiple repositories and we baerly maintain log of our work in short what
all we have worked on and what all we have done.&lt;&#x2F;p&gt;
&lt;p&gt;I have faced this problem and have been searching for a tool which can help me to generate a report of my github commits activity and how much i have worked on it.&lt;&#x2F;p&gt;
&lt;p&gt;So i have decided to build a tool which can help me to generate a report of my github commits activity and how much i have worked on it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;p&gt;This tool offers a range of features to help you analyze and visualize your GitHub commits activity. These include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Comprehensive Commit Activity Report&lt;&#x2F;strong&gt;: Get a detailed report of your GitHub commits activity.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Date Range Filtering&lt;&#x2F;strong&gt;: Filter your commits activity by a specific date range to understand your progress over time.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Commit Message Insights&lt;&#x2F;strong&gt;: Gain insights into your commits activity based on commit messages to understand the context behind your work.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The tool generates two types of reports:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;report.pdf&lt;&#x2F;strong&gt;: A professionally formatted PDF report that includes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Developer details&lt;&#x2F;li&gt;
&lt;li&gt;Commit summaries&lt;&#x2F;li&gt;
&lt;li&gt;Repository statistics&lt;&#x2F;li&gt;
&lt;li&gt;Detailed commit logs&lt;&#x2F;li&gt;
&lt;li&gt;Color-coded tables for easy analysis&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;report.txt&lt;&#x2F;strong&gt;: A plain text version of the same report, ideal for quick reference or integration with other tools.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;a-preview-of-the-report&quot;&gt;A preview of the report:&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;siddharth1729&#x2F;github_report_generator&#x2F;main&#x2F;img.png&quot; alt=&quot;Github Report Generator&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here is the link to the repository: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;siddharth1729&#x2F;github_report_generator.git&quot;&gt;Github Report Generator&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;If you like the post please connect me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;LinkedIn&lt;&#x2F;a&gt;
Follow me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Linux Kernel Memory Barriers: A Deep Dive</title>
        <published>2024-11-16T00:00:00+00:00</published>
        <updated>2024-11-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/blog/linux-kernel-memory-barriers/"/>
        <id>https://siddharthsabron.in/blog/linux-kernel-memory-barriers/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/blog/linux-kernel-memory-barriers/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1739627126042-0f9666a483b1?q=80&amp;amp;w=3174&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.0.3&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;Kovalam Beach, Kerela clicked by siddharth sabron&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Kovalam Beach, Kerela&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;QC2PLjFB1O4&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linux-kernel-memory-barriers-a-deep-dive&quot;&gt;Linux Kernel Memory Barriers: A Deep Dive&lt;&#x2F;h3&gt;
&lt;p&gt;This blog post delves into the intricate world of memory barriers within the Linux kernel. It aims to provide a practical guide for understanding and using these crucial synchronization primitives. While not an exhaustive specification, it outlines the fundamental guarantees offered by different barrier types and illustrates their application in various scenarios.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;abstract-memory-access-model&quot;&gt;Abstract Memory Access Model&lt;&#x2F;h3&gt;
&lt;p&gt;Modern computer systems employ complex optimizations involving reordering, deferral, and combination of memory operations. These optimizations, while beneficial for single-threaded performance, can introduce subtle bugs in concurrent programs. To understand why, consider a simplified model:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-------+   :   +--------+   :   +-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|       |   :   |        |   :   |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| CPU 1 |&amp;lt;-----&amp;gt;| Memory |&amp;lt;-----&amp;gt;| CPU 2 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|       |   :   |        |   :   |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-------+   :   +--------+   :   +-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ^       :       ^        :       ^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |       :       |        :       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------&amp;gt;| Device |&amp;lt;----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:   |        |   :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:   +--------+   :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each CPU operates independently, issuing memory operations that eventually become visible to other components. However, the order in which these operations are perceived by other CPUs or devices might not match the program order due to the aforementioned optimizations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-are-memory-barriers&quot;&gt;What are Memory Barriers?&lt;&#x2F;h3&gt;
&lt;p&gt;Memory barriers are instructions that impose partial ordering on memory operations. They act as fences, restricting the CPU and compiler from freely reordering accesses across the barrier. There are several types:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Write (Store) Barriers:&lt;&#x2F;strong&gt; Ensure that stores before the barrier are visible to other components before stores after the barrier.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Read (Load) Barriers:&lt;&#x2F;strong&gt; Ensure that loads before the barrier are performed before loads after the barrier.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;General Memory Barriers:&lt;&#x2F;strong&gt; Combine the effects of both read and write barriers, guaranteeing ordering for all memory operations.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Acquire and Release Barriers:&lt;&#x2F;strong&gt; Act as one-way permeable barriers. Acquire ensures that subsequent operations are seen after the acquire by other components. Release ensures that preceding operations are seen before the release by other components.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;explicit-kernel-barriers&quot;&gt;Explicit Kernel Barriers&lt;&#x2F;h3&gt;
&lt;p&gt;The Linux kernel provides several explicit barrier primitives:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;barrier&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Compiler barrier only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;           &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Full memory barrier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;rmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;          &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Read memory barrier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;wmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;          &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Write memory barrier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;smp_mb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;       &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; SMP full memory barrier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;smp_rmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; SMP read memory barrier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;smp_wmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; SMP write memory barrier  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;practical-applications&quot;&gt;Practical Applications&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s look at a common scenario where memory barriers are crucial - implementing a lock-free ring buffer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; ring_buffer &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; write_index&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; read_index&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    void&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;BUFFER_SIZE&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; producer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; ring_buffer &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;rb&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; index &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; rb&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;write_index&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Ensure we read the indexes before writing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    smp_rmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    rb&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;index &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt; BUFFER_SIZE&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Ensure the data is written before updating the index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    smp_wmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    rb&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;write_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; index &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;consumer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; ring_buffer &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;rb&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; index &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; rb&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;read_index&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    void&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Ensure we read the indexes before reading data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    smp_rmb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; rb&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;index &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt; BUFFER_SIZE&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Ensure we read the data before updating the index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    smp_mb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    rb&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;read_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; index &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;best-practices&quot;&gt;Best Practices&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Always use the most appropriate barrier for your needs&lt;&#x2F;li&gt;
&lt;li&gt;Document why each barrier is necessary&lt;&#x2F;li&gt;
&lt;li&gt;Consider using higher-level synchronization primitives when possible&lt;&#x2F;li&gt;
&lt;li&gt;Be aware of implicit barriers in kernel APIs&lt;&#x2F;li&gt;
&lt;li&gt;Test thoroughly on different architectures&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;common-pitfalls&quot;&gt;Common Pitfalls&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Missing Barriers:&lt;&#x2F;strong&gt; The most common error is simply forgetting necessary barriers&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Over-synchronization:&lt;&#x2F;strong&gt; Using stronger barriers than necessary&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Relying on CPU-specific behavior:&lt;&#x2F;strong&gt; Code should work on the weakest memory model&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ignoring compiler reordering:&lt;&#x2F;strong&gt; Remember that both CPU and compiler reordering must be considered&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;Memory barriers are essential tools for kernel developers, but they must be used carefully and deliberately. Understanding their semantics and proper application is crucial for writing correct concurrent code in the Linux kernel.&lt;&#x2F;p&gt;
&lt;p&gt;Remember that while memory barriers are powerful tools, they should be used judiciously. When possible, prefer higher-level synchronization primitives that handle memory ordering automatically. Always document your use of memory barriers clearly, as their necessity might not be immediately obvious to other developers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;Documentation&#x2F;memory-barriers.txt&quot;&gt;Linux Kernel Documentation - Memory Barriers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;!-- ÷##################################### CARD SECTION ##################################### --&gt;
&lt;!-- &lt;div class=&quot;footer-section&quot; style=&quot;
  background: var(--nav-bg);
  border-radius: var(--rounded-corner);
  box-shadow: var(--shadow);
  padding: 2rem;
  margin: 2rem 0;
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
&quot;&gt;
  &lt;h3 style=&quot;
    text-align: center;
    color: var(--fg-color);
    margin-bottom: 1.5rem;
    font-size: 1.8rem;
    margin-top: 1rem;
  &quot;&gt;✨ Thanks for reading! ✨&lt;&#x2F;h3&gt;
  
  &lt;div class=&quot;reader-message&quot; style=&quot;
    background: var(--fg05);
    padding: 1rem;
    border-radius: var(--rounded-corner-small);
    margin-bottom: 2rem;
  &quot;&gt;
    &lt;p style=&quot;
      text-align: center;
      margin: 0;
      color: var(--fg-color);
    &quot;&gt;
      If you enjoyed this article, consider following me on various platforms&lt;br&gt;
      &lt;em style=&quot;color: var(--fg60);&quot;&gt;You&#x27;d be surprised to know that 90% of my readers don&#x27;t! 😩&lt;&#x2F;em&gt;
    &lt;&#x2F;p&gt;
  &lt;&#x2F;div&gt;

  &lt;div class=&quot;social-links&quot; style=&quot;
    margin-bottom: 1.5rem;
    padding: 1rem;
    background: var(--fg05);
    border-radius: var(--rounded-corner-small);
  &quot;&gt;
    &lt;h4 style=&quot;color: var(--fg-color); margin-bottom: 1rem;margin-top: 1rem;&quot;&gt;🌟 Follow Along&lt;&#x2F;h4&gt;
    &lt;ul style=&quot;
      list-style: none;
      padding: 0;
      margin: 0;
    &quot;&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;🐦 &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;Twitter&lt;&#x2F;a&gt; - Tech insights and updates&lt;&#x2F;li&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;💼 &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;LinkedIn&lt;&#x2F;a&gt; - Professional connections&lt;&#x2F;li&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;🚀 &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;siddharth1729&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;GitHub&lt;&#x2F;a&gt; - Check out my code&lt;&#x2F;li&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;📝 &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@siddharth.sabron&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;Medium&lt;&#x2F;a&gt; - More technical articles&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;div&gt;

  &lt;div class=&quot;featured-articles&quot; style=&quot;
    margin-bottom: 1.5rem;
    padding: 1rem;
    background: var(--fg05);
    border-radius: var(--rounded-corner-small);
  &quot;&gt;
    &lt;h4 style=&quot;color: var(--fg-color); margin-bottom: 1rem;margin-top: 1rem;&quot;&gt;📚 Popular Articles&lt;&#x2F;h4&gt;
    &lt;ul style=&quot;
      list-style: none;
      padding: 0;
      margin: 0;
    &quot;&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;💾 &lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;discord&#x2F;&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;What caused Discord to switch from Go to Rust?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;🦀 &lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;How Discord Used Rust to Scale Elixir to Millions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;div&gt;

  &lt;div class=&quot;connect-section&quot; style=&quot;
    margin-bottom: 1.5rem;
    padding: 1rem;
    background: var(--fg05);
    border-radius: var(--rounded-corner-small);
  &quot;&gt;
    &lt;h4 style=&quot;color: var(--fg-color); margin-bottom: 1rem; margin-top: 1rem;&quot;&gt;🤝 Connect With Me&lt;&#x2F;h4&gt;
    &lt;ul style=&quot;
      list-style: none;
      padding: 0;
      margin: 0;
    &quot;&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;🌐 &lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;Portfolio&lt;&#x2F;a&gt; - Learn more about my work&lt;&#x2F;li&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;📧 &lt;a href=&quot;mailto:siddharth.sabron@gmail.com&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;Email&lt;&#x2F;a&gt; - Let&#x27;s chat!&lt;&#x2F;li&gt;
      &lt;li style=&quot;margin-bottom: 0.5rem;&quot;&gt;💬 &lt;a href=&quot;https:&#x2F;&#x2F;discord.com&#x2F;users&#x2F;596025752776998912&quot; style=&quot;color: var(--primary-color); text-decoration: none;&quot;&gt;Discord&lt;&#x2F;a&gt; - Direct discussions&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;div&gt;

  &lt;div class=&quot;closing-message&quot; style=&quot;
    text-align: center;
    padding: 1rem;
    background: var(--fg05);
    border-radius: var(--rounded-corner-small);
    margin-top: 1.5rem;
  &quot;&gt;
    &lt;p style=&quot;
      margin: 0;
      color: var(--fg-color);
    &quot;&gt;
      &lt;em&gt;If you found this helpful, please consider sharing it with others! 🙏&lt;&#x2F;em&gt;
    &lt;&#x2F;p&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt; --&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Designing a Scalable OCPP server</title>
        <published>2024-05-12T00:00:00+00:00</published>
        <updated>2024-05-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/blog/ocpp-server/"/>
        <id>https://siddharthsabron.in/blog/ocpp-server/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/blog/ocpp-server/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;miro.medium.com&#x2F;v2&#x2F;resize:fit:828&#x2F;format:webp&#x2F;0*jRwMVcLt1G-NRYFo.png&quot; alt=&quot;ocpp&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-ocpp&quot;&gt;What is OCPP?&lt;&#x2F;h2&gt;
&lt;p&gt;OCPP, short for Open Charge Point Protocol, is like the universal language of EV charging. It sets the standard for how charging stations talk to central systems, enabling functions like monitoring, management, billing, and even integration with third-party systems. This open-source protocol isn’t just a buzzword — it’s backed by a robust community of vendors and manufacturers, making it a widely adopted and trusted solution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-ocpp-works&quot;&gt;How OCPP Works&lt;&#x2F;h2&gt;
&lt;p&gt;At its core, OCPP operates through two main components: the protocol itself and its profiles. The protocol defines the communication rules between charge points and central servers, while profiles determine what data gets exchanged. Picture this: a driver plugs in their EV at a charging station. OCPP kicks into action, transferring driver details to the central server for authentication and initiating the charging process. Simultaneously, the station communicates key data like energy usage and status back to the central system for billing and maintenance purposes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chargers&quot;&gt;Chargers&lt;&#x2F;h2&gt;
&lt;p&gt;Chargers communicate with the OCPP or CMS server using the same OCPP protocol. They are equipped with small hardware, similar to a Raspberry Pi, where firmware code is written. This code is responsible for monitoring and transferring data about specific charging sessions to the OCPP server. Additionally, it accepts commands such as startTransaction and stopTransaction from the standard OCPP server to initiate a charging session.&lt;&#x2F;p&gt;
&lt;p&gt;Chargers also communicate with the Battery Management System (BMS) of electric vehicles (EVs) using the ISO 15118–2 digital communication protocol can see in fig 1.1, which implements various features. This protocol facilitates seamless communication between the charger and the EV’s BMS, ensuring efficient and coordinated charging processes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;security concept including encryption, signing, key management, etc.&lt;&#x2F;li&gt;
&lt;li&gt;robust PLC-based communications&lt;&#x2F;li&gt;
&lt;li&gt;automatic address assigning and association&lt;&#x2F;li&gt;
&lt;li&gt;IPv6-based communications&lt;&#x2F;li&gt;
&lt;li&gt;compressed XML messages&lt;&#x2F;li&gt;
&lt;li&gt;client-server approach&lt;&#x2F;li&gt;
&lt;li&gt;safety concept including cable check, welding detection, etc&lt;&#x2F;li&gt;
&lt;li&gt;extension concept for added-value services&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;miro.medium.com&#x2F;v2&#x2F;resize:fit:828&#x2F;format:webp&#x2F;1*T6zal2KQRFuxsaEAdnLICw.png&quot; alt=&quot;ISO 15118–2 Protocol&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-tradeoff&quot;&gt;Design Tradeoff&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we both have established some foundational concepts and are on the same page, let’s delve into the implementation aspect from a - software engineering perspective. To build an OCPP server, we need to consider various factors.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, we should brainstorm about the implementation details, such as choosing the appropriate design pattern — whether to opt for a client-server model, an event-driven architecture, or a stateless or stateful approach. Additionally, we need to decide on the programming language, protocol (e.g., HTTPS, WebRTC, WebSocket, or a queue-based implementation), and database technology. These choices will shape the robustness, scalability, and efficiency of our OCPP server.&lt;&#x2F;p&gt;
&lt;p&gt;Before diving into implementation specifics, let’s consider a scenario. To initiate a charging session, a user triggers a command from the app, which sends a request to the OCPP server. The OCPP server then establishes communication with the charger, instructing it to begin the charging session.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;client-server&quot;&gt;Client-server&lt;&#x2F;h2&gt;
&lt;p&gt;Now, let’s visualize how your system might look if you opt for a client-server model:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Start charger from user&lt;&#x2F;li&gt;
&lt;li&gt;charger started from charger&lt;&#x2F;li&gt;
&lt;li&gt;state of charging session from user evry 1 or 2 sec&lt;&#x2F;li&gt;
&lt;li&gt;end of chrging from user&lt;&#x2F;li&gt;
&lt;li&gt;session ended fron charger&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Roughly 5 http connection and state of chrging session csn be varry but lets fix this for 50(anyhow you going to chrge your veichle more than 50second). Starting the charger from the user’s end, the charger begins charging from its side. The charging session’s state is updated from the user’s end every 1 or 2 seconds. When the charging is complete, the user ends the session, and the session is ended from the charger’s side as well.&lt;&#x2F;p&gt;
&lt;p&gt;However, using this model can lead to several drawbacks and overheads, especially due to the multiple HTTPS calls involved. Here are some potential issues:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;increased-cost&quot;&gt;Increased Cost&lt;&#x2F;h3&gt;
&lt;p&gt;Each HTTPS call incurs a cost, especially if using external services or APIs. With roughly 50 HTTP connections per session, this cost can add up significantly over time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;http-header-overhead-and-handshaking&quot;&gt;HTTP Header Overhead and Handshaking&lt;&#x2F;h3&gt;
&lt;p&gt;Each HTTP request and response involves the exchange of headers, which contain metadata about the request and response. This header overhead can become significant, especially when multiple HTTP connections are made within a short period. Additionally, establishing a new connection for each HTTP request requires the overhead of handshaking, where the client and server negotiate parameters and establish the connection. Even when the client and server remain the same, this repeated handshaking process adds to the overall latency and resource consumption, impacting the speed and efficiency of the charging process. Implementing strategies like connection pooling, persistent connections, or using protocols optimized for low overhead, such as WebSocket, can help alleviate these issues and improve performance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;impact-on-latency-and-speed&quot;&gt;Impact on Latency and Speed&lt;&#x2F;h3&gt;
&lt;p&gt;Multiple HTTPS calls introduce latency and can slow down the overall charging process. This delay can be noticeable, especially in scenarios where rapid responses are required, such as managing real-time charging sessions or handling high volumes of transactions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;complexity-in-management&quot;&gt;Complexity in Management&lt;&#x2F;h3&gt;
&lt;p&gt;Managing and coordinating multiple HTTPS calls can add complexity to the system architecture. It requires robust error handling, retries, and monitoring mechanisms to ensure smooth operation and reliability.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;resource-utilization&quot;&gt;Resource Utilization&lt;&#x2F;h3&gt;
&lt;p&gt;Each HTTPS call consumes resources, including network bandwidth, server processing power, and memory. In situations with a large number of concurrent sessions, this can strain the system and impact overall performance.&lt;&#x2F;p&gt;
&lt;p&gt;To mitigate these drawbacks, optimizing the HTTPS calls, implementing caching mechanisms, reducing unnecessary data transfers, and considering alternative communication protocols or optimizations can help improve efficiency and reduce overhead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;statefull-system&quot;&gt;Statefull system&lt;&#x2F;h2&gt;
&lt;p&gt;In the previous model, we encountered challenges due to the repeated use of HTTP connections, which led to costly handshaking mechanisms and increased header lengths. However, let’s consider a more efficient approach using an event-driven and stateful system, leveraging the benefits of WebSocket technology.&lt;&#x2F;p&gt;
&lt;p&gt;In this optimized model, we acknowledge that our OCPP server and charger remain the same entities throughout the process. By adopting a stateful system, we can persist the connection between the client (user or charger) and the server (OCPP server). This persistence eliminates the need for frequent handshakes and reduces the overhead caused by lengthy headers.&lt;&#x2F;p&gt;
&lt;p&gt;Now, let’s talk about using&lt;&#x2F;p&gt;
&lt;h2 id=&quot;websocket&quot;&gt;WebSocket&lt;&#x2F;h2&gt;
&lt;p&gt;WebSocket’s duplex mechanism allows for simultaneous data transfer from both ends over a single connection. This bidirectional communication capability is crucial for real-time updates and efficient interaction between the user and the server.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;latency-and-speed&quot;&gt;Latency and Speed&lt;&#x2F;h3&gt;
&lt;p&gt;By maintaining a persistent connection, WebSocket significantly reduces latency compared to traditional HTTP connections. The elimination of repeated handshaking and header overhead results in faster data transmission, enhancing the overall speed and responsiveness of the charging process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fewer-connections&quot;&gt;Fewer Connections&lt;&#x2F;h3&gt;
&lt;p&gt;WebSocket’s persistent nature means fewer connection establishment overheads. Unlike HTTP, where each request requires a new connection and handshake, WebSocket maintains a continuous connection, leading to fewer resources consumed and improved efficiency.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;technical-details&quot;&gt;Technical Details&lt;&#x2F;h3&gt;
&lt;p&gt;WebSocket operates over TCP, providing a reliable and full-duplex communication channel. It uses a lightweight protocol that minimizes overhead, making it ideal for real-time applications like EV charging management. WebSocket’s support for binary data transmission and built-in error handling further enhances its suitability for handling EV charging sessions seamlessly.&lt;&#x2F;p&gt;
&lt;p&gt;By using WebSocket within an event-driven and stateful architecture, we can optimize the communication between the charger, user, and OCPP server. This approach not only reduces overhead and latency but also ensures a smoother and more responsive charging experience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choosing-database&quot;&gt;Choosing Database&lt;&#x2F;h2&gt;
&lt;p&gt;Choosing a scalable database like ScyllaDB for a real-time EV charging management system with WebSocket technology offers several advantages:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;real-time-performance&quot;&gt;Real-Time Performance&lt;&#x2F;h3&gt;
&lt;p&gt;ScyllaDB’s high-throughput and low-latency capabilities make it ideal for handling real-time data streams and rapid updates in an event-driven system.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;horizontal-scalability&quot;&gt;Horizontal Scalability&lt;&#x2F;h3&gt;
&lt;p&gt;ScyllaDB’s distributed architecture allows for seamless horizontal scaling by adding more nodes, ensuring the system can accommodate growing data volumes and user traffic.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;flexible-schema&quot;&gt;Flexible Schema&lt;&#x2F;h3&gt;
&lt;p&gt;With support for flexible schemas, ScyllaDB enables easy adaptation to evolving data structures and simplifies integration with WebSocket-based real-time data streams.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;high-availability&quot;&gt;High Availability&lt;&#x2F;h3&gt;
&lt;p&gt;ScyllaDB’s fault-tolerant design and automatic sharding ensure high availability and reliability, crucial for mission-critical applications like EV charging management.&lt;&#x2F;p&gt;
&lt;p&gt;In summary, ScyllaDB provides the performance, scalability, flexibility, and reliability needed for a modern, real-time EV charging system utilizing WebSocket technology.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;system-design&quot;&gt;System Design&lt;&#x2F;h2&gt;
&lt;p&gt;Designing a Detailed System Architecture for Real-Time EV Charging Management&lt;&#x2F;p&gt;
&lt;h3 id=&quot;websocket-communication-layer&quot;&gt;WebSocket Communication Layer&lt;&#x2F;h3&gt;
&lt;p&gt;Implement WebSocket protocol for real-time bidirectional communication between EV chargers, users, and the OCPP server.
Use WebSocket libraries and frameworks like Socket.IO for efficient WebSocket management and event handling.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;scylladb-for-data-storage&quot;&gt;ScyllaDB for Data Storage&lt;&#x2F;h3&gt;
&lt;p&gt;Utilize ScyllaDB as the primary database for storing real-time charging session data, user information, and system configurations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;redis-for-scaling-and-caching&quot;&gt;Redis for Scaling and Caching&lt;&#x2F;h3&gt;
&lt;p&gt;Integrate Redis as a caching layer for scaling WebSocket connections and maintaining session states. Use Redis Pub&#x2F;Sub for real-time       notifications and event broadcasting to connected clients&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stateful-api-gateway&quot;&gt;Stateful API Gateway&lt;&#x2F;h3&gt;
&lt;p&gt;Design a stateful API gateway using Redis to manage session states, authenticate users, and handle API requests. Utilize Redis data structures like Hashes and Sets for storing session information, user tokens, and access control lists (ACLs).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kafka-for-event-processing&quot;&gt;Kafka for Event Processing&lt;&#x2F;h3&gt;
&lt;p&gt;Integrate Kafka as a message broker for handling high-throughput event streams and data processing. Use Kafka topics for event-driven architecture, allowing components to publish and subscribe to relevant events.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;microservices-architecture&quot;&gt;Microservices Architecture&lt;&#x2F;h3&gt;
&lt;p&gt;Design the system using a microservices architecture for modularity, scalability, and fault isolation.
Create microservices for user management, charging session control, billing, monitoring, and analytics, each interacting through Kafka and Redis for data synchronization and event-driven communication.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;load-balancing-and-auto-scaling&quot;&gt;Load Balancing and Auto-Scaling&lt;&#x2F;h3&gt;
&lt;p&gt;Implement load balancing using Nginx or a similar tool to distribute WebSocket connections and API requests across multiple servers.
Configure auto-scaling policies based on metrics like CPU utilization, WebSocket connection count, and API request rate to dynamically adjust resource allocation and handle traffic spikes efficiently.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;miro.medium.com&#x2F;v2&#x2F;resize:fit:828&#x2F;format:webp&#x2F;1*2AWAq9xSzg5pZRxB4F6Yyw.png&quot; alt=&quot;kafka&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;current-architecture-design&quot;&gt;Current Architecture Design&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a clear understanding of our technology, tools, and architecture, let’s simulate the entire system using a straightforward example, step by step. Imagine planning a road trip from start to finish.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;starting-a-charging-session&quot;&gt;Starting a Charging Session&lt;&#x2F;h3&gt;
&lt;p&gt;The user initiates a charging session through the mobile app or web interface, sending a request to the OCPP server via HTTPS or WebSocket API endpoints.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ocpp-server-interaction&quot;&gt;OCPP Server Interaction&lt;&#x2F;h3&gt;
&lt;p&gt;Upon receiving the request, the OCPP server processes the command and verifies the user’s credentials and authorization for the charging session.
The OCPP server updates the charging session status in ScyllaDB, indicating that a new session is initiated and the user is authorized to charge.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;websocket-communication&quot;&gt;WebSocket Communication&lt;&#x2F;h3&gt;
&lt;p&gt;The OCPP server establishes a WebSocket connection with the designated charger identified for the session, using the persistent connection pool managed by Redis for efficient connection management.
Data related to the charging session, such as start command, charging parameters, and user authentication, is sent over the established WebSocket connection to the charger.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;charger-starts-the-session&quot;&gt;Charger Starts the Session&lt;&#x2F;h3&gt;
&lt;p&gt;The charger receives the data from the WebSocket connection and verifies the session details and authorization.
Upon successful validation, the charger starts the charging session, initiating the flow of electrical power to the EV.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;session-feedback-and-status-update&quot;&gt;Session Feedback and Status Update&lt;&#x2F;h3&gt;
&lt;p&gt;The charger sends real-time updates and feedback about the charging session, such as current charging rate, energy consumption, and battery status, back through the WebSocket connection to the OCPP server.
The OCPP server processes and updates the session status in ScyllaDB, continuously tracking and recording session data for monitoring and analytics purposes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;publishing-to-kafka&quot;&gt;Publishing to Kafka&lt;&#x2F;h3&gt;
&lt;p&gt;Key events and data updates related to the charging session, such as session start, stop, charging status changes, and energy consumption milestones, are published as messages to specific Kafka topics.
Kafka acts as a centralized message broker, ensuring reliable delivery of messages and providing durability and fault tolerance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;microservices-consumption&quot;&gt;Microservices Consumption&lt;&#x2F;h3&gt;
&lt;p&gt;Multiple microservices within the system architecture subscribe to relevant Kafka topics, consuming and processing the published messages.
For example, a billing microservice calculates and records charging costs based on energy consumption data received from Kafka messages.
Another monitoring microservice tracks charging session metrics and generates real-time alerts or notifications for system administrators or users&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Yes, this was it. It was all that I understood and my approach for such a system from a software engineer’s perspective.&lt;&#x2F;p&gt;
&lt;p&gt;Now, there are a lot of ways and tools you can use for building an EV charging infrastructure system that can be more scalable and robust.&lt;&#x2F;p&gt;
&lt;p&gt;My take on the EV industry from a software point of view is that it is still very immature. Many things designed or currently being developed are mostly from a hardware or business point of view, which is good. However, at the end of the day, you’re dealing with abstract software systems, which should be the prime focus of institutions.&lt;&#x2F;p&gt;
&lt;p&gt;There are very few experts who know the system from end to end, and even fewer who want to know. There is a scarcity of good blogs and reading materials, and the ones available are often not structured.&lt;&#x2F;p&gt;
&lt;p&gt;Also, I am developing an open-source OCPP server from scratch that anyone can use and build upon. It will take time, so stay tuned to my GitHub, which you can find [here](siddharth github). You can follow me on GitHub to track my progress.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;If you like the post please connect me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;LinkedIn&lt;&#x2F;a&gt;
Follow me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How Discord Used Rust to Scale Elixir to Millions</title>
        <published>2023-06-02T00:00:00+00:00</published>
        <updated>2023-06-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/blog/how-discord-scales-elixer/"/>
        <id>https://siddharthsabron.in/blog/how-discord-scales-elixer/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/blog/how-discord-scales-elixer/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1677353932592-b04b11c918db?q=80&amp;amp;w=2940&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.0.3&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;Scenic view of McLeodganj, Dharamshala, photographed by Siddharth Sabron&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Macloedganj Dharamshala&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;PUy1Un3lv28&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;table-of-content&quot;&gt;Table of Content&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#table-of-content&quot;&gt;Table of Content&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#introduction&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#the-problem-at-hand&quot;&gt;The Problem at Hand&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#exploring-potential-solutions&quot;&gt;Exploring Potential Solutions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#creating-a-unique-solution-skiplist&quot;&gt;Creating a Unique Solution: SkipList&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#refining-performance-dynamic-orderedset&quot;&gt;Refining Performance: Dynamic OrderedSet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#introducing-rust-boosting-performance&quot;&gt;Introducing Rust: Boosting Performance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#integrating-rust-with-elixir&quot;&gt;Integrating Rust with Elixir&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#benchmarking-the-rust-backed-sortedset&quot;&gt;Benchmarking the Rust-backed SortedSet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#achieving-optimal-performance-and-scalability&quot;&gt;Achieving Optimal Performance and Scalability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;how-discord-scales-elixer&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I love Discord’s backend team they are doing some amazing stuff at their product and this is just one of them, that how they used Rust to scale Elixir to gain 11 million concurrent users. Grab you Coffee or Tea and follow along.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;In the realm of software development, challenges often arise when dealing with large-scale data structures. Discord, a popular communication platform, faced one such challenge when optimizing its Member List feature. This blog explores the development process behind Discord’s SortedSet, a high-performance data structure, which allowed them to efficiently manage large sorted sets with fast mutation operations. Join us on this journey as we delve into the problem, explore various solutions, and ultimately discover how the power of Rust and Elixir combined to create an exceptional solution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-at-hand&quot;&gt;The Problem at Hand&lt;&#x2F;h2&gt;
&lt;p&gt;Discord’s Member List, which displays users on the platform, needed to be updated efficiently. However, constantly sending updates for the entire Member List resulted in unnecessary network traffic, CPU usage, and reduced battery life. To address this, Discord required a data structure capable of holding hundreds of thousands of entries, enabling fast mutation operations, and providing efficient indexing for additions and removals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;exploring-potential-solutions&quot;&gt;Exploring Potential Solutions&lt;&#x2F;h2&gt;
&lt;p&gt;Elixir, the language of choice for Discord’s core services, possesses immutable data structures. While ideal for concurrency and code reasoning, this immutability presented challenges when handling large-scale mutations. Discord’s engineers embarked on a quest to find a suitable data structure that met their requirements. The search began with Elixir’s built-in data structures, such as MapSet and List. However, MapSet lacked ordering guarantees, ruling it out as an option. Wrapping a List and enforcing uniqueness and sorting showed promising results for small lists but proved impractical for larger lists due to slow insertion times.Next, they explored Erlang’s ordsets (Ordered Sets). While ordsets performed well for smaller lists, they faced performance issues when handling larger lists, falling short of the desired speed requirements.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-a-unique-solution-skiplist&quot;&gt;Creating a Unique Solution: SkipList&lt;&#x2F;h2&gt;
&lt;p&gt;As existing options failed to meet the performance demands, Discord’s engineers decided to delve into the realm of custom data structure design. They conceived the idea of chaining multiple small ordsets together to quickly access the correct ordset when needed. This concept resembled a Skip List, which served as the inspiration for their implementation. The initial incarnation of the new data structure, dubbed OrderedSet, involved a wrapper around a list of Cells. Each Cell contained a small ordset along with the first and last items and a count. Leveraging compile-time guards, the OrderedSet achieved favorable performance in worst-case scenarios, significantly outperforming raw ordsets and naive List implementations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;refining-performance-dynamic-orderedset&quot;&gt;Refining Performance: Dynamic OrderedSet&lt;&#x2F;h2&gt;
&lt;p&gt;Although the initial implementation improved performance, it introduced a new worst-case scenario when inserting at the beginning of the list. To overcome this challenge, Discord’s engineers developed a more sophisticated approach. They allowed Cells to dynamically swell and split, inserting new Cells in the middle of the list. While slightly more expensive, this approach improved worst-case performance, as it required a Cell Split instead of numerous Cell operations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;introducing-rust-boosting-performance&quot;&gt;Introducing Rust: Boosting Performance&lt;&#x2F;h2&gt;
&lt;p&gt;Despite reaching impressive performance levels with Elixir, Discord sought to push the boundaries further. They turned to Rust, a systems programming language known for its zero-cost abstractions and mutable data structures. By leveraging Rust’s capabilities through NIFs (Native Implemented Functions), they aimed to achieve even greater performance gains.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integrating-rust-with-elixir&quot;&gt;Integrating Rust with Elixir&lt;&#x2F;h2&gt;
&lt;p&gt;Discord’s core services were primarily built in Elixir, making it essential to integrate Rust seamlessly into their existing Elixir-based infrastructure. Thanks to a remarkable Elixir project called Rustler, which facilitates safe and efficient Elixir-Rust interactions, Discord could create a well-behaved NIF. Rustler’s guarantees ensured that Rust would not crash the BEAM VM or leak memory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;benchmarking-the-rust-backed-sortedset&quot;&gt;Benchmarking the Rust-backed SortedSet&lt;&#x2F;h2&gt;
&lt;p&gt;The initial benchmarks of the Rust-backed SortedSet yielded extremely promising results. Adding an item to the set ranged from 0.4𝜇s to 2.85𝜇s, outperforming the previous OrderedSet implementation by a considerable margin. Discord expanded the benchmarking to include a wider range of Erlang Terms and functionality required for the Member List. The results were remarkable, with SortedSet demonstrating fast insertions across various set sizes, even with a million items.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;achieving-optimal-performance-and-scalability&quot;&gt;Achieving Optimal Performance and Scalability&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to the introduction of SortedSet, Discord witnessed significant performance improvements across all guilds on their platform, without any adverse effects on memory usage. The collaboration between Rust and Elixir proved that they could coexist effectively, with Elixir handling real-time communication logic and Rust providing exceptional performance when required.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Discord’s journey to optimize their Member List led to the development of SortedSet, a high-performance data structure combining the power of Rust and Elixir. By exploring various options and pushing the boundaries of data structure design, Discord achieved their goal of efficiently managing large sorted sets with fast mutation operations. With SortedSet as an open-source library, the Discord team has contributed a valuable resource to the wider software development community, demonstrating the possibilities when combining different programming languages and leveraging their unique strengths.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;If you like the post please connect me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;LinkedIn&lt;&#x2F;a&gt;
Follow me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Authentication Service in TypeScript and Clean Architecture</title>
        <published>2023-04-18T00:00:00+00:00</published>
        <updated>2023-04-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/projects/authentication-in-nodejs/"/>
        <id>https://siddharthsabron.in/projects/authentication-in-nodejs/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/projects/authentication-in-nodejs/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1749908511437-e7efd076aba1?q=80&amp;amp;w=3089&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;Wedding decoration photographed by Siddharth Sabron&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Weeding Decoration&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;fgkyZT3atk0&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This guide will walk you through the process of creating an authentication service in Node.js using TypeScript and clean architecture. The authentication service will allow users to sign up and log in to your application using email and password.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h2&gt;
&lt;p&gt;Before you begin, make sure you have the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js (v14 or higher)&lt;&#x2F;li&gt;
&lt;li&gt;npm or yarn&lt;&#x2F;li&gt;
&lt;li&gt;A text editor of your choice (e.g. VS Code)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;project-setup&quot;&gt;Project Setup&lt;&#x2F;h2&gt;
&lt;p&gt;To set up the project, follow these steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a new directory for your project.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Open the directory in your terminal or command prompt.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Initialize a new Node.js project using &lt;code&gt;npm init&lt;&#x2F;code&gt; or &lt;code&gt;yarn init&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Install the required dependencies:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;express&lt;&#x2F;code&gt; for building the server&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;jsonwebtoken&lt;&#x2F;code&gt; for generating and verifying JSON Web Tokens&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;bcrypt&lt;&#x2F;code&gt; for hashing and verifying passwords&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;dotenv&lt;&#x2F;code&gt; for managing environment variables&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;knex.js&lt;&#x2F;code&gt; for database management&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pg&lt;&#x2F;code&gt; or any other driver for the desired database engine&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;@types&#x2F;express&lt;&#x2F;code&gt;, &lt;code&gt;@types&#x2F;jsonwebtoken&lt;&#x2F;code&gt;, &lt;code&gt;@types&#x2F;bcrypt&lt;&#x2F;code&gt;, &lt;code&gt;@types&#x2F;dotenv&lt;&#x2F;code&gt; and &lt;code&gt;@types&#x2F;pg&lt;&#x2F;code&gt; for TypeScript support&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can install these dependencies using the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; express&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; jsonwebtoken&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bcrypt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dotenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; typeorm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reflect-metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pg&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @types&#x2F;express&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @types&#x2F;jsonwebtoken&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @types&#x2F;bcrypt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @types&#x2F;dotenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @types&#x2F;pg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other&quot;&gt;-save&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;src&lt;&#x2F;code&gt; directory for your source code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Inside the &lt;code&gt;src&lt;&#x2F;code&gt; directory, create a &lt;code&gt;server.ts&lt;&#x2F;code&gt; file for your server code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;clean-architecture-setup&quot;&gt;Clean Architecture Setup&lt;&#x2F;h2&gt;
&lt;p&gt;We will be using the Clean Architecture pattern to structure our code. The Clean Architecture is a software architecture that separates the code into layers with clear boundaries and dependencies pointing inwards. In this architecture, the core business logic is at the center of the architecture, surrounded by layers of less important details. The layers are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Entities: Domain models and business rules.&lt;&#x2F;li&gt;
&lt;li&gt;Use cases: Application-specific business rules.&lt;&#x2F;li&gt;
&lt;li&gt;Controllers: Handle requests and responses.&lt;&#x2F;li&gt;
&lt;li&gt;Repositories: Database and external interfaces.&lt;&#x2F;li&gt;
&lt;li&gt;Services: Manage external services like AWS S3, Twilio, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The following diagram illustrates the Clean Architecture layers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   Controllers  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|     Use Cases  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|    Entities    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  Repositories  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|    Services    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To set up the Clean Architecture, create the following directories inside the &lt;code&gt;src&lt;&#x2F;code&gt; directory:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;domain&lt;&#x2F;code&gt;: Contains the &lt;code&gt;User&lt;&#x2F;code&gt; entity and any business rules related to authentication.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;usecases&lt;&#x2F;code&gt;: Contains the use cases for authentication, such as &lt;code&gt;Signup&lt;&#x2F;code&gt; and &lt;code&gt;Login&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;interface&lt;&#x2F;code&gt;: Contains the Express.js server code and its associated controllers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;server-setup&quot;&gt;Server Setup&lt;&#x2F;h2&gt;
&lt;p&gt;Inside the &lt;code&gt;server.ts&lt;&#x2F;code&gt; file, you will need to create a new Express.js server, set up middleware for parsing JSON and handling CORS, and define routes for authentication. Here is an example of what your &lt;code&gt;server.ts&lt;&#x2F;code&gt; file might look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; express&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;express&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; bodyParser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;body-parser&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; App&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; readonly&lt;&#x2F;span&gt;&lt;span&gt; app&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; express&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  constructor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; express&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;registerRoutes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;startServer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; config&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;bodyParser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;urlencoded&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; extended&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;bodyParser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;json&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Initialize all the routes of the application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; registerRoutes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; void&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; express&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Router&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Server will listen to this port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; startServer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    try&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;      const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;      this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;process&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PORT&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;App listening on port ===&amp;gt; http:&#x2F;&#x2F;localhost:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;      console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Server could not be started&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;      process&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; default&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; App&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;entites&quot;&gt;Entites&lt;&#x2F;h2&gt;
&lt;p&gt;Entities are at the heart of the domain layer. They are the core objects that represent the business concepts of the application. Entities contain data and methods that are specific to the business domain and are independent of any particular application logic or technical implementation.&lt;&#x2F;p&gt;
&lt;p&gt;This interface defines the properties of a User entity, including its unique identifier, first and last name, email address, password, and timestamp for when it was created and last updated. The properties can be read or modified through methods defined in the domain layer.&lt;&#x2F;p&gt;
&lt;p&gt;To define an entity in TypeScript, you can use an interface or a class. Here’s an example of an interface for a User entity:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  firstName&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  lastName&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  email&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  createdAt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  updatedAt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;repository&quot;&gt;Repository&lt;&#x2F;h2&gt;
&lt;p&gt;The Repository layer is responsible for managing the persistence of entities. In the context of our authentication service, the repository will handle operations related to storing and retrieving user data from the database.&lt;&#x2F;p&gt;
&lt;p&gt;To create the UserRepository, follow these steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Inside the &lt;code&gt;src&lt;&#x2F;code&gt; directory, create a new directory called &lt;code&gt;repositories&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Inside the &lt;code&gt;repositories&lt;&#x2F;code&gt; directory, create a file called &lt;code&gt;UserRepository.ts&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;UserRepository.ts&lt;&#x2F;code&gt; file, import the necessary dependencies:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; getRepository&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Repository&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;typeorm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;domain&#x2F;entities&#x2F;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Define a class called &lt;code&gt;UserRepository&lt;&#x2F;code&gt; and export it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; UserRepository&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span&gt; repository&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Repository&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  constructor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getRepository&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Add methods to the &lt;code&gt;UserRepository&lt;&#x2F;code&gt; class for handling database operations. For example, you can add methods for creating a new user, finding a user by email, or updating a user’s password.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an example of a method for creating a new user:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; createUser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class&quot;&gt;Promise&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;newUser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return this.repository.save(newUser);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the &lt;code&gt;getRepository&lt;&#x2F;code&gt; function is provided by TypeORM, which is a popular Object-Relational Mapping (ORM) library for TypeScript and JavaScript.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Save the file and move on to the next step.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use Cases&lt;&#x2F;h2&gt;
&lt;p&gt;The Use Case layer contains application-specific business rules and orchestrates the flow of data between the entities and the repositories. In the context of our authentication service, the use cases will handle the logic for signing up and logging in users.&lt;&#x2F;p&gt;
&lt;p&gt;To create the Signup use case, follow these steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Inside the &lt;code&gt;src&#x2F;usecases&lt;&#x2F;code&gt; directory, create a file called &lt;code&gt;Signup.ts&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;Signup.ts&lt;&#x2F;code&gt; file, import the necessary dependencies:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; UserRepository&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;repositories&#x2F;UserRepository&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;domain&#x2F;entities&#x2F;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; hashPassword&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;utils&#x2F;passwordUtils&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Define a class called &lt;code&gt;Signup&lt;&#x2F;code&gt; and export it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Signup&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span&gt; userRepository&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; UserRepository&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  constructor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;userRepository&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; UserRepository&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;userRepository&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; userRepository&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Add a &lt;code&gt;execute&lt;&#x2F;code&gt; method to the &lt;code&gt;Signup&lt;&#x2F;code&gt; class that takes in the necessary input data for signing up a user, such as email and password:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;email&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class&quot;&gt;Promise&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Hash the password&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;hashedPassword&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; hashPassword&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Create a new user entity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const &lt;&#x2F;span&gt;&lt;span&gt;newUser&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; User&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Generate a unique identifier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    email&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    password&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; hashedPassword&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    createdAt&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    updatedAt&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Save the new user to the database&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;userRepository&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;createUser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;newUser&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example, the &lt;code&gt;hashPassword&lt;&#x2F;code&gt; function is a utility function that hashes the user’s password before storing it in the database. You can implement this function using a library like &lt;code&gt;bcrypt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Save the file and move on to the next step.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;controllers-and-routes&quot;&gt;Controllers and Routes&lt;&#x2F;h2&gt;
&lt;p&gt;The Controllers layer handles incoming requests, validates input data, and interacts with the use cases to process the request. In the context of our authentication service, the controllers will handle the HTTP endpoints for signing up and logging in users.&lt;&#x2F;p&gt;
&lt;p&gt;To create the AuthController and define the authentication routes, follow these steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Inside the &lt;code&gt;src&#x2F;interface&lt;&#x2F;code&gt; directory, create a file called &lt;code&gt;AuthController.ts&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;AuthController.ts&lt;&#x2F;code&gt; file, import the necessary dependencies:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Response&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;express&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Signup&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;usecases&#x2F;Signup&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; UserRepository&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;repositories&#x2F;UserRepository&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Define a class called &lt;code&gt;AuthController&lt;&#x2F;code&gt; and export it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; AuthController&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span&gt; signup&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Signup&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;  constructor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;signup&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Signup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; UserRepository&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Add methods to the &lt;code&gt;AuthController&lt;&#x2F;code&gt; class for handling the signup and login endpoints. For example, you can add a method for handling the POST request to &lt;code&gt;&#x2F;signup&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; signupHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; res&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class&quot;&gt;Promise&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; email&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt; = req.body;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  try &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;signup&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;email&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    res&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;201&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;json&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt; catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    res.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;500&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;json&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; error&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Failed to create user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that in this example, the &lt;code&gt;signupHandler&lt;&#x2F;code&gt; method calls the &lt;code&gt;execute&lt;&#x2F;code&gt; method of the &lt;code&gt;Signup&lt;&#x2F;code&gt; use case to create a new user. If the signup is successful, it responds with the created user; otherwise, it returns a 500 error.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Define the routes for authentication in the &lt;code&gt;registerRoutes&lt;&#x2F;code&gt; method of the &lt;code&gt;App&lt;&#x2F;code&gt; class in the &lt;code&gt;server.ts&lt;&#x2F;code&gt; file. For example, you can add the following route for the signup endpoint:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;router&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;signup&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; authController&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;signupHandler&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;authController&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, &lt;code&gt;authController.signupHandler&lt;&#x2F;code&gt; is bound to the route handler to maintain the correct context when handling the request.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Save all the files and start the server using &lt;code&gt;npm start&lt;&#x2F;code&gt; or &lt;code&gt;yarn start&lt;&#x2F;code&gt;. You should now be able to send HTTP requests to the authentication endpoints.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Congratulations! You have successfully set up an authentication service in Node.js using TypeScript and clean architecture. You have learned how to structure your code using the Clean Architecture pattern, set up the server, define entities and repositories, create use cases, and handle HTTP requests with controllers and routes. From here, you can further enhance your authentication service by adding features like login, password reset, and email verification.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to always follow security best practices when implementing authentication, such as using strong password hashing algorithms, protecting against brute force attacks, and handling session management securely.&lt;&#x2F;p&gt;
&lt;p&gt;Github repo &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;siddharth1729&#x2F;authentication_ts.git&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Understanding Isolation in Database</title>
        <published>2023-03-31T00:00:00+00:00</published>
        <updated>2023-03-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/blog/isolation-in-databases/"/>
        <id>https://siddharthsabron.in/blog/isolation-in-databases/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/blog/isolation-in-databases/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1692160115612-010ce42b63a8?q=80&amp;amp;w=3089&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.0.3&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot; Rajiv Chowk Metro Stataion clicked by Siddharth&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Rajiv Chowk Metro Stataion&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;a-group-of-people-standing-around-a-train-station-ugIN7vHvRvE&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Isolation in database refers to the ability of a database system to allow multiple transactions to access the same data without interfering with each other. Isolation ensures that each transaction sees a consistent view of the data, regardless of the concurrent activities of other transactions.&lt;&#x2F;p&gt;
&lt;p&gt;Types of Read Phenomena&lt;&#x2F;p&gt;
&lt;p&gt;There are three main types of read phenomena&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;isolation-in-databases&#x2F;#dirty-reads&quot;&gt;Dirty Reads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;isolation-in-databases&#x2F;#non-repeatable-reads&quot;&gt;Non-Repeatable Reads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;siddharthsabron.in&#x2F;blog&#x2F;isolation-in-databases&#x2F;#phantom-reads&quot;&gt;Phantom Reads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;dirty-reads&quot;&gt;Dirty Reads&lt;&#x2F;h2&gt;
&lt;p&gt;Dirty reads occur when a transaction reads data that has been modified by another transaction but not yet committed. This means that the transaction is reading data that is still in an intermediate or “dirty” state, and it may be rolled back later.&lt;&#x2F;p&gt;
&lt;p&gt;To illustrate this, let’s consider a simple example. Suppose we have a table named “employees” with the following columns: “id”, “name”, “salary”, and “department”. Transaction A executes the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Meanwhile, Transaction B updates the salary of employee with id 1 using the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 60000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, Transaction B does not commit the update yet. If we are using Read Uncommitted isolation level, Transaction A can read the new value of the salary column even though Transaction B has not committed the update yet.&lt;&#x2F;p&gt;
&lt;p&gt;To demonstrate this, let’s run the following SQL queries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ISOLATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; LEVEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; READ&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; UNCOMMITTED&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 60000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we are using Read Uncommitted isolation level, the read operation in Transaction A may return the new value of the salary column even though Transaction B has not committed the update yet.&lt;&#x2F;p&gt;
&lt;p&gt;To prevent dirty reads, we can use at least the Read Committed isolation level, which ensures that a transaction reads only committed data.&lt;&#x2F;p&gt;
&lt;p&gt;In SQL, we can set the isolation level for a transaction using the SET TRANSACTION statement. To set the isolation level to Read Committed, we would use the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ISOLATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; LEVEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; READ&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; COMMITTED&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In conclusion, dirty reads can occur in database systems when a transaction reads data that has been modified by another transaction but not yet committed. To prevent dirty reads, we can use at least the Read Committed isolation level, which ensures that a transaction reads only committed data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;non-repeatable-reads&quot;&gt;Non-Repeatable Reads&lt;&#x2F;h2&gt;
&lt;p&gt;Non-repeatable reads occur when a transaction reads a row twice but gets different values in each read. This can happen when another transaction modifies the row in between the two reads.&lt;&#x2F;p&gt;
&lt;p&gt;To illustrate this, let’s consider a simple example. Suppose we have a table named “employees” with the following columns: “id”, “name”, “salary”, and “department”. Transaction A executes the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Meanwhile, Transaction B updates the salary of employee with id 1 using the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 60000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we are using Read Committed isolation level, Transaction A will not see the new value of the salary column until Transaction B commits. However, if we use Repeatable Read isolation level, Transaction A may see the new value of the salary column on its subsequent reads.&lt;&#x2F;p&gt;
&lt;p&gt;To demonstrate this, let’s run the following SQL queries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 60000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COMMIT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction A again&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; salary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction A again&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we are using Repeatable Read isolation level, the second read operation in Transaction A may return a different value for the salary column compared to the first read operation, since the row was updated by Transaction B.&lt;&#x2F;p&gt;
&lt;p&gt;To prevent non-repeatable reads, we can use Serializable isolation level, which ensures that a transaction sees a consistent snapshot of the database throughout its execution, even if other transactions modify the same data.&lt;&#x2F;p&gt;
&lt;p&gt;In SQL, we can set the isolation level for a transaction using the SET TRANSACTION statement. To set the isolation level to Serializable, we would use the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ISOLATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; LEVEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; SERIALIZABLE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In conclusion, non-repeatable reads can occur in database systems when a transaction reads a row twice but gets different values in each read, due to another transaction modifying the row in between. To prevent non-repeatable reads, we can use Serializable isolation level, which ensures that a transaction sees a consistent snapshot of the database throughout its execution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phantom-reads&quot;&gt;Phantom Reads&lt;&#x2F;h2&gt;
&lt;p&gt;Phantom reads refer to the situation where a transaction reads a set of rows that satisfy a certain condition, but when the same transaction repeats the same read operation later, additional rows appear that were not visible before. This happens when another transaction commits a new row that satisfies the same condition.&lt;&#x2F;p&gt;
&lt;p&gt;To understand phantom reads better, let’s look at an example:&lt;&#x2F;p&gt;
&lt;p&gt;Suppose we have a table named “employees” with the following columns: “id”, “name”, “salary”, and “department”. Let’s say Transaction A executes the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; department &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sales&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Meanwhile, Transaction B inserts a new row into the employees table with department ‘Sales’ using the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span&gt; employees (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, salary, department) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;John Doe&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;50000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sales&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we are using Read Committed isolation level, Transaction A will not see the new row inserted by Transaction B until Transaction B commits. However, if we use Repeatable Read isolation level, Transaction A may see the new row inserted by Transaction B on its subsequent reads.&lt;&#x2F;p&gt;
&lt;p&gt;To demonstrate this, let’s run the following SQL queries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; department &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sales&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span&gt; employees (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, salary, department) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;John Doe&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;50000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sales&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COMMIT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start Transaction A again&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BEGIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; employees &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; department &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sales&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; End Transaction A again&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we are using Repeatable Read isolation level, the second read operation in Transaction A may return a new row inserted by Transaction B. This is because Repeatable Read isolation level uses a snapshot of the database taken at the beginning of the transaction, and any subsequent changes made by other transactions are not visible to the current transaction.&lt;&#x2F;p&gt;
&lt;p&gt;To prevent phantom reads, we can use Serializable isolation level, which ensures that a transaction sees a consistent snapshot of the database throughout its execution, even if other transactions modify the same data.&lt;&#x2F;p&gt;
&lt;p&gt;In SQL, we can set the isolation level for a transaction using the SET TRANSACTION statement. To set the isolation level to Serializable, we would use the following query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TRANSACTION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ISOLATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; LEVEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; SERIALIZABLE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In conclusion, phantom reads can occur in database systems when a transaction reads a set of rows that satisfy a certain condition, but additional rows appear when the same transaction repeats the same read operation later. To prevent phantom reads, we can use Serializable isolation level, which ensures that a transaction sees a consistent snapshot of the database throughout its execution.&lt;&#x2F;p&gt;
&lt;p&gt;If you enjoyed reading this article, please subscribe to it and tell your peers about it.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;If you like the post please connect me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;LinkedIn&lt;&#x2F;a&gt;
Follow me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What caused Discord to switch from Go to Rust? </title>
        <published>2023-03-11T00:00:00+00:00</published>
        <updated>2023-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Siddharth Sabron
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://siddharthsabron.in/blog/discord/"/>
        <id>https://siddharthsabron.in/blog/discord/</id>
        
        <content type="html" xml:base="https://siddharthsabron.in/blog/discord/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;images.unsplash.com&#x2F;photo-1764315576314-000e64769dc7?q=80&amp;amp;w=1974&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&quot; alt=&quot;LLandor, Mussoorie clicked by siddharth sabron &quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Landor ❤️&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;YLwjSWLvbNs&quot;&gt;Image Link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;read-states&quot;&gt;Read States&lt;&#x2F;h2&gt;
&lt;p&gt;Read States is the service that was moved from Go to Rust. Its primary
function is to record the channels and messages we have read. Every time
we sign in to Discord, send a message, and read a message, Read States
is accessed.To put it simple, Read States is on a hot road. Therefore,
Incredible speed and minimal latency are required for Read States
service.&lt;&#x2F;p&gt;
&lt;p&gt;Discord is a communication platform with billions of read states for
users and channels. However, there is only one read state that holds
various counters, such as the number of mentions in a channel. These
counters must be updated atomically and often reset to 0. To achieve
this, each read state service maintains a LRU (least recently used)
cache of read states, allowing for fast atomic counter updates. Each
cache has millions of users and tons of millions of read states, with
cache modifications occurring hundreds of thousands of times each
second. This caching strategy helps to efficiently manage and update the
vast amount of read states on Discord.&lt;&#x2F;p&gt;
&lt;p&gt;Before moving forward let&#x27;s now talk on how RUST and GO manage their
memories.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;memory-management-in-go&quot;&gt;Memory management in Go&lt;&#x2F;h2&gt;
&lt;p&gt;Memory is not instantly released in Go upon cache key eviction.Instead,
every so often, the garbage collector runs to discover any memory that
has no references and releases it. In other words, memory hangs out
until the garbage collector can assess if it is genuinely out of use,
rather than releasing immediately once it is no longer needed.The amount
of effort Go must undertake to figure out what memory is free during
garbage collection might cause the application to lag. Go will require
garbage pickups to occur at least every two minutes.In other words,
regardless of heap growth, go will still trigger a garbage collection if
it has not run for 2 minutes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;memory-management-in-rust&quot;&gt;Memory management in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;With no runtime or garbage collector, Rust is amazingly quick and
memory-efficient. It can power performance-critical applications, run on
embedded devices, and interface with other languages with ease. Rust
implements memory &quot;ownership&quot; as part of a rather novel approach to
memory management. Rust essentially keeps track of who is able to read
from and write to memory. It is aware of when an application is
utilizing memory and instantly releases it when no longer required.
Runtime memory problems are practically hard to have since it enforces
memory restrictions at build time.You don&#x27;t have to manually manage
your memory.The compiler handles it for you. So, in the Rust version of
the Read States service, a user&#x27;s Read State is instantly released from
memory when it is removed from the LRU (least recently used) cache.&lt;&#x2F;p&gt;
&lt;p&gt;The read state memory doesn&#x27;t wait for the garbage collector to pick it
up. Rust promptly releases it because it is no longer needed.No runtime
process checks if it needs to be released.&lt;&#x2F;p&gt;
&lt;p&gt;The CPU utilization after switching this Read State service from Go to
Rust is seen below.&lt;&#x2F;p&gt;
&lt;p&gt;Go is purple, Rust is blue. No alt text provided for this image&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;miro.medium.com&#x2F;v2&#x2F;resize:fit:720&#x2F;0*j6rYXpSnHhFg9RYE&quot; alt=&quot;CPU utilization graph of Discord’s Read States service: the Go implementation (purple) shows periodic spikes from garbage collection, while the Rust implementation (blue) stays flat and consistent&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I absolutely adore the drive and mindset behind Discord&#x27;s Backend Team.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;If you like the post please connect me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;siddharthsabron&#x2F;&quot;&gt;linkedin&lt;&#x2F;a&gt;
Follow me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;sudolegion&quot;&gt;twiter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
</feed>
