<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vivek Alhat</title>
    <description>The latest articles on DEV Community by Vivek Alhat (@vivekalhat).</description>
    <link>https://dev.to/vivekalhat</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F272637%2F33c1e0ae-35c8-48eb-9a3a-74c46d2dc8a2.png</url>
      <title>DEV Community: Vivek Alhat</title>
      <link>https://dev.to/vivekalhat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vivekalhat"/>
    <language>en</language>
    <item>
      <title>The Builder Design Pattern</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sat, 29 Mar 2025 19:13:00 +0000</pubDate>
      <link>https://dev.to/vivekalhat/the-builder-design-pattern-5d43</link>
      <guid>https://dev.to/vivekalhat/the-builder-design-pattern-5d43</guid>
      <description>&lt;p&gt;When creating objects in programming, sometimes we need to set many optional values. If we use constructors for this, it can get messy quickly and cause &lt;strong&gt;constructor hell&lt;/strong&gt;. The builder pattern helps us solve this problem by providing a step-by-step way to create objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use the Builder Pattern?
&lt;/h2&gt;

&lt;p&gt;Consider a &lt;code&gt;User&lt;/code&gt; class where some properties (like &lt;code&gt;age&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt;) are optional. Without the Builder Pattern, you might need multiple constructors or pass &lt;code&gt;undefined&lt;/code&gt; for missing values. This can make code hard to read.&lt;/p&gt;

&lt;p&gt;The Builder Pattern solves this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Making object creation &lt;strong&gt;more readable&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Avoiding unnecessary or confusing constructor arguments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example: Creating a User Object with a Builder
&lt;/h2&gt;

&lt;p&gt;Let's take a look at how the Builder Pattern works in TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the &lt;code&gt;User&lt;/code&gt; Class
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;User&lt;/code&gt; class has three properties: &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, and &lt;code&gt;email&lt;/code&gt;. Only &lt;code&gt;name&lt;/code&gt; is required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a &lt;code&gt;UserBuilder&lt;/code&gt; Class
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IUserBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBuilder&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IUserBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User must have a name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Using the &lt;code&gt;UserBuilder&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;johndoe@email.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'John&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;age:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;email:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'johndoe@email.com'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try to create a user &lt;strong&gt;without a name&lt;/strong&gt;, we get an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Error: User must have a name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of Using the Builder Pattern
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Improves readability&lt;/strong&gt; – Each property is set explicitly.&lt;br&gt;
✅ &lt;strong&gt;Reduces constructor overloads&lt;/strong&gt; – No need to pass &lt;code&gt;undefined&lt;/code&gt; for optional parameters.&lt;br&gt;
✅ &lt;strong&gt;Flexible object creation&lt;/strong&gt; – Easily add or remove properties without modifying the constructor.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use the Builder Pattern
&lt;/h2&gt;

&lt;p&gt;Use the Builder Pattern when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a class with &lt;strong&gt;many optional properties&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You want to make &lt;strong&gt;object creation more readable&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You want to &lt;strong&gt;enforce required fields&lt;/strong&gt; before creating the object.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The Builder Pattern is a simple yet powerful way to create objects, especially when dealing with optional parameters. It makes your code cleaner, easier to understand, and less error-prone.&lt;/p&gt;

&lt;p&gt;I am implementing design patterns in Go, Python, and TypeScript. You can find the repository &lt;a href="https://github.com/VivekAlhat/Design-Patterns" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>programming</category>
      <category>designpatterns</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Singleton Design Pattern</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Fri, 07 Mar 2025 09:23:58 +0000</pubDate>
      <link>https://dev.to/vivekalhat/the-singleton-design-pattern-686</link>
      <guid>https://dev.to/vivekalhat/the-singleton-design-pattern-686</guid>
      <description>&lt;p&gt;Design patterns are essential for writing clean, scalable, and maintainable code. One of the most commonly used design patterns is the &lt;strong&gt;Singleton Pattern&lt;/strong&gt;. In this article, we’ll explore what the Singleton pattern is, why it’s useful, and how to implement it with an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Singleton Design Pattern?
&lt;/h2&gt;

&lt;p&gt;The Singleton pattern is a creational design pattern that ensures a class has only &lt;strong&gt;one instance&lt;/strong&gt; and provides a global point of access to that instance. This pattern is useful when you need to control access to shared resources, such as logging mechanisms, configuration settings, or database connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Characteristics of the Singleton Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Instance:&lt;/strong&gt; Ensures that only one instance of the class exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global Access Point:&lt;/strong&gt; Provides a way to access the single instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Initialization:&lt;/strong&gt; The instance is created only when it is first needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thread Safety (Optional):&lt;/strong&gt; In multi-threaded environments, precautions should be taken to avoid multiple instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Implement the Singleton Pattern
&lt;/h2&gt;

&lt;p&gt;Let's implement a &lt;strong&gt;Logger&lt;/strong&gt; class using the Singleton pattern in TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// private static instance variable&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// private constructor to prevent external initialization&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="c1"&gt;// static method to get the instance&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Creating new instance&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logger1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logger2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;logger2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Both are the same loggers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Private Constructor&lt;/strong&gt;: Prevents external instantiation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Instance Variable&lt;/strong&gt;: Stores the single instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Method (&lt;code&gt;getInstance&lt;/code&gt;)&lt;/strong&gt;: Ensures only one instance is created and provides global access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Initialization&lt;/strong&gt;: The instance is created only when first accessed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensuring Uniqueness&lt;/strong&gt;: Checking if &lt;code&gt;logger1 === logger2&lt;/code&gt; confirms that both variables reference the same instance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Use Cases of Singleton Pattern
&lt;/h2&gt;

&lt;p&gt;The Singleton pattern is useful in scenarios where multiple instances could lead to inconsistencies or unnecessary resource usage. Some common use cases include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Logging&lt;/strong&gt;: A single instance ensures consistent logging throughout the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration Management&lt;/strong&gt;: Prevents multiple conflicting configuration objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Connection Pooling&lt;/strong&gt;: Avoids multiple redundant connections to the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Pros and Cons of Singleton Pattern
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;p&gt;✔ It ensures a single point of access to a resource.&lt;br&gt;
✔ It saves memory by preventing multiple unnecessary instances.&lt;br&gt;
✔ It is useful for managing shared states like caching and logging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;p&gt;✖ It can introduce &lt;strong&gt;global state&lt;/strong&gt; hence making debugging harder.&lt;br&gt;
✖ It is not inherently &lt;strong&gt;thread-safe&lt;/strong&gt; hence needs additional handling in multi-threaded environments.&lt;/p&gt;

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

&lt;p&gt;The Singleton pattern is a powerful and commonly used design pattern that ensures only one instance of a class exists. &lt;/p&gt;

&lt;p&gt;I am implementing design patterns in Go, Python, and TypeScript. You can find the repository &lt;a href="https://github.com/VivekAlhat/Design-Patterns" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>programming</category>
      <category>designpatterns</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Design Patterns: A Beginner's Guide</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Tue, 04 Feb 2025 17:15:44 +0000</pubDate>
      <link>https://dev.to/vivekalhat/understanding-design-patterns-a-beginners-guide-3d8i</link>
      <guid>https://dev.to/vivekalhat/understanding-design-patterns-a-beginners-guide-3d8i</guid>
      <description>&lt;p&gt;If you've worked on a software project that became difficult to manage as it grew, you've likely encountered design challenges that could have been solved with a structured approach. This is where design patterns come in. They provide reusable solutions to common problems in software development, improving code maintainability, readability, and scalability.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore what design patterns are, why they are useful, their different types, and their pros and cons. This article will serve as a foundation for the upcoming articles in this series, where we will dive deeper into specific design patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Are Design Patterns?
&lt;/h3&gt;

&lt;p&gt;Design patterns are proven solutions to recurring design problems in software development. They are not specific implementations but rather templates that can be used to solve particular problems in different contexts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Design Patterns?
&lt;/h3&gt;

&lt;p&gt;Software development is often about solving problems efficiently. Instead of reinventing the wheel every time, developers can leverage design patterns to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Improve Code Reusability&lt;/strong&gt; – Patterns provide well-established solutions that can be adapted across different projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhance Maintainability&lt;/strong&gt; – Well-structured code is easier to read, modify, and debug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce Development Time&lt;/strong&gt; – With predefined solutions, developers can focus on implementation rather than figuring out the architecture from scratch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Types of Design Patterns
&lt;/h3&gt;

&lt;p&gt;Design patterns are categorized into three main types:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Creational Patterns
&lt;/h4&gt;

&lt;p&gt;These patterns deal with object creation mechanisms, improving flexibility and reusability. Some common creational patterns include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Singleton&lt;/strong&gt; – Ensures only one instance of a class exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Factory&lt;/strong&gt; – Provides an interface for creating objects but allows subclasses to alter the type of objects that will be created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Builder&lt;/strong&gt; – Separates object construction from its representation, allowing step-by-step creation of complex objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Structural Patterns
&lt;/h4&gt;

&lt;p&gt;These patterns focus on composing classes and objects to form larger structures while ensuring flexibility and efficiency. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adapter&lt;/strong&gt; – Allows incompatible interfaces to work together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decorator&lt;/strong&gt; – Dynamically adds responsibilities to an object without modifying its code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facade&lt;/strong&gt; – Provides a simplified interface to a larger system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Behavioral Patterns
&lt;/h4&gt;

&lt;p&gt;These patterns deal with communication between objects, focusing on improving the flexibility of interactions. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observer&lt;/strong&gt; – Defines a one-to-many dependency where multiple objects are notified of state changes in another object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strategy&lt;/strong&gt; – Enables selecting an algorithm’s implementation at runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command&lt;/strong&gt; – Encapsulates requests as objects, allowing parameterization of clients and request queuing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros and Cons of Design Patterns
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ✅ Pros:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Increases Code Reusability&lt;/strong&gt; – Solutions can be used across multiple projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhances Maintainability&lt;/strong&gt; – Code is more modular and easier to refactor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improves Scalability&lt;/strong&gt; – Helps in designing software that can evolve over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized Solutions&lt;/strong&gt; – Reduces ambiguity in architecture discussions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ❌ Cons:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overuse Can Lead to Complexity&lt;/strong&gt; – Applying patterns unnecessarily can make code more complicated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Curve&lt;/strong&gt; – Understanding and properly implementing design patterns requires time and experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Overhead&lt;/strong&gt; – Some patterns, like Decorator and Observer, may introduce additional processing costs.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;a href="https://refactoring.guru/design-patterns" rel="noopener noreferrer"&gt;Refactoring Guru&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Design patterns are powerful tools that help developers build efficient, maintainable, and scalable software.&lt;/p&gt;

&lt;p&gt;In the upcoming articles of this series, we will explore specific design patterns in detail. Stay tuned!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>designpatterns</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a Multi-Agent Blog Writer Using Crew AI</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sun, 29 Dec 2024 14:26:44 +0000</pubDate>
      <link>https://dev.to/vivekalhat/building-a-multi-agent-blog-writer-using-crew-ai-22ap</link>
      <guid>https://dev.to/vivekalhat/building-a-multi-agent-blog-writer-using-crew-ai-22ap</guid>
      <description>&lt;p&gt;Creating high-quality, engaging blog content often involves multiple stages, from planning and writing to editing. With Crew AI, you can build a multi-agent system that automates this process using AI, streamlining content creation while maintaining quality. In this blog, we’ll explore what Crew AI is, its key components, and how to build a blog writing multi-agent system step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Crew AI?
&lt;/h3&gt;

&lt;p&gt;Crew AI is a Python-based framework for orchestrating intelligent agents to collaborate on complex tasks. Each agent represents a specialized entity with a distinct role, expertise, and goals. By defining tasks and assigning them to agents, Crew AI enables you to build workflows where agents seamlessly interact to achieve a shared goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Concepts
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Agent&lt;/strong&gt;&lt;br&gt;
An Agent represents an individual entity responsible for executing specific tasks. Each agent has a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role: Defines its primary responsibility.&lt;/li&gt;
&lt;li&gt;Goal: Specifies the desired outcome for its tasks.&lt;/li&gt;
&lt;li&gt;Backstory: Provides contextual information to enhance its performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Task&lt;/strong&gt;&lt;br&gt;
A Task represents a unit of work assigned to an agent. It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Description: A detailed explanation of what the agent must do.&lt;/li&gt;
&lt;li&gt;Expected Output: Criteria for evaluating task completion.&lt;/li&gt;
&lt;li&gt;Assigned Agent: The agent responsible for executing the task.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Crew&lt;/strong&gt;&lt;br&gt;
A Crew is a collection of agents working together to complete tasks. The tasks can be executed sequentially or hierarchically, depending on the Process configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Process&lt;/strong&gt;&lt;br&gt;
The Process defines how tasks are executed. It can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sequential: Tasks are completed in a predefined order.&lt;/li&gt;
&lt;li&gt;Hierarchical: Tasks are executed in a managerial hierarchy.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this example, we use the &lt;code&gt;groq/llama-3.1-8b-instant&lt;/code&gt; language model as the LLM. This model provides the natural language capabilities for agents to perform their roles effectively. You'll need an API key to interact with this LLM. You can create your Groq account &lt;a href="https://groq.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s dive into building a blog writing system where agents collaboratively plan, write, and edit a blog post.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Setting Up the Environment
&lt;/h4&gt;

&lt;p&gt;Before starting, ensure you have the required dependencies installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install crewai groq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Initialize the LLM
&lt;/h4&gt;

&lt;p&gt;The language model is the backbone of our system. Define it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from crewai import LLM  

llm = LLM(  
    model="groq/llama-3.1-8b-instant",  
    api_key="",  # Replace with your API key  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets up the LLM that all agents will use for processing text-based tasks.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Defining Agents
&lt;/h4&gt;

&lt;p&gt;a) &lt;strong&gt;Content Planner&lt;/strong&gt;&lt;br&gt;
The Content Planner is responsible for creating a structured outline for the blog post. Define it with a clear goal and backstory to guide its outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from crewai import Agent  

planner = Agent(  
    role="Content Planner",  
    goal="Develop a comprehensive and structured content outline for {topic}, including key sections, subsections, and supporting points.",  
    backstory="An expert content strategist skilled at breaking down complex topics into manageable parts.",  
    llm=llm,  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b) &lt;strong&gt;Content Writer&lt;/strong&gt;&lt;br&gt;
The Content Writer expands the outline into a detailed blog post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;writer = Agent(  
    role="Content Writer",  
    goal="Produce captivating and informative blog posts about {topic}.",  
    backstory="A versatile writer passionate about simplifying complex ideas.",  
    llm=llm,  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;c) &lt;strong&gt;Content Editor&lt;/strong&gt;&lt;br&gt;
The Content Editor refines and polishes the blog post to ensure quality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;editor = Agent(  
    role="Content Editor",  
    goal="Refine the blog post, ensuring clarity, coherence, and grammatical accuracy.",  
    backstory="A meticulous editor with a strong eye for detail.",  
    llm=llm,  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Defining Tasks
&lt;/h4&gt;

&lt;p&gt;a) &lt;strong&gt;Content Planning Task&lt;/strong&gt;&lt;br&gt;
The first task involves creating an outline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from crewai import Task  

plan = Task(  
    description="Create a detailed content outline for {topic}, including main sections and key points.",  
    expected_output="A structured outline for {topic}, with headings and bullet points.",  
    agent=planner,  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b) &lt;strong&gt;Content Writing Task&lt;/strong&gt;&lt;br&gt;
The second task transforms the outline into a complete blog post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;write = Task(  
    description="Transform the outline into a 1000-word blog post in markdown format.",  
    expected_output="A comprehensive blog post with clear language and examples.",  
    agent=writer,  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;c) &lt;strong&gt;Content Editing Task&lt;/strong&gt;&lt;br&gt;
The final task involves refining the blog post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;edit = Task(  
    description="Review and polish the blog post, ensuring quality and alignment with the outline.",  
    expected_output="A polished, error-free blog post with enhanced structure and tone.",  
    agent=editor,  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Assembling the Crew
&lt;/h4&gt;

&lt;p&gt;Combine the agents and tasks into a crew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from crewai import Crew, Process  

crew = Crew(  
    agents=[planner, writer, editor],  
    tasks=[plan, write, edit],  
    verbose=True,  
    process=Process.sequential,  # Execute tasks in sequence  
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. Kicking Off the Process
&lt;/h4&gt;

&lt;p&gt;Prompt the user for the blog topic and start the process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;topic = input("Topic?\n")  
edit.output_file = topic + ".md"  # Save the final output as a markdown file  
crew.kickoff(inputs={"topic": topic})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Content Planner creates an outline for the given topic.&lt;/li&gt;
&lt;li&gt;The Content Writer expands the outline into a detailed blog post.&lt;/li&gt;
&lt;li&gt;The Content Editor reviews and refines the content for quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire process runs sequentially, ensuring each task builds upon the output of the previous one.&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Building a simple rate limiter in Go</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sat, 28 Dec 2024 18:10:37 +0000</pubDate>
      <link>https://dev.to/vivekalhat/rate-limiting-for-beginners-what-it-is-and-how-to-build-one-in-go-955</link>
      <guid>https://dev.to/vivekalhat/rate-limiting-for-beginners-what-it-is-and-how-to-build-one-in-go-955</guid>
      <description>&lt;p&gt;Rate limiting is a critical concept in web development and API design. It ensures that users or systems can only make a limited number of requests to a server within a specific time frame. In this blog post, we’ll explore what rate limiting is, why it’s essential, and how to implement a simple rate limiter in Go.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  What Is Rate Limiting?
&lt;/h3&gt;

&lt;p&gt;Imagine a theme park with a roller coaster ride that can only accommodate 10 people every 10 minutes. If more than 10 people try to get on within that timeframe, they’ll have to wait. This analogy mirrors the principle of rate limiting in software systems.&lt;/p&gt;

&lt;p&gt;In technical terms, rate limiting restricts the number of requests a client (e.g., a user, device, or IP address) can send to a server within a predefined period. It helps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prevent abuse and ensure fair usage of resources.&lt;/li&gt;
&lt;li&gt;Protect servers from being overwhelmed by excessive traffic.&lt;/li&gt;
&lt;li&gt;Avoid costly overuse of third-party APIs or services.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, an API might allow 100 requests per minute per user. If a user exceeds this limit, the server denies further requests until the limit resets.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does Rate Limiting Work?
&lt;/h3&gt;

&lt;p&gt;One common way to implement rate limiting is through the &lt;strong&gt;token bucket algorithm&lt;/strong&gt;. Here’s how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A bucket starts with a fixed number of tokens (e.g., 10).&lt;/li&gt;
&lt;li&gt;Each request removes one token from the bucket.&lt;/li&gt;
&lt;li&gt;If the bucket has no tokens left, the request is denied.&lt;/li&gt;
&lt;li&gt;Tokens are replenished at a steady rate (e.g., 1 token every second) until the bucket is full.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Building a Simple Rate Limiter in Go
&lt;/h3&gt;

&lt;p&gt;Let’s dive into building a rate limiter in Go that limits each client to 3 requests per minute.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Define the Rate Limiter Structure
&lt;/h4&gt;

&lt;p&gt;We’ll use the &lt;code&gt;sync.Mutex&lt;/code&gt; to ensure thread safety and store information like the number of tokens, the maximum capacity, and the refill rate.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;RateLimiter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt;         &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="c"&gt;// Current number of tokens&lt;/span&gt;
    &lt;span class="n"&gt;maxTokens&lt;/span&gt;      &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="c"&gt;// Maximum tokens allowed&lt;/span&gt;
    &lt;span class="n"&gt;refillRate&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="c"&gt;// Tokens added per second&lt;/span&gt;
    &lt;span class="n"&gt;lastRefillTime&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="c"&gt;// Last time tokens were refilled&lt;/span&gt;
    &lt;span class="n"&gt;mutex&lt;/span&gt;          &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewRateLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refillRate&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;maxTokens&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;refillRate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;refillRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;lastRefillTime&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Implement Token Refill Logic
&lt;/h4&gt;

&lt;p&gt;Tokens should be replenished periodically based on the elapsed time since the last refill.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;refillTokens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastRefillTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Seconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;tokensToAdd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;refillRate&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;tokensToAdd&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxTokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxTokens&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastRefillTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Check If a Request Is Allowed
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Allow&lt;/code&gt; method will determine if a request can proceed based on the available tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;refillTokens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Apply Rate Limiting Per IP
&lt;/h4&gt;

&lt;p&gt;To limit requests per client, we’ll create a map of IP addresses to their respective rate limiters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;IPRateLimiter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;limiters&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt;
    &lt;span class="n"&gt;mutex&lt;/span&gt;    &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewIPRateLimiter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;IPRateLimiter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;IPRateLimiter&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;limiters&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;IPRateLimiter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;RateLimiter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;limiters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Allow 3 requests per minute&lt;/span&gt;
        &lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewRateLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;limiters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Create Middleware for Rate Limiting
&lt;/h4&gt;

&lt;p&gt;Finally, we’ll create an HTTP middleware that enforces the rate limit for each client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;RateLimitMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ipRateLimiter&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;IPRateLimiter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SplitHostPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid IP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ipRateLimiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Rate Limit Exceeded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusTooManyRequests&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6: Set Up the Server
&lt;/h4&gt;

&lt;p&gt;Here’s how to hook it all together and test the rate limiter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Request processed successfully at %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ipRateLimiter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewIPRateLimiter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;mux&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RateLimitMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ipRateLimiter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server starting on :8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing the Rate Limiter
&lt;/h3&gt;

&lt;p&gt;Start the server and test it using &lt;code&gt;curl&lt;/code&gt; or your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Send 3 requests quickly: All should succeed.&lt;/li&gt;
&lt;li&gt;Send a 4th request within the same minute: You should see &lt;code&gt;Rate Limit Exceeded&lt;/code&gt; message.&lt;/li&gt;
&lt;li&gt;Wait for 20 seconds and try again: The bucket refills, and requests should succeed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/VivekAlhat/go-rate-limiter" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Database Consistency</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Wed, 25 Dec 2024 09:34:06 +0000</pubDate>
      <link>https://dev.to/vivekalhat/understanding-database-consistency-5dn2</link>
      <guid>https://dev.to/vivekalhat/understanding-database-consistency-5dn2</guid>
      <description>&lt;p&gt;When working with databases, one of the most important concepts to understand is &lt;strong&gt;consistency&lt;/strong&gt;. It ensures that the data in your database remains reliable and meaningful. Let’s dive into what database consistency is, its types, and why it’s essential for your applications.&lt;/p&gt;

&lt;h4&gt;
  
  
  What Is Database Consistency?
&lt;/h4&gt;

&lt;p&gt;In simple terms, &lt;strong&gt;database consistency&lt;/strong&gt; refers to the correctness and validity of the data stored in a database. Whenever data is added, modified, or deleted, the database should ensure it remains in a consistent state. This means that all defined rules, constraints, and relationships between data must be upheld.&lt;/p&gt;

&lt;p&gt;For example, imagine you’re transferring money between two bank accounts. If $100 is deducted from one account, it must be added to the other account, anything else would result in inconsistent data.&lt;/p&gt;

&lt;p&gt;Consistency is a key pillar of the &lt;strong&gt;ACID properties&lt;/strong&gt; of databases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity:&lt;/strong&gt; Transactions are all-or-nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency:&lt;/strong&gt; The database moves from one valid state to another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation:&lt;/strong&gt; Concurrent transactions don’t interfere with each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durability:&lt;/strong&gt; Once a transaction is committed, it’s permanent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Types of Database Consistency
&lt;/h4&gt;

&lt;p&gt;There are two main types of consistency in databases: &lt;strong&gt;strong consistency&lt;/strong&gt; and &lt;strong&gt;eventual consistency&lt;/strong&gt;. Let’s break these down.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strong Consistency&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Strong consistency ensures that all users see the same data at the same time, no matter where they are accessing it from. &lt;/li&gt;
&lt;li&gt;Every transaction is immediately visible to all parts of the system once it’s complete. &lt;/li&gt;
&lt;li&gt;This type of consistency is common in traditional relational databases like MySQL and PostgreSQL, which use ACID transactions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; In an online ticket booking system, once a ticket is sold, it’s immediately marked as unavailable to everyone else.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eventual Consistency&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Eventual consistency is often used in distributed systems and NoSQL databases. &lt;/li&gt;
&lt;li&gt;It doesn’t guarantee immediate consistency, but over time, all parts of the system will reflect the same data.&lt;/li&gt;
&lt;li&gt;This approach is suitable for scenarios where high availability and partition tolerance are prioritized over immediate consistency (as per the &lt;strong&gt;CAP theorem&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; In a social media app, when you update your profile picture, it might take a few seconds or minutes for all your friends to see the change, but eventually, they will all see the updated picture.&lt;/p&gt;

&lt;h4&gt;
  
  
  Differences Between Strong and Eventual Consistency
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Strong Consistency&lt;/th&gt;
&lt;th&gt;Eventual Consistency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Guarantee&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;All users see the same data instantly.&lt;/td&gt;
&lt;td&gt;All users see the same data eventually.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Critical systems like banking or finance.&lt;/td&gt;
&lt;td&gt;High-availability systems like social media.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Higher latency due to synchronization.&lt;/td&gt;
&lt;td&gt;Lower latency with delayed consistency.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simpler to reason about.&lt;/td&gt;
&lt;td&gt;More complex to implement in large systems.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Example Systems&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Relational databases (MySQL, PostgreSQL).&lt;/td&gt;
&lt;td&gt;NoSQL databases (Cassandra, DynamoDB).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Why Does Consistency Matter?
&lt;/h4&gt;

&lt;p&gt;Consistency is crucial for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Integrity:&lt;/strong&gt; Ensuring that data remains accurate and follows defined rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Trust:&lt;/strong&gt; Providing users with correct and reliable information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business Logic:&lt;/strong&gt; Preventing errors like duplicate entries, incorrect balances, or invalid relationships between data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Balancing Consistency with Other Factors
&lt;/h4&gt;

&lt;p&gt;In real-world systems, achieving perfect consistency can sometimes come at the cost of performance or availability. Distributed databases, for instance, often face a trade-off between consistency, availability, and partition tolerance, a concept known as the &lt;strong&gt;CAP theorem&lt;/strong&gt;. &lt;/p&gt;

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

&lt;p&gt;Depending on your application’s requirements, you might prioritize one over the others:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Consistency:&lt;/strong&gt; Ideal for financial systems or other critical applications where data accuracy is paramount.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Availability:&lt;/strong&gt; Suitable for applications like social networks or e-commerce sites where uptime is more important than immediate consistency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;Database consistency is a foundational concept that ensures the reliability and accuracy of your data. Whether you prioritize strong consistency or eventual consistency depends on your application’s specific needs. By understanding and applying the right strategies, you can design systems that balance consistency with performance and scalability.&lt;/p&gt;

</description>
      <category>database</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building a simple RAG agent with LlamaIndex</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Mon, 30 Sep 2024 14:44:00 +0000</pubDate>
      <link>https://dev.to/vivekalhat/building-a-simple-rag-agent-with-llamaindex-4c6k</link>
      <guid>https://dev.to/vivekalhat/building-a-simple-rag-agent-with-llamaindex-4c6k</guid>
      <description>&lt;p&gt;LlamaIndex is a framework for building context-augmented generative AI applications with LLMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is context augmentation?
&lt;/h3&gt;

&lt;p&gt;Context augmentation refers to a technique where additional relevant information or context is provided to an LLM model, improving its understanding and responses to a given query. This augmentation typically involves retrieving, integrating, or attaching external data sources such as documents, embeddings, to the model's input. The goal is to make the model more informed by providing it with necessary context that helps it give better, more accurate and nuanced answers. Retrieval augmented generation(RAG) is the most popular example of context augmentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are agents?
&lt;/h3&gt;

&lt;p&gt;Agents are automated reasoning and decision engines powered by LLMs that use tools to perform research, data extraction, web search, and more tasks. They can be used for simple use cases like question-answering based on the data to being able to decide and take actions in order to complete tasks.&lt;/p&gt;

&lt;p&gt;In this post, we'll build a simple RAG agent using LlamaIndex.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a RAG agent
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Installing dependencies
&lt;/h4&gt;

&lt;p&gt;We'll be using Python to build simple RAG agent using LlamaIndex. Let's first install required dependencies as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;llama&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dotenv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting up LLM and loading documents
&lt;/h4&gt;

&lt;p&gt;We'll be using OpenAI's &lt;code&gt;gpt-4o-mini&lt;/code&gt; as the LLM. You need to put the API key in environment variables file. You can read more about setting up a local LLM using LLamaIndex &lt;a href="https://docs.llamaindex.ai/en/stable/understanding/using_llms/using_llms/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.llms.openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;

&lt;span class="c1"&gt;# Load environment variables (e.g., OPENAI_API_KEY)
&lt;/span&gt;&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Configure OpenAI model
&lt;/span&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load documents from the local directory
&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Create an index from documents for querying
&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_query_engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;First we configure the LLM model using OpenAI and specifying the &lt;code&gt;gpt-4o-mini&lt;/code&gt; model. You can switch to other available models/LLMs depending on your needs.&lt;/li&gt;
&lt;li&gt;Then, we use &lt;code&gt;SimpleDirectoryReader&lt;/code&gt; to load documents from the local &lt;code&gt;./data&lt;/code&gt; directory. This reader scans through the directory, reads files, and structures the data for querying.&lt;/li&gt;
&lt;li&gt;Next, we create a vector store index from the loaded documents, allowing us to perform efficient vector-based retrieval during query execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Creating custom functions for agent
&lt;/h4&gt;

&lt;p&gt;Now, let's define some basic functions that the agent can use to perform tasks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Multiply two numbers and returns the product&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Add two numbers and returns the sum&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Creating tools for the agent
&lt;/h4&gt;

&lt;p&gt;Next, we'll create tools from the functions and the query engine that we defined earlier, which the agent will use to perform tasks. These tools acts as utilities that the agent can leverage when handling different types of queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.core.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FunctionTool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QueryEngineTool&lt;/span&gt;

&lt;span class="c1"&gt;# Wrap functions as tools
&lt;/span&gt;&lt;span class="n"&gt;add_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FunctionTool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;multiply_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FunctionTool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a query engine tool for document retrieval
&lt;/span&gt;&lt;span class="n"&gt;space_facts_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QueryEngineTool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;space_facts_tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A RAG engine with information about fun space facts.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;FunctionTool&lt;/code&gt; wraps the &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;multiply&lt;/code&gt; function and exposes them as tools. The agent can now access these tools to perform calculations.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;QueryEngineTool&lt;/code&gt; wraps the &lt;code&gt;query_engine&lt;/code&gt; to allow the agent to query and retrieve information from the vector store. We've named it &lt;code&gt;space_facts_tool&lt;/code&gt; with a description, indicating that this tool can retrieve information about space facts. You can ingest anything and customize the tool as per the ingested data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Creating the agent
&lt;/h4&gt;

&lt;p&gt;We will now create the agent using &lt;code&gt;ReActAgent&lt;/code&gt;. The agent will be responsible for deciding when to use the tools and how to respond to queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.core.agent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ReActAgent&lt;/span&gt;

&lt;span class="c1"&gt;# Create the agent with the tools
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReActAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;multiply_tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;add_tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;space_facts_tool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This agent uses &lt;strong&gt;ReAct&lt;/strong&gt; framework, which allows the model to &lt;strong&gt;reason and act&lt;/strong&gt; by utilizing the given tools in a logical sequence. The agent is initialized with the tools we created, and the &lt;code&gt;verbose=True&lt;/code&gt; flag will output detailed information on how the agent reasons and executes tasks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Running the agent
&lt;/h4&gt;

&lt;p&gt;Finally, let's run the agent in an interactive loop where it processes user queries until we exit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Query: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/bye&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How the RAG agent works?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When you ask a question related to the documents you ingested, the &lt;code&gt;space_facts_tool&lt;/code&gt; i.e., the vector store tool retrieves the relevant information using the &lt;code&gt;query_engine&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When you ask for calculations, the agent uses either &lt;code&gt;add_tool&lt;/code&gt; or &lt;code&gt;multiply_tool&lt;/code&gt; to perform those tasks.&lt;/li&gt;
&lt;li&gt;The agent decides on-the-fly which tool to use based on the user query and provides the output.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>rag</category>
      <category>openai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a simple load balancer in Go</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sat, 07 Sep 2024 12:40:46 +0000</pubDate>
      <link>https://dev.to/vivekalhat/building-a-simple-load-balancer-in-go-70d</link>
      <guid>https://dev.to/vivekalhat/building-a-simple-load-balancer-in-go-70d</guid>
      <description>&lt;p&gt;Load balancers are crucial in modern software development. If you've ever wondered how requests are distributed across multiple servers, or why certain websites feel faster even during heavy traffic, the answer often lies in efficient load balancing.&lt;/p&gt;

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

&lt;p&gt;In this post, we'll build a simple application load balancer using &lt;strong&gt;Round Robin algorithm&lt;/strong&gt; in Go. The aim of this post is to understand how a load balancer works under the hood, step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Load Balancer?
&lt;/h3&gt;

&lt;p&gt;A load balancer is a system that distributes incoming network traffic across multiple servers. It ensures that no single server bears too much load, preventing bottlenecks and improving the overall user experience. Load balancing approach also ensure that if one server fails, then the traffic can be automatically re-routed to another available server, thus reducing the impact of the failure and increasing availability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do we use Load Balancers?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High availability&lt;/strong&gt;: By distributing traffic, load balancers ensure that even if one server fails, traffic can be routed to other healthy servers, making the application more resilient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Load balancers allow you to scale your system horizontally by adding more servers as traffic increases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;: It maximizes resource utilization by ensuring all servers share the workload equally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Load balancing algorithms
&lt;/h3&gt;

&lt;p&gt;There are different algorithms and strategies to distribute the traffic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Round Robin&lt;/strong&gt;: One of the simplest methods available. It distributes requests sequentially among the available servers. Once it reaches the last server, it starts again from the beginning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weighted Round Robin&lt;/strong&gt;: Similar to round robin algorithm except each server is assigned some fixed numerical weighting. This given weight is used to determine the server for routing traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least Connections&lt;/strong&gt;: Routes traffic to the server with the least active connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP Hashing&lt;/strong&gt;: Select the server based on the client's IP address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, we'll focus on implementing a &lt;strong&gt;Round Robin&lt;/strong&gt; load balancer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Round Robin algorithm?
&lt;/h3&gt;

&lt;p&gt;A round robin algorithm sends each incoming request to the next available server in a circular manner. If server A handles the first request, server B will handle the second, and server C will handle the third. Once all servers have received a request, it starts again from server A.&lt;/p&gt;

&lt;p&gt;Now, let's jump into the code and build our load balancer!&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Define the Load Balancer and Server
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;LoadBalancer&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Current&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Mutex&lt;/span&gt;   &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We'll first define a simple &lt;code&gt;LoadBalancer&lt;/code&gt; struct with a &lt;code&gt;Current&lt;/code&gt; field to keep track of which server should handle next request. The &lt;code&gt;Mutex&lt;/code&gt; ensures that our code is safe to use concurrently.&lt;/p&gt;

&lt;p&gt;Each server we load balance is defined by the &lt;code&gt;Server&lt;/code&gt; struct:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;URL&lt;/span&gt;       &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;
    &lt;span class="n"&gt;IsHealthy&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Mutex&lt;/span&gt;     &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, each server has a URL and an &lt;code&gt;IsHealthy&lt;/code&gt; flag, which indicates whether the server is available to handle requests.&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 2: Round Robin Algorithm
&lt;/h4&gt;

&lt;p&gt;The heart of our load balancer is the round robin algorithm. Here's how it works:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;LoadBalancer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;getNextServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;nextServer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;

        &lt;span class="n"&gt;nextServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;isHealthy&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;nextServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsHealthy&lt;/span&gt;
        &lt;span class="n"&gt;nextServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isHealthy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nextServer&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;This method loops through the list of servers in a round robin fashion. If the selected server is healthy, it returns that server to handle the incoming request. &lt;/li&gt;
&lt;li&gt;We are using &lt;code&gt;Mutex&lt;/code&gt; to ensure that only one goroutine can access and modify the &lt;code&gt;Current&lt;/code&gt; field of the load balancer at a time. This ensures that the round robin algorithm operates correctly when multiple requests are being processed concurrently. &lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;Server&lt;/code&gt; also has its own &lt;code&gt;Mutex&lt;/code&gt;. When we check the &lt;code&gt;IsHealthy&lt;/code&gt; field, we lock the server's &lt;code&gt;Mutex&lt;/code&gt; to prevent concurrent access from multiple goroutines.&lt;/li&gt;
&lt;li&gt;Without &lt;code&gt;Mutex&lt;/code&gt; locking it is possible that another goroutine could be changing the value which could result in reading an incorrect or inconsistent data.&lt;/li&gt;
&lt;li&gt;We unlock the &lt;code&gt;Mutex&lt;/code&gt; as soon as we have updated the &lt;code&gt;Current&lt;/code&gt; field or read the &lt;code&gt;IsHealthy&lt;/code&gt; field value to keep the critical section as small as possible. In this way, we are using &lt;code&gt;Mutex&lt;/code&gt; to avoid any race condition.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Step 3: Configuring the Load Balancer
&lt;/h4&gt;

&lt;p&gt;Our configuration is stored in a &lt;code&gt;config.json&lt;/code&gt; file, which contains the server URLs and health check intervals (more on it in below section).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Port&lt;/span&gt;                &lt;span class="kt"&gt;string&lt;/span&gt;   &lt;span class="s"&gt;`json:"port"`&lt;/span&gt;
    &lt;span class="n"&gt;HealthCheckInterval&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;   &lt;span class="s"&gt;`json:"healthCheckInterval"`&lt;/span&gt;
    &lt;span class="n"&gt;Servers&lt;/span&gt;             &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"servers"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The configuration file might look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"healthCheckInterval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5002"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5003"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5004"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5005"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Step 4: Health Checks
&lt;/h4&gt;

&lt;p&gt;We want to make sure that the servers are healthy before routing any incoming traffic to them. This is done by sending periodic health checks to each server:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;healthCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;healthCheckInterval&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;healthCheckInterval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s is down&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsHealthy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsHealthy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every few seconds (as specified in the config), the load balancer sends a &lt;code&gt;HEAD&lt;/code&gt; request to each server to check if it is healthy. If a server is down, the &lt;code&gt;IsHealthy&lt;/code&gt; flag is set to &lt;code&gt;false&lt;/code&gt;, preventing future traffic from being routed to it.&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 5: Reverse Proxy
&lt;/h4&gt;

&lt;p&gt;When the load balancer receives a request, it forwards the request to the next available server using a &lt;strong&gt;reverse proxy&lt;/strong&gt;. In Golang, the &lt;code&gt;httputil&lt;/code&gt; package provides a built-in way to handle reverse proxying, and we will use it in our code through the &lt;code&gt;ReverseProxy&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ReverseProxy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;httputil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReverseProxy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;httputil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSingleHostReverseProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  What is a Reverse Proxy?
&lt;/h5&gt;

&lt;p&gt;A reverse proxy is a server that sits between a client and one or more backend severs. It receives the client's request, forwards it to one of the backend servers, and then returns the server's response to the client. The client interacts with the proxy, unaware of which specific backend server is handling the request.&lt;/p&gt;

&lt;p&gt;In our case, the load balancer acts as a reverse proxy, sitting in front of multiple servers and distributing incoming HTTP requests across them.&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 6: Handling Requests
&lt;/h4&gt;

&lt;p&gt;When a client makes a request to the load balancer, it selects the next available healthy server using the round robin algorithm implementation in &lt;code&gt;getNextServer&lt;/code&gt; function and proxies the client request to that server. If no healthy server is available then we send service unavailable error to the client.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getNextServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"No healthy server available"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusServiceUnavailable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-Forwarded-Server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReverseProxy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;ReverseProxy&lt;/code&gt; method proxies the request to the actual server, and we also add a custom header &lt;code&gt;X-Forwarded-Server&lt;/code&gt; for debugging purposes (though in production, we should avoid exposing internal server details like this).&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 7: Starting the Load Balancer
&lt;/h4&gt;

&lt;p&gt;Finally, we start the load balancer on the specified port:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting load balancer on port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error starting load balancer: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Working Demo
&lt;/h3&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/d21e79861ce94e6b80abb0314854a43b"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;In this post, we built a basic load balancer from scratch in Golang using a round robin algorithm. This is a simple yet effective way to distribute traffic across multiple servers and ensure that your system can handle higher loads efficiently.&lt;/p&gt;

&lt;p&gt;There's a lot more to explore, such as adding sophisticated health checks, implementing different load balancing algorithms, or improving fault tolerance. But this basic example can be a solid foundation to build upon.&lt;/p&gt;

&lt;p&gt;You can find the source code in &lt;a href="https://github.com/VivekAlhat/go-load-balancer" rel="noopener noreferrer"&gt;this&lt;/a&gt; GitHub repo.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>go</category>
    </item>
    <item>
      <title>Building a tiny vector store from scratch</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Mon, 26 Aug 2024 20:10:25 +0000</pubDate>
      <link>https://dev.to/vivekalhat/building-a-tiny-vector-store-from-scratch-59ep</link>
      <guid>https://dev.to/vivekalhat/building-a-tiny-vector-store-from-scratch-59ep</guid>
      <description>&lt;p&gt;With the evolving landscape of generative AI, vector databases are playing crucial role in powering generative AI applications. There are so many vector databases currently available that are open source such as Chroma, Milvus along with other popular proprietary vector databases such as Pinecone, SingleStore. You can read the detailed comparison of different vector databases on this &lt;a href="https://superlinked.com/vector-db-comparison" rel="noopener noreferrer"&gt;site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But, have you ever wondered how these vector databases work behind the scenes? &lt;/p&gt;

&lt;p&gt;A great way to learn something is to understand how things work under the hood. In this article, we will be building a tiny in-memory vector store "&lt;strong&gt;Pixie&lt;/strong&gt;" from scratch using Python with only &lt;code&gt;NumPy&lt;/code&gt; as a dependency.&lt;/p&gt;

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




&lt;p&gt;Before diving into the code, let's briefly discuss what a vector store is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a vector store?
&lt;/h2&gt;

&lt;p&gt;A vector store is a database designed to store and retrieve vector embeddings efficiently. These embeddings are numerical representations of data (often text but could be images, audio etc.) that capture semantic meaning in a high-dimensional space. The key feature of a vector store is their ability to perform efficient similarity searches, finding the most relevant data points based on their vector representations. Vector stores can be used in many tasks such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Semantic search&lt;/li&gt;
&lt;li&gt;Retrieval augmented generation (RAG)&lt;/li&gt;
&lt;li&gt;Recommendation system&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Let's code
&lt;/h2&gt;

&lt;p&gt;In this article, we are going to create a tiny in-memory vector store called "&lt;strong&gt;Pixie&lt;/strong&gt;". While it won't have all the optimizations of a production-grade system, it will demonstrate the core concepts. Pixie will have two main functionalities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Storing document embeddings&lt;/li&gt;
&lt;li&gt;Performing similarity searches&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up the vector store
&lt;/h3&gt;

&lt;p&gt;First, we'll create a class called &lt;code&gt;Pixie&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;helpers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cosine_similarity&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pixie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embedder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;First, we import &lt;code&gt;numpy&lt;/code&gt; for efficient numerical operations and storing multi-dimensional arrays.&lt;/li&gt;
&lt;li&gt;We will also import &lt;code&gt;SentenceTransformer&lt;/code&gt; from &lt;code&gt;sentence_transformers&lt;/code&gt; library. We are using &lt;code&gt;SentenceTransformer&lt;/code&gt; for embeddings generation, but you could use any embedding model that converts text to vectors. In this article, our primary focus will be on vector store itself, and not on embeddings generation.&lt;/li&gt;
&lt;li&gt;Next, we'll initialize &lt;code&gt;Pixie&lt;/code&gt; class with an &lt;code&gt;embedder&lt;/code&gt;. The &lt;code&gt;embedder&lt;/code&gt; can be moved outside of the main vector store but for simplicity purposes, we'll initialize it inside the vector store class.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;self.store&lt;/code&gt; will hold our document embeddings as a NumPy array.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;self.embedder&lt;/code&gt; will hold the embedding model that we'll use to convert documents and queries into vectors.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Ingesting documents
&lt;/h3&gt;

&lt;p&gt;To ingest documents/data in our vector store, we'll implement the &lt;code&gt;from_docs&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;from_docs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ingested &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method does few key things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It takes a list of documents and stores them as a NumPy array in &lt;code&gt;self.docs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It uses the embedder model to convert each document into a vector embedding. These embeddings are stored in &lt;code&gt;self.store&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It returns a message confirming how many documents were ingested.
The &lt;code&gt;encode&lt;/code&gt; method of our embedder is doing the heavy lifting here, converting each text document into a high-dimensional vector representation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Performing similarity search
&lt;/h3&gt;

&lt;p&gt;The heart of our vector store is the similarity search function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;similarity_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;q_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;top_k_indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top_k_indices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We start by creating an empty list called &lt;code&gt;matches&lt;/code&gt; to store our matches.&lt;/li&gt;
&lt;li&gt;We &lt;code&gt;encode&lt;/code&gt; the user query using the same embedder model we used for ingesting the documents. This ensures that the query vector is in the same space as our document vectors.&lt;/li&gt;
&lt;li&gt;We call a &lt;code&gt;cosine_similarity&lt;/code&gt; function (which we'll define next) to find the most similar documents.&lt;/li&gt;
&lt;li&gt;We use the returned indices to fetch the actual documents from &lt;code&gt;self.docs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, we return the list of matching documents.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementing cosine similarity
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store_embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dot_product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store_embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;magnitude_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store_embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;magnitude_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dot_product&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;magnitude_a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;magnitude_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;argsort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;similarity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;top_k_indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;top_k_indices&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is doing several important things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It calculates the cosine similarity using the formula: cos(θ) = (A · B) / (||A|| * ||B||)&lt;/li&gt;
&lt;li&gt;First, we calculate the dot product between the query embeddings and all document embeddings in the store.&lt;/li&gt;
&lt;li&gt;Then, we compute the magnitudes (Euclidean norms) of all vectors.&lt;/li&gt;
&lt;li&gt;Lastly, we sort the found similarities and return the indices of the top-k most similar documents.
We are using cosine similarity because it measures the angle between vectors, ignoring their magnitudes. This means it can find semantically similar documents regardless of their length. &lt;/li&gt;
&lt;li&gt;There are other similarity metrics that you can explore such as:

&lt;ol&gt;
&lt;li&gt;Euclidean distance&lt;/li&gt;
&lt;li&gt;Dot product similarity&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;You can read more about cosine similarity &lt;a href="https://en.wikipedia.org/wiki/Cosine_similarity" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Piecing everything together
&lt;/h3&gt;

&lt;p&gt;Now that we have built all the pieces, let's understand how they work together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When we create a &lt;code&gt;Pixie&lt;/code&gt; instance, we provide it with an embedding model.&lt;/li&gt;
&lt;li&gt;When we ingest documents, we create vector embeddings for each document and store them in &lt;code&gt;self.store&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For a similarity search:

&lt;ol&gt;
&lt;li&gt;We create an embedding for the query.&lt;/li&gt;
&lt;li&gt;We calculate cosine similarity between the query embeddings and all document embeddings.&lt;/li&gt;
&lt;li&gt;We return the most similar documents.
All the magic happens inside the cosine similarity calculation. By comparing the angle between vectors rather than their magnitude, we can find semantically similar documents even if they use different words or phrasing.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Seeing it in action
&lt;/h2&gt;

&lt;p&gt;Now let's implement a simple RAG system using our &lt;strong&gt;Pixie&lt;/strong&gt; vector store. We'll ingest a story document of a "space battle &amp;amp; alien invasion" and then ask questions about it to see how it generates an answer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt;

&lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filterwarnings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;

&lt;span class="n"&gt;current_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;root_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;..&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pixie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pixie&lt;/span&gt;


&lt;span class="c1"&gt;# creating an instance of a pre-trained embedder model
&lt;/span&gt;&lt;span class="n"&gt;embedder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all-MiniLM-L6-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# creating an instance of Pixie vector store
&lt;/span&gt;&lt;span class="n"&gt;pixie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pixie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# generate an answer using llama3 and context docs
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example/spacebattle.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# ingesting the data into vector store
&lt;/span&gt;    &lt;span class="n"&gt;ingested&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pixie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_docs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ingested&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# system prompt
&lt;/span&gt;&lt;span class="n"&gt;PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    User has asked you following question and you need to answer it based on the below provided context. 
If you don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t find any answer in the given context then just say &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;I don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t have answer for that&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;. 
In the final answer, do not add &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;according to the context or as per the context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;. 
You can be creative while using the context to generate the final answer. DO NOT just share the context as it is.

    CONTEXT: {0}
    QUESTION: {1}

    ANSWER HERE:
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Ask anything: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask a question to continue...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/bye&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# search similar matches for query in the embedding store
&lt;/span&gt;    &lt;span class="n"&gt;similarities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pixie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;similarity_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, top &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;similarities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; matched results:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Matched Documents Start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;similarities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Matched Documents End&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;similarities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PROMPT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Question: {0}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Answer: {1}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ingested 8 documents

Ask anything: What was the invasion about?
query: What was the invasion about?, top 5 matched results:

----- Matched Documents Start -----
Epilogue: A New Dawn
Years passed, and the alliance between humans and Zorani flourished. Together, they rebuilt what had been lost, creating a new era of exploration and cooperation. The memory of the Krell invasion served as a stark reminder of the dangers that lurked in the cosmos, but also of the strength that came from unity. Admiral Selene Cortez retired, her name etched in the annals of history. Her legacy lived on in the new generation of leaders who continued to protect and explore the stars. And so, under the twin banners of Earth and Zorani, the galaxy knew peace—a fragile peace, hard-won and deeply cherished.

Chapter 3: The Invasion
Kael's warning proved true. The Krell arrived in a wave of bio-mechanical ships, each one bristling with organic weaponry and shields that regenerated like living tissue. Their tactics were brutal and efficient. The Titan Fleet, caught off guard, scrambled to mount a defense. Admiral Cortez's voice echoed through the corridors of the Prometheus. "All hands to battle stations! Prepare to engage!" The first clash was catastrophic. The Krell ships, with their organic hulls and adaptive technology, sliced through human defenses like a knife through butter. The outer rim colonies fell one by one, each defeat sending a shockwave of despair through the fleet. Onboard the Prometheus, Kael offered to assist, sharing Zorani technology and knowledge. Reluctantly, Cortez agreed, integrating Kael’s insights into their strategy. New energy weapons were developed, capable of piercing Krell defenses, and adaptive shields were installed to withstand their relentless attacks.

Chapter 5: The Final Battle
Victory on Helios IV was a much-needed morale boost, but the war was far from over. The Krell regrouped, launching a counter-offensive aimed directly at Earth. Every available ship was called back to defend humanity’s homeworld. As the Krell armada approached, Earth’s skies filled with the largest fleet ever assembled. The Prometheus led the charge, flanked by newly built warships and the remaining Zorani vessels that had joined the fight. "This is it," Cortez addressed her crew. "The fate of our species depends on this battle. We hold the line here, or we perish." The space above Earth turned into a maelstrom of fire and metal. Ships collided, energy beams sliced through the void, and explosions lit up the darkness. The Krell, relentless and numerous, seemed unbeatable. In the midst of chaos, Kael revealed a hidden aspect of Zorani technology—a weapon capable of creating a singularity, a black hole that could consume the Krell fleet. It was a desperate measure, one that could destroy both fleets. Admiral Cortez faced an impossible choice. To use the weapon would mean sacrificing the Titan Fleet and potentially Earth itself. But to do nothing would mean certain destruction at the hands of the Krell. "Activate the weapon," she ordered, her voice heavy with resolve. The Prometheus moved into position, its hull battered and scorched. As the singularity weapon charged, the Krell ships converged, sensing the threat. In a blinding burst of light, the weapon fired, tearing the fabric of space and creating a black hole that began to devour everything in its path.

Chapter 1: The Warning
It began with a whisper—a distant signal intercepted by the outermost listening posts of the Titan Fleet. The signal was alien, unlike anything the human race had ever encountered. For centuries, humanity had expanded its reach into the cosmos, colonizing distant planets and establishing trade routes across the galaxy. The Titan Fleet, the pride of Earth's military might, stood as the guardian of these far-flung colonies.Admiral Selene Cortez, a seasoned commander with a reputation for her sharp tactical mind, was the first to analyze the signal. As she sat in her command center aboard the flagship Prometheus, the eerie transmission played on a loop. It was a distress call, but its origin was unknown. The message, when decoded, revealed coordinates on the edge of the Andromeda Sector. "Set a course," Cortez ordered. The fleet moved with precision, a testament to years of training and discipline.

Chapter 4: Turning the Tide
The next battle, over the resource-rich planet of Helios IV, was a turning point. Utilizing the new technology, the Titan Fleet managed to hold their ground. The energy weapons seared through Krell ships, and the adaptive shields absorbed their retaliatory strikes. "Focus fire on the lead ship," Cortez commanded. "We break their formation, we break their spirit." The flagship of the Krell fleet, a massive dreadnought known as Voreth, was targeted. As the Prometheus and its escorts unleashed a barrage, the Krell ship's organic armor struggled to regenerate. In a final, desperate maneuver, Cortez ordered a concentrated strike on Voreth's core. With a blinding flash, the dreadnought exploded, sending a ripple of confusion through the Krell ranks. The humans pressed their advantage, driving the Krell back.
----- Matched Documents End -----


Question: What was the invasion about?
Answer: The Krell invasion was about the Krell arriving in bio-mechanical ships with organic weaponry and shields that regenerated like living tissue, seeking to conquer and destroy humanity.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;We have successfully built a tiny in-memory vector store from scratch by using Python and NumPy. While it is very basic, it demonstrates the core concepts such as vector storage, and similarity search. Production grade vector stores are much more optimized and feature-rich.&lt;/p&gt;

&lt;p&gt;Github repo: &lt;a href="https://github.com/VivekAlhat/Pixie" rel="noopener noreferrer"&gt;Pixie&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding, and may your vectors always point in the right direction!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Load Balancers in AWS</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sun, 30 Jun 2024 18:12:23 +0000</pubDate>
      <link>https://dev.to/vivekalhat/load-balancers-in-aws-5gbb</link>
      <guid>https://dev.to/vivekalhat/load-balancers-in-aws-5gbb</guid>
      <description>&lt;p&gt;Load balancers are servers that forward traffic to multiple servers downstream. They are crucial for distributing incoming traffic across different servers such as EC2 instances, in multiple Availability Zones. This increases high availability of your application. A load balancer ensures that no single server bears too much load, thus enhancing the performance and reliability of your application.&lt;/p&gt;

&lt;p&gt;AWS Elastic Load Balancer (ELB) is a managed load balancer. It is integrated with many AWS services including EC2, ECS, Route53, and CloudWatch. While it might be costlier than setting up your own load balancer, the time and effort saved in managing and configuring ELB make it a preferred choice for many.&lt;/p&gt;

&lt;p&gt;AWS Elastic Load Balancer has following types of managed load balancers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Classic Load Balancer (old generation)&lt;/li&gt;
&lt;li&gt;Application Load Balancer&lt;/li&gt;
&lt;li&gt;Network Load Balancer&lt;/li&gt;
&lt;li&gt;Gateway Load Balancer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Classic Load Balancer (CLB) comes under the old generation in AWS. It is recommended to use the newer generation of load balancers as they provide more features.&lt;/p&gt;

&lt;p&gt;Following are some of the key features of load balancers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They distribute traffic across multiple downstream instances, ensuring efficient handling of requests.&lt;/li&gt;
&lt;li&gt;They provide a single DNS point of access for your application.&lt;/li&gt;
&lt;li&gt;They can seamlessly manage failures in downstream instances.&lt;/li&gt;
&lt;li&gt;They perform regular health checks on your instances to ensure only healthy instances receive traffic.&lt;/li&gt;
&lt;li&gt;They can operate across multiple AZs for high availability.&lt;/li&gt;
&lt;li&gt;They can segment public and private traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we will explore Application Load Balancer (ALB) in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Load Balancer (ALB)
&lt;/h3&gt;

&lt;p&gt;An Application Load Balancer (ALB) operates at application layer of the OSI model making it ideal for HTTP/HTTPS traffic. It supports advanced routing mechanisms such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Path based routing&lt;/li&gt;
&lt;li&gt;Hostname based routing&lt;/li&gt;
&lt;li&gt;Query string or header based routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ALB can route traffic to multiple target groups, including EC2 instances, ECS tasks, Lambda functions, or private IP addresses. It supports modern HTTP, HTTPS, HTTP/2, WebSocket protocols. ALB provides a single DNS name that clients can use to access your application thus simplifying DNS management.&lt;/p&gt;

&lt;p&gt;Let's create a simple Application Load Balancer between two EC2 instances. The purpose of this load balancer will be to distribute traffic to EC2 instances. To follow the below steps, you need to create minimum 2 EC2 instances. You can refer &lt;a href="https://dev.to/vivekalhat/beginners-guide-to-aws-ec2-2adk"&gt;this&lt;/a&gt; article to learn about creating a new EC2 instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps for creating a new Application Load Balancer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On EC2 homepage, select &lt;code&gt;Load Balancers&lt;/code&gt; option in the menu and click on &lt;code&gt;Create load balancer&lt;/code&gt; option.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2vwfidz5guvlnyzkqa3.png" alt="ALB 1" width="800" height="208"&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Application Load Balancer&lt;/code&gt; as a type and click create.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiyhwofnhfbvjyhqhvz8.png" alt="ALB 2" width="799" height="769"&gt;
&lt;/li&gt;
&lt;li&gt;Give a name to the load balancer, select internet facing as a scheme and &lt;code&gt;IPv4&lt;/code&gt; as IP address type.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfb5yi0g1f730iwv36rm.png" alt="ALB 3" width="800" height="405"&gt;
&lt;/li&gt;
&lt;li&gt;Select availability zone mapping in which load balancer will route the traffic.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkgpvd6lylhssvodaqf6.png" alt="ALB 4" width="800" height="592"&gt;
&lt;/li&gt;
&lt;li&gt;Select or create a new security group for load balancer. You can add inbound rules specific to your use case to allow traffic to the EC2 instances.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvcp7eu7ozyud2dijkyc.png" alt="ALB 5" width="800" height="181"&gt;
&lt;/li&gt;
&lt;li&gt;Create a new target group to which load balancer will route the incoming traffic. In this example, we will be routing the traffic via load balancers to two EC2 instances.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrkst15jes8olhpjnydt.png" alt="ALB 6" width="800" height="376"&gt;
&lt;/li&gt;
&lt;li&gt;On &lt;code&gt;Create target group&lt;/code&gt; page, select &lt;code&gt;Instances&lt;/code&gt; as a target type and add a name for the target group. You can keep other settings as default.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphurrm0lorkpqf16sy72.png" alt="ALB 7" width="799" height="232"&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m1cib1p6jpumboucdx1.png" alt="ALB 8" width="796" height="435"&gt;
&lt;/li&gt;
&lt;li&gt;On the register targets page, select the EC2 instances to which load balancer will route the incoming traffic and click on &lt;code&gt;Include as pending below&lt;/code&gt; option. After registering the targets, click on &lt;code&gt;Create target group&lt;/code&gt; option.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlx7m2jl2nsq6mtwg8ls.png" alt="ALB 9" width="800" height="469"&gt;
&lt;/li&gt;
&lt;li&gt;Select the newly created target group in load balancer configuration page under &lt;code&gt;Listening and routing section&lt;/code&gt;.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkycndshtl7mt1el3vvyz.png" alt="ALB 10" width="800" height="388"&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Create load balancer&lt;/code&gt; option to create a new load balancer to route traffic between the selected target group based on the configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After creating a new load balancer, any incoming traffic to the EC2 instances will be handled by the rules mentioned in the load balancer. You can also specify custom rules inside the load balancer. Let's create a new custom rule to handle error route in the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a custom rule in Load Balancer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Select the load balancer and under &lt;code&gt;Listeners and rules&lt;/code&gt; section, select the default &lt;code&gt;HTTP:80&lt;/code&gt; listener.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdw92uknzd8k7c1vwq910.png" alt="Rule 1" width="800" height="171"&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Add rule&lt;/code&gt; option and add a name to the custom rule.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjdpqqb0fzshxfquort7.png" alt="Rule 2" width="800" height="377"&gt;
&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;Define rule conditions&lt;/code&gt;, add a path based condition to match &lt;code&gt;/error&lt;/code&gt; path.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc31paep9jy7c8p76svch.png" alt="Rule 3" width="800" height="513"&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;Define rule actions&lt;/code&gt;, select &lt;code&gt;Return fixed response&lt;/code&gt; option add a response body to be displayed when the &lt;code&gt;/error&lt;/code&gt; route is accessed.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekz1g1lzcdedd2a3fx9u.png" alt="Rule 4" width="800" height="714"&gt;
&lt;/li&gt;
&lt;li&gt;Set rule priority as &lt;code&gt;1&lt;/code&gt; and click next and create the custom rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After creating a custom rule, if you access the &lt;code&gt;/error&lt;/code&gt; path on the Load Balancer's DNS address, you will see the custom error response body as configured.&lt;/p&gt;

&lt;p&gt;In this way, you can create a load balancer and custom rules using AWS Elastic Load Balancer. You can refer the official user &lt;a href="https://aws.amazon.com/elasticloadbalancing/" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to learn more about load balancing in AWS.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Scaling databases with AWS RDS and read replicas</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sun, 30 Jun 2024 07:41:42 +0000</pubDate>
      <link>https://dev.to/vivekalhat/scaling-databases-with-aws-rds-and-read-replicas-58h9</link>
      <guid>https://dev.to/vivekalhat/scaling-databases-with-aws-rds-and-read-replicas-58h9</guid>
      <description>&lt;p&gt;Amazon Web Services (AWS) Relational Database Service (RDS) is a managed service that simplifies the process of configuring, operating, and scaling a relational database in the cloud. AWS RDS is a versatile choice that supports several database engines including PostgreSQL, MySQL, Oracle, MariaDB, Microsoft SQL Server, and Amazon's own Aurora.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of using RDS over a self hosted database
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Managed Service&lt;/strong&gt; - AWS RDS is a fully managed service, which means that AWS takes care of provisioning, patching, backup, recovery, and even scaling. This allows developers and database administrators to focus on the application development and optimization rather than managing the underlying infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Backups&lt;/strong&gt; - RDS provides continuous backups based on a defined retention period. It ensures that your data is always protected and can be restored when necessary. This automatic backup process eliminates the risk of data loss due to unforeseen events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Point in Time Restore&lt;/strong&gt; - With RDS, you can restore your database to any specific point within your backup retention period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read Replicas&lt;/strong&gt; - RDS supports the creation of read-only replicas of the master database. This helps in reducing the load on the primary database. Read replicas are ideal for read-heavy applications. This helps in distributing the read traffic and increasing the performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring Dashboards&lt;/strong&gt; - AWS CloudWatch integration allows you to monitor key metrics such as network traffic, CPU utilization, disk I/O, and memory usage without the need of any third-party tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creating a new database
&lt;/h3&gt;

&lt;p&gt;AWS RDS provides two methods for creating a new database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standard create&lt;/strong&gt; - You can set all the configuration options including for availability, security, backups and maintenance. You have full control on configuring your database needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy create&lt;/strong&gt; - It uses recommended best-practice configurations. Some configurable options can be changed even after the database is created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's create a new PostgreSQL database using easy create method.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select &lt;code&gt;Easy create&lt;/code&gt; method for database creation.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5f6y5ggntk9jnm19gldv.png" alt="Database Creation Method" width="800" height="187"&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;PostgreSQL&lt;/code&gt; as a database engine.&lt;/li&gt;
&lt;li&gt;Select your preferred database instance size. You can select either production, dev/test, or free tier if applicable.&lt;/li&gt;
&lt;li&gt;Add a name for your database instance and for master user.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftzs668gg6umhzdi5rnsx.png" alt="Database Identifier" width="800" height="256"&gt;
&lt;/li&gt;
&lt;li&gt;You can configure the credentials manager as AWS Secrets Manager or self manage the credentials.&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Create database&lt;/code&gt; option to create your new &lt;code&gt;PostgreSQL&lt;/code&gt; database.&lt;/li&gt;
&lt;li&gt;It takes a couple of minutes to get a new database up and running on AWS cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Auto Scaling RDS
&lt;/h3&gt;

&lt;p&gt;RDS Auto Scaling helps in dynamically increasing the storage capacity of your database instance without manual intervention. This feature is particularly useful for applications with unpredictable workloads. You can set &lt;code&gt;Maximum Storage Threshold&lt;/code&gt;, which is the highest limit for database storage to prevent infinite scaling. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1sm9n1sg709mvun28md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1sm9n1sg709mvun28md.png" alt="Auto Scaling RDS" width="347" height="236"&gt;&lt;/a&gt;&lt;br&gt;
RDS auto scales under the following conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Storage is less than 10%.&lt;/li&gt;
&lt;li&gt;Low storage lasts for at least 5 minutes.&lt;/li&gt;
&lt;li&gt;6 hours have passed since the last storage modification.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Read Replica
&lt;/h3&gt;

&lt;p&gt;Read replica is one of the powerful feature of RDS that allow you to create up to 15 read-only copies of your primary database. These replicas can be located within the same availability zone (AZ), across different AZs, or even in different regions.&lt;/p&gt;

&lt;p&gt;Key benefits of using Read Replicas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can offload the read traffic to read replicas. This significantly reduces the load on primary database thus enhances overall performance.&lt;/li&gt;
&lt;li&gt;Read replicas can be promoted to a standalone database in case of a failure of the primary database. It helps in disaster recovery.&lt;/li&gt;
&lt;li&gt;You can scale your read-heavy applications by distributing read traffic across multiple replicas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following things you should consider while creating a replica:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data replication to read replicas is asynchronous. It means there could be a slight delay which is also known as replication lag before changes in the primary database are reflected in the replicas.&lt;/li&gt;
&lt;li&gt;Applications must use the specific connections strings for read replicas to route the read traffic appropriately.&lt;/li&gt;
&lt;li&gt;Replication within the same region is free but cross region replication incurs additional cost.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's create a read replica of the database that we created before.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select &lt;code&gt;Create read replica&lt;/code&gt; option from the actions menu of database homepage.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1cate1vf2f0xvllb75u.png" alt="Action Menu" width="655" height="411"&gt;
&lt;/li&gt;
&lt;li&gt;Select the replica source and add a replica database instance identifier.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtqbt5ah0yipz93pxo3d.png" alt="Replica Source" width="800" height="280"&gt;
&lt;/li&gt;
&lt;li&gt;You can select the destination region where the replica will be launched.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93c78s0l2xa8pnm7w7rd.png" alt="Replica Region" width="800" height="472"&gt;
&lt;/li&gt;
&lt;li&gt;Configure other settings as required and click on &lt;code&gt;Create read replica&lt;/code&gt; option to create a read replica of your primary database instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  RDS Multi AZ for Disaster Recovery
&lt;/h3&gt;

&lt;p&gt;RDS multi AZ deployments provide high availability and reliability for database instances. In a multi AZ setup, any changes made to the primary database are synchronously replicated to a standby instance in a different availability zone (AZ). This ensures that the standby instance in another AZ is always up-to-date with the primary database.&lt;/p&gt;

&lt;p&gt;Key features of multi AZ deployments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Failover&lt;/strong&gt; - In the event of a failure in the primary database, RDS automatically switches to the standby instance in another AZ. This ensures continuous operation with minimal downtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Availability&lt;/strong&gt; - Multi AZ deployments are designed for high availability and disaster recovery. They are not meant for scaling read operations. However, you can combine multi AZ setup with read replicas for additional disaster recovery capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can refer the official user &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to learn more about AWS RDS.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Beginners guide to AWS EC2</title>
      <dc:creator>Vivek Alhat</dc:creator>
      <pubDate>Sun, 31 Mar 2024 11:04:33 +0000</pubDate>
      <link>https://dev.to/vivekalhat/beginners-guide-to-aws-ec2-2adk</link>
      <guid>https://dev.to/vivekalhat/beginners-guide-to-aws-ec2-2adk</guid>
      <description>&lt;p&gt;AWS EC2 stands for Elastic Compute Cloud. It is one of the most popular and widely used service offered by AWS. EC2 is a foundational pillar in the digital landscape of AWS ecosystem. It offers flexible and scalable infrastructure for businesses to thrive in the cloud. &lt;/p&gt;

&lt;p&gt;With EC2 users can provision virtual servers within minutes, choosing from diverse instance types tailored to specific workload requirements. Before EC2, managing computing resources posed challenges such as upfront investments in hardware and inefficient scaling. With EC2, businesses can provision servers on-demand, paying only for what they use, leading to increased agility, scalability, and innovation.&lt;/p&gt;

&lt;p&gt;Following are different types of instance types EC2 provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;General purpose&lt;/li&gt;
&lt;li&gt;Compute optimized&lt;/li&gt;
&lt;li&gt;Memory optimized&lt;/li&gt;
&lt;li&gt;Storage optimized&lt;/li&gt;
&lt;li&gt;Accelerated computing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find more details about different instance types &lt;a href="https://aws.amazon.com/ec2/instance-types/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launching a new instance
&lt;/h2&gt;

&lt;p&gt;To launch a new EC2 instance, go to EC2 dashboard page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on “Launch instances” button.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Give a name to the EC2 instance. Under “Application and OS images (AMI)” section. Select any available AMI. I have selected “Amazon Linux” as the AMI for this instance. An AMI, or Amazon Machine Image is a pre-configured template used to create virtual machines (instances) within EC2. It serves as a blueprint for launching EC2 instances, providing the necessary operating system, software packages, configurations, and even data stored on the instance’s root volume.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Select an appropriate instance type as per your use case and workload. For the current instance  I am going with &lt;code&gt;t2.micro&lt;/code&gt; type of instance. Create a new key pair login credentials. A key pair login is a security credentials that you can use to prove your identity when connecting to the EC2 instance.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Under the “Network settings”, you can configure a firewall and network settings for the EC2 instance. You can create a security group and specify inbound and outbound traffic rules to restrict access to the EC2 instance. We will discuss more about security groups in later sections.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;You can also configure storage for EC2 instance. AWS also offers EBS (Elastic Block Store), an easy-to-use, scalable block store service that you can use for EC2. For now, I am keeping the default configuration for storage.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Once you are done configuring the instance, click on “Launch instance” button to start the instance. After the instance is successfully launched. You can see its details in the “instances” section of EC2 dashboard.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Instance Operations
&lt;/h2&gt;

&lt;p&gt;You can stop, terminate, or reboot an EC2 instance from the dashboard by selecting the instance and clicking on “Instance state” option.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Security Groups
&lt;/h2&gt;

&lt;p&gt;A security group acts as a virtual firewall for EC2. Security groups are used to control the inbound and outbound traffic for an EC2 instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inbound rules&lt;/strong&gt;: these rules define the incoming traffic allowed to reach the EC2 instances. You can configure inbound rules to permit specific IP addresses, ranges, or protocols (such as SSH for remote access or HTTP for web traffic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outbound rules&lt;/strong&gt;: these rules define the traffic allowed to leave the EC2 instances. These rules control the communication initiated by the instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A security group can be used with multiple EC2 instances and it can also reference another security group. Security groups are region/VPC specific which means that a security group created in &lt;code&gt;ap-south-1&lt;/code&gt; cannot be used in &lt;code&gt;ap-northeast-3&lt;/code&gt; region.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to EC2 instance
&lt;/h2&gt;

&lt;p&gt;Primarily there are two ways of connecting to an EC2 instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSH&lt;/strong&gt;: You can connect to the instance using SSH. To connect using SSH you need to prove your identity using a key value pair that we created when launching the instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Instance Connect&lt;/strong&gt;: Using this way, you can connect to the instance using browser based SSH client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view more options on how to connect to the instance. Click on “Connect” button after selecting the instance from the dashboard page.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>aws</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
