<?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: Rangga Aprilio Utama</title>
    <description>The latest articles on DEV Community by Rangga Aprilio Utama (@ranggaaprilio).</description>
    <link>https://dev.to/ranggaaprilio</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F559554%2F63b8cca4-9511-44ec-90a6-12db9c166988.jpeg</url>
      <title>DEV Community: Rangga Aprilio Utama</title>
      <link>https://dev.to/ranggaaprilio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ranggaaprilio"/>
    <language>en</language>
    <item>
      <title>SSO Is More Than "Log In Once"</title>
      <dc:creator>Rangga Aprilio Utama</dc:creator>
      <pubDate>Sun, 07 Jun 2026 01:26:27 +0000</pubDate>
      <link>https://dev.to/ranggaaprilio/sso-is-more-than-log-in-once-42gc</link>
      <guid>https://dev.to/ranggaaprilio/sso-is-more-than-log-in-once-42gc</guid>
      <description>&lt;p&gt;&lt;em&gt;A practical look at identity, sessions, OAuth 2.0, OpenID Connect, and tenant isolation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Single Sign-On is often summarized as "log in once and access many applications." That is correct, but incomplete. A real SSO system must also answer several security questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which application is requesting access?&lt;/li&gt;
&lt;li&gt;Which organization owns that application?&lt;/li&gt;
&lt;li&gt;Is the user allowed to use it?&lt;/li&gt;
&lt;li&gt;What information did the user approve sharing?&lt;/li&gt;
&lt;li&gt;How can the application trust the tokens it receives?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Three Actors
&lt;/h2&gt;

&lt;p&gt;An SSO flow has three main actors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The end user&lt;/strong&gt; who wants to sign in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The client application&lt;/strong&gt; that needs the user's identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The identity provider&lt;/strong&gt;, which authenticates the user and issues tokens.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The client application never receives the user's password. Instead, it redirects the browser to the identity provider. The provider handles authentication and sends the application a short-lived authorization code.&lt;/p&gt;

&lt;p&gt;This separation is fundamental: applications delegate authentication to one trusted identity provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Sign-In Flow Works
&lt;/h2&gt;

&lt;p&gt;A secure implementation can use the OAuth 2.0 Authorization Code Flow with OpenID Connect and PKCE.&lt;/p&gt;

&lt;p&gt;The sequence is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A client redirects the browser to the identity provider with its &lt;code&gt;client_id&lt;/code&gt;, callback URL, requested scopes, &lt;code&gt;state&lt;/code&gt;, and an S256 PKCE challenge.&lt;/li&gt;
&lt;li&gt;The provider validates the client and callback URL before showing any login page.&lt;/li&gt;
&lt;li&gt;It resolves the tenant from the registered client, so tenant context does not come from untrusted user input.&lt;/li&gt;
&lt;li&gt;The provider stores the validated request as a short-lived authorization transaction. The frontend receives only an opaque transaction ID.&lt;/li&gt;
&lt;li&gt;The user signs in. The provider verifies the tenant-scoped account, password, account status, and role for that client.&lt;/li&gt;
&lt;li&gt;The user approves or denies the requested access on a consent screen.&lt;/li&gt;
&lt;li&gt;On approval, the provider returns a short-lived, single-use authorization code to the registered callback.&lt;/li&gt;
&lt;li&gt;The client exchanges the code and its PKCE verifier for an ID token, access token, and refresh token.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ID token tells the client who authenticated. The access token authorizes API access. The refresh token allows the client to obtain a new short-lived access token without asking the user to sign in again.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSO Flow Diagram
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNqFVW1v2jAQ_iuWP4eOtBRKNFWqoJpYpQ0VdZMmpMkkR7BI7MwvrLTqf9_ZTiC8aXyAGN89d8_5eZx3msoMaEI1_LEgUhhzlitWzgXBD7NGClsuQNXr1EhFXnSzrpgyPOUVE4Y8VBVhmowKDmFV8JQZLsVp6CSbutBJhpHcbMlUyQ3PzoHOQGuEcNHN4wxbgDPlpxMXhVAGUgOZ-2Ne13YNd-7vsacEYQrcJ3M647kgXJC_3KzIbPZ9TkMwRjWxX0CAYgaINu6biYxMn0aPZAOKL3nTb0hATgl5sGYlFX_zvIlyI9UmVEjDXCbj6PNCfbpXkHHlGnl5nkQBH39SWeHPrk66YkUBIq_pYomm0A9W8Mz1FGAjcoDnKxgQzO2cx24j1pNNyGgF6ZrAK9eGi9wNheiw10ySFYZ8k2Tjyu_3SP1xcIjnxp2QMddVwbakkDlOuWINi9aBeCozuyi5ISkycHJghT4EbBi7mW-JxcyItLlZHVjVA1aygGOAPUEF_jhB4RF2NGrukKRLgUJDmK-HhYLnfFHAKdsatdN0-AzGKuE8s3JEUPyoQrvzyhGfZ9g0Z-hi2hRYmiJ03Y3ImtmfnW4qhXY5GucHB8f04lGrCr0F-vzoH8JuI1Rs16tEX5yf9x7RKI4COti2J7sXvLtKTtTgnfTcyNN74TTL0_dK3ee3jLiTu_IzhguxntTjK9oGPRNwfb0zpr3oJ0yKzrvqyDunFP3xo8HrAwwJCpYK9IoYuQahT9hNJy4z3BMYJ61K66YDSMhrpU0nLb0pDnh8lV3gXUvWsNVkqWRJvv58mh2n-Eq1iTRefWgchUy51hYd5W8MZjPuXgERXgEVV9u9z_zpHEnDwR5xr3aXb0OlZSmvR7Q4v6TGMYhtS4ptF_xHTj7yt8fOjpWEBqIRzRXPaGKUhYiWoErmlvTdhcwp-rWEOU3wMWNq7V4EH5iDr5VfUpZNmpI2X9FkiRcUrmzl5FK_LHf_KqwGaiStMDTpxR6DJu_0lSZx3L267Q-H3Zu7Qa9_E3cHEd3SpHN7NRhe3w2Gcb8f94f97vVHRN982fgqjgc313E_7vZuu4Ner__xD5uheu0" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqFVW1v2jAQ_iuWP4eOtBRKNFWqoJpYpQ0VdZMmpMkkR7BI7MwvrLTqf9_ZTiC8aXyAGN89d8_5eZx3msoMaEI1_LEgUhhzlitWzgXBD7NGClsuQNXr1EhFXnSzrpgyPOUVE4Y8VBVhmowKDmFV8JQZLsVp6CSbutBJhpHcbMlUyQ3PzoHOQGuEcNHN4wxbgDPlpxMXhVAGUgOZ-2Ne13YNd-7vsacEYQrcJ3M647kgXJC_3KzIbPZ9TkMwRjWxX0CAYgaINu6biYxMn0aPZAOKL3nTb0hATgl5sGYlFX_zvIlyI9UmVEjDXCbj6PNCfbpXkHHlGnl5nkQBH39SWeHPrk66YkUBIq_pYomm0A9W8Mz1FGAjcoDnKxgQzO2cx24j1pNNyGgF6ZrAK9eGi9wNheiw10ySFYZ8k2Tjyu_3SP1xcIjnxp2QMddVwbakkDlOuWINi9aBeCozuyi5ISkycHJghT4EbBi7mW-JxcyItLlZHVjVA1aygGOAPUEF_jhB4RF2NGrukKRLgUJDmK-HhYLnfFHAKdsatdN0-AzGKuE8s3JEUPyoQrvzyhGfZ9g0Z-hi2hRYmiJ03Y3ImtmfnW4qhXY5GucHB8f04lGrCr0F-vzoH8JuI1Rs16tEX5yf9x7RKI4COti2J7sXvLtKTtTgnfTcyNN74TTL0_dK3ee3jLiTu_IzhguxntTjK9oGPRNwfb0zpr3oJ0yKzrvqyDunFP3xo8HrAwwJCpYK9IoYuQahT9hNJy4z3BMYJ61K66YDSMhrpU0nLb0pDnh8lV3gXUvWsNVkqWRJvv58mh2n-Eq1iTRefWgchUy51hYd5W8MZjPuXgERXgEVV9u9z_zpHEnDwR5xr3aXb0OlZSmvR7Q4v6TGMYhtS4ptF_xHTj7yt8fOjpWEBqIRzRXPaGKUhYiWoErmlvTdhcwp-rWEOU3wMWNq7V4EH5iDr5VfUpZNmpI2X9FkiRcUrmzl5FK_LHf_KqwGaiStMDTpxR6DJu_0lSZx3L267Q-H3Zu7Qa9_E3cHEd3SpHN7NRhe3w2Gcb8f94f97vVHRN982fgqjgc313E_7vZuu4Ner__xD5uheu0%3Ftype%3Dpng" width="1407" height="1796"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where "Single" Sign-On Happens
&lt;/h2&gt;

&lt;p&gt;The reusable part is the identity-provider session.&lt;/p&gt;

&lt;p&gt;After login, the provider creates an opaque server-side browser session and stores its identifier in a host-only, &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;SameSite=Lax&lt;/code&gt; cookie. A later authorization request can reuse that session, including for another registered application in the same tenant.&lt;/p&gt;

&lt;p&gt;However, reusing authentication does not mean automatically granting access.&lt;/p&gt;

&lt;p&gt;The provider still checks that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the session belongs to the client's tenant;&lt;/li&gt;
&lt;li&gt;the user is still active;&lt;/li&gt;
&lt;li&gt;the user still has a role for the requesting client; and&lt;/li&gt;
&lt;li&gt;the current request satisfies rules such as &lt;code&gt;prompt=login&lt;/code&gt; or &lt;code&gt;max_age&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reveals an important SSO principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Authentication can be shared, but authorization must be evaluated for every application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A user may be signed in to the identity provider and still be denied access to a specific client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenancy Changes the Trust Boundary
&lt;/h2&gt;

&lt;p&gt;In a multi-tenant platform, the same SSO service supports many organizations. Isolation is therefore part of authentication itself, not merely a database concern.&lt;/p&gt;

&lt;p&gt;A multi-tenant implementation should associate users, OAuth clients, roles, sessions, and tokens with a tenant. The &lt;code&gt;client_id&lt;/code&gt; can determine the tenant during authorization, while issued tokens can contain both &lt;code&gt;tenant_id&lt;/code&gt; and &lt;code&gt;client_id&lt;/code&gt; claims.&lt;/p&gt;

&lt;p&gt;This prevents a valid identity from Tenant A from silently becoming valid for an application owned by Tenant B.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why PKCE, State, and Redirect URIs Matter
&lt;/h2&gt;

&lt;p&gt;Several small-looking values protect the flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PKCE&lt;/strong&gt; binds the authorization request to the client that started it. An intercepted code is useless without the original verifier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State&lt;/strong&gt; lets the client detect forged or mismatched callbacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registered redirect URI matching&lt;/strong&gt; prevents the provider from sending codes to an attacker-controlled destination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-use authorization codes&lt;/strong&gt; reduce replay risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce and authentication time&lt;/strong&gt; preserve OpenID Connect context in the ID token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;S256 PKCE should protect both public clients, such as SPAs and mobile apps, and confidential server-side clients. Confidential clients can also authenticate with a secret that is stored as a hash and shown only when created or rotated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tokens Are Verifiable, Not Magical
&lt;/h2&gt;

&lt;p&gt;The identity provider can sign ID and access tokens with RS256. Applications retrieve public keys from a JWKS endpoint and verify token signatures without receiving the private signing key.&lt;/p&gt;

&lt;p&gt;Verification must include more than the signature. A client should also validate the issuer, audience, expiration, tenant, and expected nonce. Roles and scopes can then support application-level authorization.&lt;/p&gt;

&lt;p&gt;Access tokens are deliberately short-lived. Refresh tokens live longer, are stored hashed, rotate when used, and can be revoked. This limits damage while preserving a smooth user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Supports the Security Model
&lt;/h2&gt;

&lt;p&gt;A practical implementation can follow Clean Architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;domain entities describe clients, users, roles, codes, tokens, and sessions;&lt;/li&gt;
&lt;li&gt;use cases implement authorization, login, consent, token exchange, refresh, and logout;&lt;/li&gt;
&lt;li&gt;PostgreSQL stores durable identity and configuration data;&lt;/li&gt;
&lt;li&gt;Redis stores short-lived transactions, sessions, codes, and throttling counters;&lt;/li&gt;
&lt;li&gt;HTTP handlers translate protocol requests into use-case calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation keeps OAuth rules independent from specific web frameworks and storage technologies, making security behavior easier to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Main Lesson
&lt;/h2&gt;

&lt;p&gt;SSO is not simply a shared login form. It is a trust system connecting identities, organizations, applications, browser sessions, consent, and cryptographically verifiable tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;authenticate once, validate access per client, keep tenant boundaries explicit, and trust only server-validated protocol state.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is what turns "log in once" from a convenience feature into a secure identity architecture.&lt;/p&gt;




&lt;p&gt;I will share the source code related to this SSO implementation through the link below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="https://github.com/ranggaaprilio/keyles" rel="noopener noreferrer"&gt;Keyles&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>sso</category>
      <category>authentication</category>
      <category>oidc</category>
    </item>
    <item>
      <title>🚀 The Secret Sauce of Scalable Apps: Database Connection Pooling</title>
      <dc:creator>Rangga Aprilio Utama</dc:creator>
      <pubDate>Fri, 02 Jan 2026 15:15:52 +0000</pubDate>
      <link>https://dev.to/ranggaaprilio/the-secret-sauce-of-scalable-apps-database-connection-pooling-1di</link>
      <guid>https://dev.to/ranggaaprilio/the-secret-sauce-of-scalable-apps-database-connection-pooling-1di</guid>
      <description>&lt;p&gt;When people talk about scalability, they usually mention caching, load balancers, or microservices.&lt;br&gt;&lt;br&gt;
But many apps fail much earlier — at the &lt;strong&gt;database connection level&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your app talks to the database inefficiently, no amount of fancy architecture will save you.&lt;br&gt;&lt;br&gt;
That’s where &lt;strong&gt;database connection pooling&lt;/strong&gt; comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 What Is Database Connection Pooling?
&lt;/h2&gt;

&lt;p&gt;A connection pool is simply a &lt;strong&gt;set of database connections kept ready in memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of opening a brand-new database connection for every request, your app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Borrows a connection from the pool&lt;/li&gt;
&lt;li&gt;Runs the query&lt;/li&gt;
&lt;li&gt;Returns the connection to the pool&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The same connection gets reused many times.&lt;/p&gt;

&lt;p&gt;Simple idea. Massive impact.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ Why Opening a New Connection Every Time Is a Bad Idea
&lt;/h2&gt;

&lt;p&gt;It &lt;em&gt;works&lt;/em&gt; in small apps, but breaks badly at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Connections Are Expensive
&lt;/h3&gt;

&lt;p&gt;Opening a DB connection isn’t instant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;network handshake&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;resource allocation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can take &lt;strong&gt;tens or even hundreds of milliseconds&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  2️⃣ You Waste Database Resources
&lt;/h3&gt;

&lt;p&gt;Constantly creating and destroying connections forces the database to clean up over and over again.&lt;/p&gt;

&lt;p&gt;At high traffic, this adds up fast.&lt;/p&gt;




&lt;h3&gt;
  
  
  3️⃣ You Can Kill Your Own Database
&lt;/h3&gt;

&lt;p&gt;Thousands of concurrent requests opening connections can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;exhaust DB limits&lt;/li&gt;
&lt;li&gt;spike latency&lt;/li&gt;
&lt;li&gt;cause timeouts everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congrats — you’ve DDoS’ed yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ The 3 Pool Settings You Must Understand
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔢 Max Open Connections
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;maximum number of connections&lt;/strong&gt; the app can open to the database.&lt;/p&gt;

&lt;p&gt;If this limit is reached:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new requests must wait&lt;/li&gt;
&lt;li&gt;wait too long → timeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Too small = bottleneck&lt;br&gt;&lt;br&gt;
Too large = database overload&lt;/p&gt;




&lt;h3&gt;
  
  
  💤 Max Idle Connections
&lt;/h3&gt;

&lt;p&gt;How many connections are allowed to sit idle in the pool.&lt;/p&gt;

&lt;p&gt;Why this matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;idle connections = faster responses&lt;/li&gt;
&lt;li&gt;no need to reconnect from scratch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But too many idle connections waste DB resources.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⏳ Max Connection Lifetime
&lt;/h3&gt;

&lt;p&gt;How long a connection can live before being recycled.&lt;/p&gt;

&lt;p&gt;This helps prevent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stale connections&lt;/li&gt;
&lt;li&gt;silent disconnects from the database or network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always keep this &lt;strong&gt;shorter than the DB’s own timeout&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Common Pitfalls (Read This Carefully)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  💣 Connection Leaks
&lt;/h3&gt;

&lt;p&gt;The most common pooling bug.&lt;/p&gt;

&lt;p&gt;It happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a connection is taken from the pool&lt;/li&gt;
&lt;li&gt;but never returned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usually caused by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing &lt;code&gt;finally&lt;/code&gt; / &lt;code&gt;defer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;early returns&lt;/li&gt;
&lt;li&gt;bad error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pool slowly drains&lt;/li&gt;
&lt;li&gt;requests hang&lt;/li&gt;
&lt;li&gt;app looks “dead”&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔄 Connection Reset Is Mandatory
&lt;/h3&gt;

&lt;p&gt;Before a connection goes back to the pool, it must be cleaned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rollback open transactions&lt;/li&gt;
&lt;li&gt;release locks&lt;/li&gt;
&lt;li&gt;reset session state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otherwise, the next request inherits a mess.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧐 Pre-Ping vs Optimistic Use
&lt;/h3&gt;

&lt;p&gt;Some pools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;test connections (&lt;code&gt;SELECT 1&lt;/code&gt;) before handing them out → safer, slower&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Others:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use the connection directly&lt;/li&gt;
&lt;li&gt;recreate it only on failure → faster, riskier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choose based on your latency and network reliability.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Connection pooling isn’t an optimization — it’s &lt;strong&gt;foundational&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A well-sized pool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keeps latency low&lt;/li&gt;
&lt;li&gt;protects your database&lt;/li&gt;
&lt;li&gt;lets your app scale smoothly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get this wrong, and your app will fail under load no matter how good your code is.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚕 A Simple Analogy
&lt;/h2&gt;

&lt;p&gt;Imagine a taxi company.&lt;/p&gt;

&lt;p&gt;Bad approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build a new car for every passenger&lt;/li&gt;
&lt;li&gt;destroy it after the ride&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s opening a DB connection per request.&lt;/p&gt;

&lt;p&gt;Good approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep a fleet of cars&lt;/li&gt;
&lt;li&gt;&lt;p&gt;reuse them for different passengers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Max Open Connections&lt;/strong&gt; = total cars  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Max Idle Connections&lt;/strong&gt; = cars waiting at the station  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Efficient, scalable, and sane.&lt;/p&gt;

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