<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Back-End Stuff]]></title><description><![CDATA[Back-End Stuff]]></description><link>https://blogs.thedefycode.org</link><generator>RSS for Node</generator><lastBuildDate>Thu, 14 May 2026 21:23:17 GMT</lastBuildDate><atom:link href="https://blogs.thedefycode.org/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Build a Custom Connection Pool in Go]]></title><description><![CDATA[Recently, I worked on a project where I had to implement dynamic connection pooling. I know it sounds strange, and I thought it would be as complex as it sounds. But trust me, it's actually quite easy. Let me share the whole story with you.

Let's be...]]></description><link>https://blogs.thedefycode.org/pools</link><guid isPermaLink="true">https://blogs.thedefycode.org/pools</guid><category><![CDATA[#connections]]></category><category><![CDATA[Pools]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[connection pool]]></category><category><![CDATA[DatabaseConnectionPool]]></category><dc:creator><![CDATA[Anshul]]></dc:creator><pubDate>Sat, 26 Apr 2025 11:10:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747821779565/29969dfb-34c4-4ad2-bea8-439b585be6f5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<blockquote>
<p>Recently, I worked on a project where I had to implement dynamic connection pooling. I know it sounds strange, and I thought it would be as complex as it sounds. But trust me, it's actually quite easy. Let me share the whole story with you.</p>
</blockquote>
<p>Let's begin. I hope you know a little about networking and backend stuff. I was trying to send data to a custom processing server over a TCP connection. I needed a connection pool that would let me process data simultaneously over TCP connections and send responses back through these connections.</p>
<p>So, I chose the most popular language known for its concurrency performance, and <mark>yes, you guessed it right, it's Golang.</mark> It made it very easy to create a connection pool from scratch.</p>
<p>Alright, let's get to the point. I used goroutines to manage the concurrent processing. To efficiently share some TCP connections between goroutines, I used channels in GoLang.</p>
<hr />
<h2 id="heading-here-are-the-steps">Here are the steps:</h2>
<h3 id="heading-step-1-represent-the-pool">Step 1: Represent the pool</h3>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Pool <span class="hljs-keyword">struct</span> {
    addr      <span class="hljs-keyword">string</span>        <span class="hljs-comment">// the server address we want to connect to</span>
    min       <span class="hljs-keyword">int</span>           <span class="hljs-comment">// minimum number of connections to start the pool with</span>
    max       <span class="hljs-keyword">int</span>           <span class="hljs-comment">// maximum number of connections the pool can handle</span>
    active    <span class="hljs-keyword">int</span>           <span class="hljs-comment">// current number of active (open/available) connections</span>
    mutx      sync.Mutex    <span class="hljs-comment">// used to safely update 'active' when adding/removing connections</span>
    idle_conn <span class="hljs-keyword">chan</span> net.Conn <span class="hljs-comment">// channel that holds idle (ready-to-use) connections</span>
    timeout   time.Duration <span class="hljs-comment">// how long to wait when trying to create a new TCP connection</span>
}
</code></pre>
<h3 id="heading-step-2-how-to-make-a-pool">Step 2 : How To Make a Pool</h3>
<pre><code class="lang-go">
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewPool</span><span class="hljs-params">(addr <span class="hljs-keyword">string</span>, min <span class="hljs-keyword">int</span>, max <span class="hljs-keyword">int</span>, timeout time.Duration)</span> *<span class="hljs-title">Pool</span></span> {
    pool := &amp;Pool{ <span class="hljs-comment">// creating a new pool</span>
        addr:      addr,
        min:       min,
        max:       max,
        idle_conn: <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> net.Conn, max), <span class="hljs-comment">// creating a new channel with length as max </span>
        timeout:   timeout,
        active:    <span class="hljs-number">0</span>,
    }
    <span class="hljs-comment">// Channels are like a way for goroutines (tiny, lightweight threads) to chat and collaborate.</span>

    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; min; i++ { <span class="hljs-comment">// seeding the pool with some intial set of connections</span>
        conn, err := net.DialTimeout(<span class="hljs-string">"tcp"</span>, addr, timeout) <span class="hljs-comment">// creating a new connection</span>

        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            cfg.ERRORLogger.Log.Panic(err) <span class="hljs-comment">// it's just a custom logger i have creating for </span>
            <span class="hljs-comment">// better logging</span>
        }

        pool.idle_conn &lt;- conn <span class="hljs-comment">// pushing new connection to the channel</span>
        pool.active++ <span class="hljs-comment">// updating no. of available connections free to use.</span>
    }

    <span class="hljs-keyword">return</span> pool
}
<span class="hljs-comment">// That's it our new pool is created and ready to use with some set of intial connections.</span>
<span class="hljs-comment">// The intial number of connections is defined by "min" passed to the function.</span>
</code></pre>
<ul>
<li><p>We set up a new pool with a few initial connections.</p>
</li>
<li><p>Now, this pool keeps these connections ready to go. Whenever a function or Go routine needs to send data to the server, it borrows a connection from the pool. Once it's done, it returns the connection back to the pool. I'll show you how this works in the steps below.</p>
</li>
<li><p><mark>By keeping a bunch of connections with the server always ready and active, we boost the system's performance. </mark> This way, we don't have to create a new connection for every Go routine and drop it after each use.</p>
</li>
</ul>
<hr />
<p>Now up to this point, we've tackled most of the tricky stuff. All that's left is to figure out a way to grab a connection from the pool and then put it back when we're done.</p>
<h3 id="heading-step-3-how-to-borrow-a-connection-from-the-pool">Step 3 : How to Borrow a Connection from the Pool</h3>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(pool *Pool)</span> <span class="hljs-title">Get</span><span class="hljs-params">()</span> <span class="hljs-params">(net.Conn, error)</span></span> {
    <span class="hljs-keyword">select</span> {
    <span class="hljs-keyword">case</span> conn := &lt;-pool.idle_conn: <span class="hljs-comment">// borrow a new connetion from that channel/pool we have created and store it in conn</span>
        <span class="hljs-keyword">return</span> conn, <span class="hljs-literal">nil</span> <span class="hljs-comment">// return that connection</span>

    <span class="hljs-comment">// Remember, we never pushed the pool to its limits. </span>
    <span class="hljs-comment">// We just set it up with a small number of connections, say 10. </span>
    <span class="hljs-comment">// Now, if you try to do more work than that, the pool won't have a connection</span>
    <span class="hljs-comment">// ready for you.</span>

    <span class="hljs-comment">// So, to deal with that, we say if our pool hasn't reached its max limit yet,</span>
    <span class="hljs-comment">// we can just create a new connection on the fly, use it, and then put it back </span>
    <span class="hljs-comment">// in the pool.</span>
    <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">if</span> pool.active &lt; pool.max {
            conn, err := net.DialTimeout(<span class="hljs-string">"tcp"</span>, pool.addr, pool.timeout)

            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, err
            }

            pool.active++
            <span class="hljs-keyword">return</span> conn, <span class="hljs-literal">nil</span>
        } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// But if our pool has hit its limit, we'll just hang tight </span>
    <span class="hljs-comment">// and wait for an idle connection.</span>
            <span class="hljs-keyword">return</span> &lt;-pool.idle_conn, <span class="hljs-literal">nil</span>
        }
    }
}
</code></pre>
<hr />
<p><mark>With lots of connections, we also have the responsibility to return them so others can use them efficiently.</mark></p>
<p>Let's wrap this up with one final touch.</p>
<h3 id="heading-step-4-how-to-return-a-connection-back-to-the-pool">Step 4. How to Return a Connection Back to the Pool</h3>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(pool *Pool)</span> <span class="hljs-title">Put</span><span class="hljs-params">(conn net.Conn)</span></span> {
    <span class="hljs-keyword">select</span> {
    <span class="hljs-keyword">case</span> pool.idle_conn &lt;- conn: <span class="hljs-comment">// trying to put this connection back into the pool for later use</span>
    <span class="hljs-keyword">default</span>: <span class="hljs-comment">// but what if our pool is already full</span>
        conn.Close() <span class="hljs-comment">// Close the connection if there's no space to keep it.</span>
        <span class="hljs-comment">// Then, lock the pool, decrease the active count by 1, and unlock it.</span>
        pool.mutx.Lock() 
        pool.active--
        pool.mutx.Unlock()
    }
}
</code></pre>
<hr />
<p>Congratulations! You've just learned how easy it is to create your own connection pooling setup.</p>
<p>Let's check out how to use this in action!</p>
<pre><code class="lang-go">
<span class="hljs-keyword">var</span> GlobalPool = pools.NewPool(<span class="hljs-string">"127.0.0.1:6379"</span>, <span class="hljs-number">10</span>, <span class="hljs-number">100</span>, <span class="hljs-number">10</span>*time.Second)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">UseConnectionFromGlobalPool</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
    <span class="hljs-comment">// Get a connection from the global pool</span>
    conn, err := GlobalPool.Get()
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span> err <span class="hljs-comment">// return if getting connection failed</span>
    }
    <span class="hljs-comment">// Always put back the connection when done</span>
    <span class="hljs-keyword">defer</span> GlobalPool.Put(conn)

    <span class="hljs-comment">// Do your work with the connection here</span>
    <span class="hljs-comment">// For example: send/receive data using conn</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">// success</span>
}
</code></pre>
<hr />
<p>Thank you for reading! If you enjoyed this post and want to stay updated with more insights and tips, make sure to follow me for more content like this. Happy coding!</p>
]]></content:encoded></item></channel></rss>