<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss/styles.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Rimrachai&apos;s Dev Notes</title><description>Notes on building software, one commit at a time.</description><link>https://blog.rimrachai.com/</link><language>en-us</language><item><title>Why a Smaller Connection Pool Makes Your Database Faster</title><link>https://blog.rimrachai.com/blogs/database-connection-pool-sizing/</link><guid isPermaLink="true">https://blog.rimrachai.com/blogs/database-connection-pool-sizing/</guid><description>More database connections doesn&apos;t mean more throughput. Here&apos;s the math behind why a pool of 10-20 connections often outperforms one with hundreds, and the formula to size yours correctly.</description><pubDate>Mon, 30 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I used to think more database connections meant better performance. I was wrong and the real answer surprised me.&lt;/p&gt;
&lt;h2 id=&quot;a-real-scenario&quot;&gt;A Real Scenario&lt;/h2&gt;
&lt;p&gt;Say you have 10,000 concurrent users hitting your app. How big should your connection pool be?&lt;/p&gt;
&lt;p&gt;10,000? 1,000? 500?&lt;/p&gt;
&lt;p&gt;Try 10. Yes, ten.&lt;/p&gt;
&lt;h2 id=&quot;why-thats-not-a-typo&quot;&gt;Why That’s Not a Typo&lt;/h2&gt;
&lt;p&gt;Your database is bottlenecked by three things: CPU, disk, and network not connection count.&lt;/p&gt;
&lt;p&gt;A 4-core server can only do four things at once. Throwing 500 connections at it doesn’t give you 500x throughput. It gives you 500 threads fighting over 4 cores, with the operating system burning cycles just switching between them. That overhead is called &lt;strong&gt;context switching&lt;/strong&gt;, and it’s pure waste.&lt;/p&gt;
&lt;h2 id=&quot;so-why-not-exactly-4-connections&quot;&gt;So Why Not Exactly 4 Connections?&lt;/h2&gt;
&lt;p&gt;Because of I/O wait.&lt;/p&gt;
&lt;p&gt;When a query hits disk, that thread just sits there blocked, doing nothing, while the CPU sits idle. So it makes sense to let another thread step in and use that idle CPU time up to a point.&lt;/p&gt;
&lt;p&gt;This is the reasoning behind a formula the PostgreSQL community has used for pool sizing:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.t05yi.css&quot;&gt;&lt;script type=&quot;module&quot; src=&quot;/_astro/ec.0vx5m.js&quot;&gt;&lt;/script&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e1e4e8;--1:#24292e&quot;&gt;connections = (core_count × 2) + effective_spindle_count&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;connections = (core_count × 2) + effective_spindle_count&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For a 4-core server with one HDD:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#e1e4e8;--1:#24292e&quot;&gt;(4 × 2) + 1 = 9 → round up to 10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;(4 × 2) + 1 = 9 → round up to 10&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For SSDs, the effective spindle count drops to 0, giving you 8. Faster storage means less blocking, which means you need &lt;em&gt;fewer&lt;/em&gt; connections, not more. Counterintuitive, but it holds up: SSDs shrink the ideal pool size rather than growing it.&lt;/p&gt;
&lt;h2 id=&quot;the-proof-oracles-50x-improvement&quot;&gt;The Proof: Oracle’s 50x Improvement&lt;/h2&gt;
&lt;p&gt;Oracle’s Real-World Performance team demonstrated this live in a short video: they dropped a connection pool from 2,048 down to 96 connections. Response time went from roughly 100ms to roughly 2ms — a 50x improvement, with zero code changes. You can watch the demo yourself: &lt;a href=&quot;https://youtu.be/_C77sBcAtSQ&quot;&gt;Oracle Real-World Performance: Connection Pooling&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-mental-model-to-keep&quot;&gt;The Mental Model to Keep&lt;/h2&gt;
&lt;p&gt;Aim for a small pool — somewhere around 10 to 20 connections. Everything else queues and waits its turn. The database runs at full speed on what it can actually handle, and requests get served quickly, one after another.&lt;/p&gt;
&lt;p&gt;Compare that to a huge pool where 500 connections all thrash the CPU simultaneously. Nobody gets fast service — everyone gets slow service, together.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Sources: &lt;a href=&quot;https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing&quot;&gt;HikariCP wiki — About Pool Sizing&lt;/a&gt;, &lt;a href=&quot;https://youtu.be/_C77sBcAtSQ&quot;&gt;Oracle Real-World Performance: Connection Pooling (video)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;markdown-alert markdown-alert-note&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;octicon octicon-note mr-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Note&lt;/p&gt;
&lt;p dir=&quot;auto&quot;&gt;Useful information that users should know, even when skimming content.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;markdown-alert markdown-alert-tip&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;octicon octicon-tip mr-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Tip&lt;/p&gt;
&lt;p dir=&quot;auto&quot;&gt;Helpful advice for doing things better or more easily.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;markdown-alert markdown-alert-important&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;octicon octicon-important mr-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Important&lt;/p&gt;
&lt;p dir=&quot;auto&quot;&gt;Key information users need to know to achieve their goal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;markdown-alert markdown-alert-warning&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;octicon octicon-warning mr-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Warning&lt;/p&gt;
&lt;p dir=&quot;auto&quot;&gt;Urgent info that needs immediate user attention to avoid problems.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;markdown-alert markdown-alert-caution&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;octicon octicon-caution mr-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Caution&lt;/p&gt;
&lt;p dir=&quot;auto&quot;&gt;Advises about risks or negative outcomes of certain actions.&lt;/p&gt;
&lt;/div&gt;</content:encoded><category>database</category><category>performance</category><category>postgresql</category><category>backend</category><category>engineering</category></item></channel></rss>