<?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: Fazal Mansuri</title>
    <description>The latest articles on DEV Community by Fazal Mansuri (@fazal_mansuri_).</description>
    <link>https://dev.to/fazal_mansuri_</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%2F2949287%2Fcf0675d7-fc54-4289-bbdc-92bc98944ffa.jpg</url>
      <title>DEV Community: Fazal Mansuri</title>
      <link>https://dev.to/fazal_mansuri_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fazal_mansuri_"/>
    <language>en</language>
    <item>
      <title>🛠️ Database Connection Pooling: The Hidden Bottleneck That Can Bring Your Application Down</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Fri, 06 Nov 2026 17:45:44 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/database-connection-pooling-the-hidden-bottleneck-that-can-bring-your-application-down-5g6g</link>
      <guid>https://dev.to/fazal_mansuri_/database-connection-pooling-the-hidden-bottleneck-that-can-bring-your-application-down-5g6g</guid>
      <description>&lt;p&gt;Imagine this.&lt;/p&gt;

&lt;p&gt;Your application has been running perfectly for weeks. APIs are responding quickly, database queries are working and everything looks healthy.&lt;/p&gt;

&lt;p&gt;Then, suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API requests start taking several seconds.&lt;/li&gt;
&lt;li&gt;Some requests time out, while others never seem to complete.&lt;/li&gt;
&lt;li&gt;New database operations stop working.&lt;/li&gt;
&lt;li&gt;Restarting the application temporarily fixes everything.&lt;/li&gt;
&lt;li&gt;A few minutes or hours later, the same problem returns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You check the database. It's running.&lt;/p&gt;

&lt;p&gt;You check the application. No obvious crash.&lt;/p&gt;

&lt;p&gt;You check the logs and find something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: context deadline exceeded
Error: connection pool exhausted
Error: timeout acquiring connection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One possible reason?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your application has run out of available database connections.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where database connection pooling becomes extremely important.&lt;/p&gt;

&lt;p&gt;Connection pooling is one of those concepts that developers often configure once and forget about. But an incorrectly configured pool, or connections that are never released, can gradually bring an otherwise healthy application to a halt.&lt;/p&gt;

&lt;p&gt;In this article, we'll go beyond what connection pooling is. We'll understand how it works, how connections get stuck, how to reproduce pool exhaustion, how to debug it in a real application and which practices help prevent these problems in production.&lt;/p&gt;

&lt;p&gt;We'll use Go's &lt;code&gt;database/sql&lt;/code&gt; package for practical examples, but the concepts apply to most backend technologies.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. First, why do we need a database connection pool?
&lt;/h2&gt;

&lt;p&gt;Let's start with a basic question.&lt;/p&gt;

&lt;p&gt;What happens when an API needs to execute a database query?&lt;/p&gt;

&lt;p&gt;At a high level, the application needs a connection to the database, sends a query, receives the result and then releases the connection for reuse.&lt;/p&gt;

&lt;p&gt;Opening a brand-new database connection for every request is expensive.&lt;/p&gt;

&lt;p&gt;Establishing a connection can involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A network connection between the application and database.&lt;/li&gt;
&lt;li&gt;Authentication.&lt;/li&gt;
&lt;li&gt;Database session initialization.&lt;/li&gt;
&lt;li&gt;TLS negotiation, if configured.&lt;/li&gt;
&lt;li&gt;Other database and driver-specific setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now imagine an application receiving 500 requests simultaneously.&lt;/p&gt;

&lt;p&gt;If every request independently opens a new database connection, we could end up creating hundreds of connections unnecessarily.&lt;/p&gt;

&lt;p&gt;That introduces overhead and can overwhelm the database server.&lt;/p&gt;

&lt;p&gt;Instead, we use a &lt;strong&gt;connection pool&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A connection pool maintains a collection of reusable database connections. When an application needs a connection, it borrows one from the pool. Once the operation is finished, the connection is returned so another operation can use it.&lt;/p&gt;

&lt;p&gt;Think of it like a shared collection of resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A request needs a database connection.&lt;/li&gt;
&lt;li&gt;The pool provides an available connection.&lt;/li&gt;
&lt;li&gt;The request executes its database operation.&lt;/li&gt;
&lt;li&gt;The connection is released back to the pool.&lt;/li&gt;
&lt;li&gt;Another request can reuse it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important part is that the application doesn't need to establish a new physical connection for every query.&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%2Fdummyimage.com%2F1200x600%2Ff0f0f0%2F333333.png%26text%3DApplication%2B%25E2%2586%2592%2BConnection%2BPool%2B%25E2%2586%2592%2BDatabase" 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%2Fdummyimage.com%2F1200x600%2Ff0f0f0%2F333333.png%26text%3DApplication%2B%25E2%2586%2592%2BConnection%2BPool%2B%25E2%2586%2592%2BDatabase" alt="Application to connection pool to database conceptual diagram" width="1200" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One important distinction:&lt;/strong&gt; A connection pool is not the same as a database connection.&lt;/p&gt;

&lt;p&gt;The pool manages connections. Your application borrows and returns them as database operations require.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How connection pooling works in Go
&lt;/h2&gt;

&lt;p&gt;Go makes connection pooling particularly interesting because &lt;code&gt;database/sql&lt;/code&gt; manages the pool for us.&lt;/p&gt;

&lt;p&gt;Consider this example:&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;db&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connectionString&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;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common misconception is that &lt;code&gt;sql.Open()&lt;/code&gt; immediately establishes a database connection.&lt;/p&gt;

&lt;p&gt;It doesn't necessarily do that.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sql.Open()&lt;/code&gt; creates a &lt;code&gt;*sql.DB&lt;/code&gt; handle, which manages a pool of connections. Actual connections are typically established when they're needed.&lt;/p&gt;

&lt;p&gt;If you want to verify that the database is reachable during application startup, use &lt;code&gt;PingContext()&lt;/code&gt;:&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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&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="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="m"&gt;5&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;Second&lt;/span&gt;&lt;span class="p"&gt;,&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;cancel&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="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PingContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="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;"database connection failed: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;Also, notice something important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;*sql.DB&lt;/code&gt; is designed to be long-lived and shared across goroutines.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You generally create one database handle during application startup and reuse it throughout the application's lifetime.&lt;/p&gt;

&lt;p&gt;You should not create a new &lt;code&gt;sql.DB&lt;/code&gt; inside every API handler.&lt;/p&gt;

&lt;p&gt;For example, avoid this:&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;GetUsers&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;db&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connectionString&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;"Database error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;500&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Execute query...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because every handler creates its own pool. Instead of sharing a controlled number of connections, you end up with multiple independent pools.&lt;/p&gt;

&lt;p&gt;This can cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unnecessary connection creation.&lt;/li&gt;
&lt;li&gt;Too many connections on the database server.&lt;/li&gt;
&lt;li&gt;More resource consumption.&lt;/li&gt;
&lt;li&gt;Difficult-to-manage connection limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A better approach is to initialize the pool once and inject the shared &lt;code&gt;*sql.DB&lt;/code&gt; into your repository or service layer.&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;UserRepository&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;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&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;NewUserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UserRepository&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;UserRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;db&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;Now every repository operation uses the same pool.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Understanding the connection pool configuration
&lt;/h2&gt;

&lt;p&gt;Go provides several methods to control the pool.&lt;/p&gt;

&lt;p&gt;These are worth understanding properly because setting them without understanding their impact can create production issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SetMaxOpenConns&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxOpenConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This defines the maximum number of open connections that the pool can have at a time.&lt;/p&gt;

&lt;p&gt;For example, if the maximum is 25:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Up to 25 connections can be open.&lt;/li&gt;
&lt;li&gt;If all 25 are busy, additional operations wait.&lt;/li&gt;
&lt;li&gt;When a connection becomes available, a waiting operation can use it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of the most important settings because it controls how many concurrent database operations can hold connections from that pool.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SetMaxIdleConns&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxIdleConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This defines the maximum number of connections that can remain idle in the pool.&lt;/p&gt;

&lt;p&gt;Why keep idle connections?&lt;/p&gt;

&lt;p&gt;Because creating a new connection takes time. Keeping a reasonable number of connections available can reduce the overhead of establishing new ones.&lt;/p&gt;

&lt;p&gt;But don't confuse idle connections with unused resources that are automatically closed immediately. Idle connections can remain open until they are reused or removed by pool lifecycle rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SetConnMaxLifetime&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConnMaxLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&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;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets the maximum amount of time a connection may be reused.&lt;/p&gt;

&lt;p&gt;Once a connection reaches its lifetime, it becomes eligible for removal and replacement.&lt;/p&gt;

&lt;p&gt;Why is this useful?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database infrastructure may rotate connections.&lt;/li&gt;
&lt;li&gt;Network devices may terminate long-lived connections.&lt;/li&gt;
&lt;li&gt;Cloud database environments may have connection lifecycle constraints.&lt;/li&gt;
&lt;li&gt;Long-lived sessions can accumulate server-side state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This does not mean an active query is forcibly interrupted exactly when the lifetime expires. The pool applies connection lifetime rules as connections are returned and reused.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SetConnMaxIdleTime&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConnMaxIdleTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&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;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This controls how long an idle connection can remain unused before it becomes eligible for closure.&lt;/p&gt;

&lt;p&gt;For example, imagine your application receives heavy traffic during the day but very little traffic at night.&lt;/p&gt;

&lt;p&gt;You might not need to keep every previously opened connection around during idle periods.&lt;/p&gt;

&lt;p&gt;This setting helps the pool clean up connections that have been sitting unused.&lt;/p&gt;

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

&lt;p&gt;A basic configuration might look like this:&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;NewDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dsn&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;db&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dsn&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="k"&gt;return&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;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxOpenConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxIdleConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConnMaxLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&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;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConnMaxIdleTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&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;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&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="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="m"&gt;5&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;Second&lt;/span&gt;&lt;span class="p"&gt;,&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;cancel&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="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PingContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;span class="n"&gt;err&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;db&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values are examples, not universal production defaults. Your actual configuration should depend on database capacity, application concurrency, query behavior, number of instances and workload.&lt;/p&gt;

&lt;p&gt;We'll come back to sizing later.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The real problem: How does an application run out of connections?
&lt;/h2&gt;

&lt;p&gt;Now let's get to the interesting part.&lt;/p&gt;

&lt;p&gt;Suppose your application has the following configuration:&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxOpenConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means the pool can have at most five open connections.&lt;/p&gt;

&lt;p&gt;Imagine five API requests are executing database operations simultaneously.&lt;/p&gt;

&lt;p&gt;All five connections are occupied.&lt;/p&gt;

&lt;p&gt;Now a sixth request arrives.&lt;/p&gt;

&lt;p&gt;What happens?&lt;/p&gt;

&lt;p&gt;It waits until one of the existing operations releases a connection.&lt;/p&gt;

&lt;p&gt;This is expected behavior.&lt;/p&gt;

&lt;p&gt;But what if those five connections are never released?&lt;/p&gt;

&lt;p&gt;The sixth request keeps waiting.&lt;/p&gt;

&lt;p&gt;The seventh request keeps waiting.&lt;/p&gt;

&lt;p&gt;Eventually, requests start timing out and your application appears to be stuck.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;connection pool exhaustion&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The database itself might still be healthy. The problem is that your application cannot obtain a connection from its own pool.&lt;/p&gt;

&lt;p&gt;Let's look at the most common reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Common causes of connection leaks and pool exhaustion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem 1: Forgetting to close query rows
&lt;/h3&gt;

&lt;p&gt;This is one of the easiest mistakes to make.&lt;/p&gt;

&lt;p&gt;Consider:&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;GetUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SELECT id, name FROM users"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&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="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&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="no"&gt;nil&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;err&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="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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;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;p&gt;Looks perfectly fine, right?&lt;/p&gt;

&lt;p&gt;But there's an issue.&lt;/p&gt;

&lt;p&gt;We never close &lt;code&gt;rows&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Rows&lt;/code&gt; object can hold a database connection while the result set is being consumed. If it isn't closed, the connection may remain unavailable to other operations.&lt;/p&gt;

&lt;p&gt;A safer implementation:&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;GetUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SELECT id, name FROM users"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&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="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&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="no"&gt;nil&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;err&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="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&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;Three important things are happening here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;defer rows.Close()&lt;/code&gt; ensures cleanup when the function returns, including error paths.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rows.Err()&lt;/code&gt; checks whether iteration ended because of an error.&lt;/li&gt;
&lt;li&gt;The connection can be returned to the pool once the result set is closed and the operation is finished.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;A practical rule: Whenever you call &lt;code&gt;Query()&lt;/code&gt; and receive &lt;code&gt;*sql.Rows&lt;/code&gt;, close it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also, remember that &lt;code&gt;QueryRow()&lt;/code&gt; behaves differently: it represents a single-row result and doesn't require you to call &lt;code&gt;Close()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: Not completing database transactions
&lt;/h3&gt;

&lt;p&gt;Transactions are another common source of connection exhaustion.&lt;/p&gt;

&lt;p&gt;Consider:&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;UpdateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tx&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Begin&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"UPDATE users SET status = ? WHERE id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&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;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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;p&gt;What's wrong here?&lt;/p&gt;

&lt;p&gt;We started a transaction but never committed or rolled it back.&lt;/p&gt;

&lt;p&gt;A transaction holds its underlying connection until it is completed.&lt;/p&gt;

&lt;p&gt;If this happens repeatedly, connections can remain occupied and the pool can eventually become exhausted.&lt;/p&gt;

&lt;p&gt;A safer pattern:&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;UpdateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tx&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Begin&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rollback&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"UPDATE users SET status = ? WHERE id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&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;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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&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="no"&gt;nil&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;err&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;p&gt;Why defer &lt;code&gt;Rollback()&lt;/code&gt; if we're going to commit?&lt;/p&gt;

&lt;p&gt;Because it provides cleanup for every early return.&lt;/p&gt;

&lt;p&gt;After a successful commit, the deferred rollback simply returns an error indicating that the transaction has already completed. It's safe to ignore that result in this cleanup pattern.&lt;/p&gt;

&lt;p&gt;The important thing is that every transaction should have a clearly defined completion path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never start a transaction and leave its lifecycle uncertain.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: Starting another database operation inside a transaction
&lt;/h3&gt;

&lt;p&gt;Here's a subtle issue that can be particularly confusing.&lt;/p&gt;

&lt;p&gt;Imagine your pool has only one connection:&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxOpenConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now consider:&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;UpdateAndFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tx&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Begin&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rollback&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"UPDATE users SET status = ? WHERE id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&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;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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"SELECT name FROM users WHERE id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&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;Can you spot the problem?&lt;/p&gt;

&lt;p&gt;The transaction already holds the only available connection.&lt;/p&gt;

&lt;p&gt;But the next query uses &lt;code&gt;db.QueryRow()&lt;/code&gt;, which tries to acquire a connection from the pool.&lt;/p&gt;

&lt;p&gt;There are no available connections.&lt;/p&gt;

&lt;p&gt;The transaction is waiting for the query to finish and the query is waiting for the transaction's connection to become available.&lt;/p&gt;

&lt;p&gt;Neither can proceed.&lt;/p&gt;

&lt;p&gt;This is a deadlock-like situation caused by exhausting the pool.&lt;/p&gt;

&lt;p&gt;The fix is simple: execute queries that belong to the transaction through &lt;code&gt;tx&lt;/code&gt;, not through &lt;code&gt;db&lt;/code&gt;.&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;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"SELECT name FROM users WHERE id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an especially important distinction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;db.Exec()&lt;/code&gt; / &lt;code&gt;db.Query()&lt;/code&gt; acquire connections from the pool.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tx.Exec()&lt;/code&gt; / &lt;code&gt;tx.Query()&lt;/code&gt; use the connection already reserved by that transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Problem 4: Long-running queries
&lt;/h3&gt;

&lt;p&gt;Not every pool exhaustion issue is caused by a connection leak.&lt;/p&gt;

&lt;p&gt;Sometimes, connections are being released correctly, but database operations are taking too long.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your pool has 20 connections.&lt;/li&gt;
&lt;li&gt;20 requests execute slow database queries.&lt;/li&gt;
&lt;li&gt;Each query takes 15 seconds.&lt;/li&gt;
&lt;li&gt;Another 100 requests arrive during that period.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those new requests must wait for connections.&lt;/p&gt;

&lt;p&gt;The application may appear unresponsive even though no connection has leaked.&lt;/p&gt;

&lt;p&gt;Common reasons include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing database indexes.&lt;/li&gt;
&lt;li&gt;Queries scanning too many rows.&lt;/li&gt;
&lt;li&gt;Unnecessary joins.&lt;/li&gt;
&lt;li&gt;Lock contention.&lt;/li&gt;
&lt;li&gt;Large result sets.&lt;/li&gt;
&lt;li&gt;Database CPU or I/O saturation.&lt;/li&gt;
&lt;li&gt;Slow network communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why increasing &lt;code&gt;MaxOpenConns&lt;/code&gt; isn't always the solution.&lt;/p&gt;

&lt;p&gt;If the database is already struggling, allowing more concurrent queries may make things worse.&lt;/p&gt;

&lt;p&gt;The right approach is to investigate query execution time, database load and lock waits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 5: Queries without timeouts
&lt;/h3&gt;

&lt;p&gt;Consider:&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;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"SELECT id, name FROM users"&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;What happens if the database takes too long to respond?&lt;/p&gt;

&lt;p&gt;Without a suitable context deadline, the operation may wait longer than the caller can reasonably tolerate.&lt;/p&gt;

&lt;p&gt;Use context-aware operations:&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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&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="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="m"&gt;3&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;Second&lt;/span&gt;&lt;span class="p"&gt;,&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;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"SELECT id, name FROM users"&lt;/span&gt;&lt;span class="p"&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;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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A context deadline gives the operation a time limit and allows cancellation to propagate through the database driver where supported.&lt;/p&gt;

&lt;p&gt;Be careful, though: a timeout is not a substitute for closing rows or completing transactions.&lt;/p&gt;

&lt;p&gt;You need both proper resource cleanup and sensible deadlines.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Let's reproduce connection pool exhaustion
&lt;/h2&gt;

&lt;p&gt;Theory is useful, but let's actually see what happens.&lt;/p&gt;

&lt;p&gt;We'll intentionally create a small pool and hold connections for a few seconds.&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;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"database/sql"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&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;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;db&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"your-connection-string"&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;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxOpenConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxIdleConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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;1&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="m"&gt;5&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="k"&gt;go&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;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&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="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="m"&gt;10&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;Second&lt;/span&gt;&lt;span class="p"&gt;,&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;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="n"&gt;start&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;conn&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;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;"Worker %d failed: %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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;err&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="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;"Worker %d acquired connection in %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;id&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;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&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;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&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;Second&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;"Worker %d released connection&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;id&lt;/span&gt;&lt;span class="p"&gt;)&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="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;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&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;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stats&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;"Open: %d&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;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenConnections&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;"In use: %d&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;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InUse&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;"Idle: %d&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;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Idle&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;"Wait count: %d&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;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitCount&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;"Wait duration: %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;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitDuration&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;Here, we're deliberately limiting the pool to two connections while starting five workers.&lt;/p&gt;

&lt;p&gt;What should happen?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first two workers acquire connections.&lt;/li&gt;
&lt;li&gt;The remaining three workers wait.&lt;/li&gt;
&lt;li&gt;When one of the first workers closes its connection, a waiting worker can acquire it.&lt;/li&gt;
&lt;li&gt;The process continues until all workers finish or their contexts expire.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice this line:&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;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns the reserved connection to the pool.&lt;/p&gt;

&lt;p&gt;For this demonstration, we're using &lt;code&gt;db.Conn()&lt;/code&gt; to reserve a connection explicitly. In normal application code, you generally use &lt;code&gt;QueryContext&lt;/code&gt;, &lt;code&gt;ExecContext&lt;/code&gt;, or a transaction and let &lt;code&gt;database/sql&lt;/code&gt; manage connection acquisition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try changing the sleep duration, pool size and context timeout.&lt;/strong&gt; You'll get a much better understanding of how pool contention behaves.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. How to debug connection pool exhaustion in a real application
&lt;/h2&gt;

&lt;p&gt;Now imagine this happens in production.&lt;/p&gt;

&lt;p&gt;The API is slow, requests are timing out and the database pool is fully occupied.&lt;/p&gt;

&lt;p&gt;Where do you start?&lt;/p&gt;

&lt;p&gt;Don't immediately increase the connection limit or restart the application.&lt;/p&gt;

&lt;p&gt;First, collect evidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Check pool statistics
&lt;/h3&gt;

&lt;p&gt;Go provides a very useful method:&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;stats&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns a &lt;code&gt;DBStats&lt;/code&gt; structure containing information about the pool.&lt;/p&gt;

&lt;p&gt;Some important fields:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it tells you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OpenConnections&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Currently open connections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InUse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Connections currently checked out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Idle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Connections currently idle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MaxOpenConnections&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Configured maximum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WaitCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Total number of waits for a connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WaitDuration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Total time spent waiting for connections&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's log them:&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;LogDBStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stats&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"DB Pool | Open: %d | InUse: %d | Idle: %d | MaxOpen: %d | WaitCount: %d | WaitDuration: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenConnections&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InUse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Idle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MaxOpenConnections&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitDuration&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;Call this periodically or expose these values through your application's metrics endpoint.&lt;/p&gt;

&lt;p&gt;Now imagine you see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB Pool | Open: 25 | InUse: 25 | Idle: 0 |
MaxOpen: 25 | WaitCount: 1200 | WaitDuration: 45s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does this tell us?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All 25 connections are currently occupied.&lt;/li&gt;
&lt;li&gt;There are no idle connections available.&lt;/li&gt;
&lt;li&gt;Other operations have been waiting for connections.&lt;/li&gt;
&lt;li&gt;The pool is experiencing contention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a strong indication that the pool is under pressure.&lt;/p&gt;

&lt;p&gt;But don't jump to the conclusion that connections are leaking.&lt;/p&gt;

&lt;p&gt;The same pattern can be caused by slow queries, long transactions, high request concurrency, or actual leaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;code&gt;WaitCount&lt;/code&gt; and &lt;code&gt;WaitDuration&lt;/code&gt; are cumulative counters. They aren't necessarily the number of requests waiting right now.&lt;/p&gt;

&lt;p&gt;For meaningful monitoring, compare their values over time. For example, calculate the increase in &lt;code&gt;WaitCount&lt;/code&gt; and &lt;code&gt;WaitDuration&lt;/code&gt; over each monitoring interval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Check whether connections are being released
&lt;/h3&gt;

&lt;p&gt;This is where you investigate the code.&lt;/p&gt;

&lt;p&gt;Search for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;db.Query()&lt;/code&gt; without &lt;code&gt;rows.Close()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Transactions without a commit or rollback.&lt;/li&gt;
&lt;li&gt;Early returns before cleanup.&lt;/li&gt;
&lt;li&gt;Long-running queries.&lt;/li&gt;
&lt;li&gt;Database operations inside loops.&lt;/li&gt;
&lt;li&gt;Connections reserved using &lt;code&gt;db.Conn()&lt;/code&gt; without &lt;code&gt;Close()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Rows that remain open while unrelated work is performed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pay special attention to functions that execute multiple database operations.&lt;/p&gt;

&lt;p&gt;For example:&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;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Some processing...&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;someCondition&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;p&gt;If &lt;code&gt;rows.Close()&lt;/code&gt; is missing, that early return can leave the result set open.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;defer rows.Close()&lt;/code&gt; immediately after successfully acquiring rows is a much safer pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Check the database server itself
&lt;/h3&gt;

&lt;p&gt;Your application metrics tell you what is happening inside the pool.&lt;/p&gt;

&lt;p&gt;But they don't tell you everything about the database.&lt;/p&gt;

&lt;p&gt;You should also investigate the database server.&lt;/p&gt;

&lt;p&gt;For PostgreSQL, you can inspect active sessions using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;usename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;wait_event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;wait_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;query_start&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;query_duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_stat_activity&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;datname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;query_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long-running queries.&lt;/li&gt;
&lt;li&gt;Sessions waiting on locks.&lt;/li&gt;
&lt;li&gt;Unexpectedly high numbers of active sessions.&lt;/li&gt;
&lt;li&gt;Sessions in &lt;code&gt;idle in transaction&lt;/code&gt; state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last state is particularly interesting.&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;idle in transaction&lt;/code&gt; session means a transaction has started but is currently not executing a query and has not been completed.&lt;/p&gt;

&lt;p&gt;Such transactions can hold locks and other resources and can contribute to connection pressure.&lt;/p&gt;

&lt;p&gt;For MySQL, you can inspect current sessions using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="k"&gt;FULL&lt;/span&gt; &lt;span class="n"&gt;PROCESSLIST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the connection count, query duration and session state.&lt;/p&gt;

&lt;p&gt;These checks help distinguish application-side connection leaks from database-side performance or locking problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Check query latency and acquisition time separately
&lt;/h3&gt;

&lt;p&gt;This is a debugging detail worth remembering.&lt;/p&gt;

&lt;p&gt;A database operation can be slow for two very different reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It took a long time to acquire a connection.&lt;/li&gt;
&lt;li&gt;It acquired a connection quickly, but the query itself took a long time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These should be measured separately.&lt;/p&gt;

&lt;p&gt;For example:&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;start&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;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;acquireAndExecuteDuration&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;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Query call duration: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;acquireAndExecuteDuration&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 measures the time spent obtaining a connection and executing the query call until it returns its rows. It is not necessarily the full time spent consuming the result set.&lt;/p&gt;

&lt;p&gt;For more detailed observability, instrument:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connection acquisition duration.&lt;/li&gt;
&lt;li&gt;Query execution duration.&lt;/li&gt;
&lt;li&gt;Rows iteration duration.&lt;/li&gt;
&lt;li&gt;Transaction duration.&lt;/li&gt;
&lt;li&gt;Connection pool wait statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it much easier to identify where the time is actually going.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Don't use application restarts as the permanent fix
&lt;/h3&gt;

&lt;p&gt;Restarting an application can temporarily solve a pool exhaustion issue because closing the database handle releases its connections.&lt;/p&gt;

&lt;p&gt;But if the underlying bug remains, it will happen again.&lt;/p&gt;

&lt;p&gt;A restart is a recovery action, not a root-cause fix.&lt;/p&gt;

&lt;p&gt;The goal should be to identify why connections are staying occupied and correct that behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. How should you choose the connection pool size?
&lt;/h2&gt;

&lt;p&gt;This is one of the most common configuration questions.&lt;/p&gt;

&lt;p&gt;Should &lt;code&gt;MaxOpenConns&lt;/code&gt; be 10, 25, 50, or 100?&lt;/p&gt;

&lt;p&gt;There is no universal answer.&lt;/p&gt;

&lt;p&gt;It depends on your workload and database capacity.&lt;/p&gt;

&lt;p&gt;Let's take an example.&lt;/p&gt;

&lt;p&gt;Suppose your database server allows 200 connections.&lt;/p&gt;

&lt;p&gt;Your architecture has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 application instances.&lt;/li&gt;
&lt;li&gt;1 background worker service.&lt;/li&gt;
&lt;li&gt;1 scheduled job service.&lt;/li&gt;
&lt;li&gt;Database administration and migration connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If every application instance configures:&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMaxOpenConns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then your three application instances alone could potentially open 300 connections.&lt;/p&gt;

&lt;p&gt;That's already more than the database's total connection limit.&lt;/p&gt;

&lt;p&gt;Remember:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The connection limit applies to the database server, not just one application instance.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A better way to think about it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database connection budget
    |
    +-- Application instance 1
    +-- Application instance 2
    +-- Application instance 3
    +-- Background workers
    +-- Scheduled jobs
    +-- Migrations and administration
    +-- Operational reserve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The total possible connections across all these consumers must fit within the database's available capacity.&lt;/p&gt;

&lt;p&gt;You should also leave room for database maintenance and other operational needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What factors should influence the pool size?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Number of application instances&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A pool size of 25 across four instances can potentially mean 100 connections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Query execution time&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Long-running queries occupy connections longer, increasing contention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Request concurrency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A large number of concurrent requests doesn't automatically mean you need an equally large database pool. Many requests may not need the database simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Database capacity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The database must be able to handle the number of concurrent queries efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Background jobs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Workers and scheduled tasks also consume connections and must be included in your calculations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Connection limits of your database infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Managed databases, self-hosted databases and connection proxies may impose different limits.&lt;/p&gt;

&lt;h3&gt;
  
  
  A practical approach
&lt;/h3&gt;

&lt;p&gt;Start with a conservative pool size.&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load test realistic traffic.&lt;/li&gt;
&lt;li&gt;Monitor &lt;code&gt;InUse&lt;/code&gt;, &lt;code&gt;Idle&lt;/code&gt;, &lt;code&gt;WaitCount&lt;/code&gt; and &lt;code&gt;WaitDuration&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check query latency and database CPU.&lt;/li&gt;
&lt;li&gt;Identify whether connection waits are caused by slow queries or insufficient pool capacity.&lt;/li&gt;
&lt;li&gt;Increase the limit gradually if the database has capacity.&lt;/li&gt;
&lt;li&gt;Repeat the load test and compare results.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't increase the pool size simply because requests are waiting.&lt;/p&gt;

&lt;p&gt;More connections can increase database contention and make the situation worse.&lt;/p&gt;

&lt;p&gt;The objective isn't to maximize the number of connections.&lt;/p&gt;

&lt;p&gt;It's to find a balance between application concurrency and database capacity.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Best practices for production applications
&lt;/h2&gt;

&lt;p&gt;Let's put the important practices together.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create one shared database pool
&lt;/h3&gt;

&lt;p&gt;Initialize &lt;code&gt;*sql.DB&lt;/code&gt; during application startup and reuse it.&lt;/p&gt;

&lt;p&gt;Avoid creating a new pool for every request or repository operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Always close query rows
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;rows&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do this immediately after successfully obtaining rows.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Always complete transactions
&lt;/h3&gt;

&lt;p&gt;Use a clear commit or rollback path.&lt;/p&gt;

&lt;p&gt;A deferred rollback is a useful safety net for early returns.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Use context-aware database operations
&lt;/h3&gt;

&lt;p&gt;Prefer:&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BeginTx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use sensible deadlines based on the operation and API requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Don't hold connections longer than necessary
&lt;/h3&gt;

&lt;p&gt;Avoid performing unrelated work while holding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open result sets.&lt;/li&gt;
&lt;li&gt;Transactions.&lt;/li&gt;
&lt;li&gt;Reserved connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, don't make an external HTTP request while holding a database transaction unless that is an intentional and carefully designed requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Monitor pool statistics
&lt;/h3&gt;

&lt;p&gt;Expose connection pool metrics and alert on sustained saturation, increasing wait time and unusual connection usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Monitor the database too
&lt;/h3&gt;

&lt;p&gt;Application metrics alone aren't enough.&lt;/p&gt;

&lt;p&gt;Track database CPU, memory, query latency, locks, active sessions and connection usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Size pools across all application instances
&lt;/h3&gt;

&lt;p&gt;Don't configure every instance independently without considering the total database connection budget.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Use query timeouts and appropriate indexes
&lt;/h3&gt;

&lt;p&gt;A slow query can occupy a connection just as effectively as a leaked connection.&lt;/p&gt;

&lt;p&gt;Optimize the query instead of blindly increasing the pool.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Test under concurrency
&lt;/h3&gt;

&lt;p&gt;A database operation that works perfectly in a single-request test may behave very differently under concurrent load.&lt;/p&gt;

&lt;p&gt;Load testing and integration testing can expose resource lifecycle problems before production does.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. A few misconceptions worth clearing up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Misconception 1: Increasing &lt;code&gt;MaxOpenConns&lt;/code&gt; always fixes connection exhaustion.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not true. If connections are leaking or queries are too slow, increasing the limit may only delay the problem or overload the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 2: &lt;code&gt;sql.Open()&lt;/code&gt; immediately creates a database connection.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not necessarily. It creates a pool handle. Use &lt;code&gt;PingContext()&lt;/code&gt; when you need to verify connectivity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 3: Idle connections are bad.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not necessarily. Idle connections are reusable resources. The problem is keeping more of them than your workload or infrastructure needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 4: Every connection leak is caused by forgetting &lt;code&gt;rows.Close()&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Unfinished transactions, reserved connections that aren't closed, slow operations and other resource-lifecycle issues can also cause pool exhaustion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 5: A healthy database means the application can always query it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not true. Your application's local connection pool can be exhausted even when the database server itself is healthy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 6: &lt;code&gt;MaxOpenConns&lt;/code&gt; should match the number of API requests.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Many API requests don't execute database queries simultaneously. Pool sizing should be based on actual database concurrency and server capacity.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Your production debugging checklist
&lt;/h2&gt;

&lt;p&gt;If your application suddenly starts timing out while communicating with the database, here's a practical checklist to follow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Check whether &lt;code&gt;InUse&lt;/code&gt; has reached &lt;code&gt;MaxOpenConnections&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] Check whether &lt;code&gt;Idle&lt;/code&gt; is consistently zero.&lt;/li&gt;
&lt;li&gt;[ ] Compare &lt;code&gt;WaitCount&lt;/code&gt; and &lt;code&gt;WaitDuration&lt;/code&gt; over time.&lt;/li&gt;
&lt;li&gt;[ ] Check for missing &lt;code&gt;rows.Close()&lt;/code&gt; calls.&lt;/li&gt;
&lt;li&gt;[ ] Check whether transactions are always committed or rolled back.&lt;/li&gt;
&lt;li&gt;[ ] Look for reserved connections that aren't closed.&lt;/li&gt;
&lt;li&gt;[ ] Identify long-running queries.&lt;/li&gt;
&lt;li&gt;[ ] Inspect database locks and &lt;code&gt;idle in transaction&lt;/code&gt; sessions.&lt;/li&gt;
&lt;li&gt;[ ] Separate connection acquisition time from query execution time.&lt;/li&gt;
&lt;li&gt;[ ] Check total connections across all application instances.&lt;/li&gt;
&lt;li&gt;[ ] Review context deadlines and query timeouts.&lt;/li&gt;
&lt;li&gt;[ ] Load test the fix before deploying it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This checklist won't automatically identify every possible issue, but it gives you a systematic place to start instead of randomly changing pool configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Database connection pooling is not just about setting &lt;code&gt;MaxOpenConns&lt;/code&gt; and &lt;code&gt;MaxIdleConns&lt;/code&gt; and moving on.&lt;/p&gt;

&lt;p&gt;It's about understanding how your application acquires, uses and releases database connections.&lt;/p&gt;

&lt;p&gt;A missing &lt;code&gt;rows.Close()&lt;/code&gt;, an unfinished transaction, or a query that takes much longer than expected can occupy connections and eventually prevent the rest of your application from accessing the database.&lt;/p&gt;

&lt;p&gt;The interesting part is that the database might be completely healthy while your application is unable to execute another query.&lt;/p&gt;

&lt;p&gt;That's why connection pool monitoring, proper resource cleanup, query optimization and realistic pool sizing are all important parts of building reliable backend systems.&lt;/p&gt;

&lt;p&gt;If there's one thing I'd like you to take away from this article, it's this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't just monitor whether your database is up. Monitor whether your application can actually get a connection to use it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because sometimes, the problem isn't that your database stopped working. It's that your application ran out of ways to talk to it.&lt;/p&gt;




&lt;p&gt;💬 &lt;strong&gt;Have you ever debugged a connection pool exhaustion issue in a production application?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What was the actual root cause - a connection leak, a long-running query, an unfinished transaction, or something else?&lt;/p&gt;

&lt;p&gt;I'd love to hear about real-world debugging experiences in the comments.&lt;/p&gt;

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

</description>
      <category>database</category>
      <category>debugging</category>
      <category>learning</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>🧩 JavaScript Promises Inside Promises: The Hidden Bugs, Execution Flow and How to Fix Them</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Fri, 02 Oct 2026 13:10:36 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/javascript-promises-inside-promises-the-hidden-bugs-execution-flow-and-how-to-fix-them-4p16</link>
      <guid>https://dev.to/fazal_mansuri_/javascript-promises-inside-promises-the-hidden-bugs-execution-flow-and-how-to-fix-them-4p16</guid>
      <description>&lt;p&gt;Have you ever debugged JavaScript code where a function says &lt;strong&gt;“Done!”&lt;/strong&gt;, but the operation it depends on is still running?&lt;/p&gt;

&lt;p&gt;Or perhaps an API request fails, but the error never reaches the &lt;code&gt;catch()&lt;/code&gt; block you expected to handle it.&lt;/p&gt;

&lt;p&gt;You inspect the code. You see &lt;code&gt;.then()&lt;/code&gt;, another &lt;code&gt;.then()&lt;/code&gt;, maybe a &lt;code&gt;new Promise()&lt;/code&gt; inside another Promise and suddenly the execution flow becomes difficult to follow.&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;

&lt;p&gt;As JavaScript developers, we use Promises for API calls, database operations, file processing, authentication, background tasks and countless other asynchronous operations. Yet some of the bugs we encounter aren't caused by Promises themselves. They're caused by how we connect them.&lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;saveUser&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;User saved successfully!&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;p&gt;Looks reasonable, right?&lt;/p&gt;

&lt;p&gt;But what if &lt;code&gt;saveUser()&lt;/code&gt; returns a Promise?&lt;/p&gt;

&lt;p&gt;The success message can appear &lt;strong&gt;before the save operation finishes&lt;/strong&gt;. Worse, if saving fails, the error might not reach the error handler you intended to use.&lt;/p&gt;

&lt;p&gt;The problem isn't that Promises are outdated or that nested Promises are always bad. The problem is understanding &lt;strong&gt;which asynchronous operation the current chain is actually waiting for&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we'll work through these issues step by step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What really happens when a Promise is created inside another Promise?&lt;/li&gt;
&lt;li&gt;How does JavaScript execute synchronous code, Promise callbacks and timers?&lt;/li&gt;
&lt;li&gt;Why does forgetting &lt;code&gt;return&lt;/code&gt; break a Promise chain?&lt;/li&gt;
&lt;li&gt;How do nested Promises differ from normal Promise chaining?&lt;/li&gt;
&lt;li&gt;Does the same bug happen with &lt;code&gt;async/await&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;When should you use Promises, &lt;code&gt;async/await&lt;/code&gt;, &lt;code&gt;Promise.all()&lt;/code&gt;, or a background task?&lt;/li&gt;
&lt;li&gt;How can you debug these problems in a real application?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with a bug we can reproduce.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. First, let's reproduce the bug
&lt;/h2&gt;

&lt;p&gt;Imagine you're building a user registration API.&lt;/p&gt;

&lt;p&gt;After a user registers, your application needs to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the user's information.&lt;/li&gt;
&lt;li&gt;Send a welcome email.&lt;/li&gt;
&lt;li&gt;Confirm that registration has completed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For simplicity, we'll simulate the database and email operations using Promises.&lt;/p&gt;

&lt;h3&gt;
  
  
  The buggy implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveUser&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;1. User saved to database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fazal&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="mi"&gt;1000&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="s2"&gt;`2. Welcome email sent to &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&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="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;sendWelcomeEmail&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;3. Registration completed successfully&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="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do you expect to happen?&lt;/p&gt;

&lt;p&gt;A reasonable expectation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User saved to database
2. Welcome email sent to Fazal
3. Registration completed successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the actual output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User saved to database
3. Registration completed successfully
2. Welcome email sent to Fazal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait. Why?&lt;/p&gt;

&lt;p&gt;We called &lt;code&gt;sendWelcomeEmail(user)&lt;/code&gt; before logging the success message. Shouldn't JavaScript wait for it?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No. Calling an asynchronous function that returns a Promise does not automatically make the surrounding code wait for that Promise.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's understand exactly where the execution flow goes wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  What JavaScript actually does
&lt;/h3&gt;

&lt;p&gt;Look at this callback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sendWelcomeEmail&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function calls &lt;code&gt;sendWelcomeEmail(user)&lt;/code&gt;, which starts the email operation and returns a Promise.&lt;/p&gt;

&lt;p&gt;But the callback doesn't return that Promise.&lt;/p&gt;

&lt;p&gt;From the Promise chain's perspective, this callback returns &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means the next &lt;code&gt;.then()&lt;/code&gt; doesn't need to wait for the email operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;saveUser()
    |
    | Promise fulfills
    v
First .then()
    |
    | Starts email operation
    | Does NOT return its Promise
    v
First .then() fulfills with undefined
    |
    v
Second .then()
    |
    | Runs immediately after the previous
    | Promise reaction completes
    v
"Registration completed successfully"
    |
    | Email operation is still running
    v
"Welcome email sent to Fazal"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact wording matters here: the next &lt;code&gt;.then()&lt;/code&gt; doesn't run synchronously inside the previous callback. It runs as a Promise reaction after the preceding chain Promise fulfills. But because the preceding callback returned &lt;code&gt;undefined&lt;/code&gt;, that fulfillment doesn't depend on the email Promise.&lt;/p&gt;

&lt;p&gt;This is the central bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix: return the Promise
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&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="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;3. Registration completed successfully&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User saved to database
2. Welcome email sent to Fazal
3. Registration completed successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We changed only one thing: &lt;strong&gt;we returned the inner Promise&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;JavaScript can now connect the two asynchronous operations into one chain.&lt;/p&gt;

&lt;p&gt;A shorter version works too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&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="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;3. Registration completed successfully&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an arrow function has an expression body, that expression is returned implicitly. Here, the expression is the Promise returned by &lt;code&gt;sendWelcomeEmail()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Keep this rule in mind throughout the article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the next step must wait for an asynchronous operation, make sure that operation's Promise is returned or awaited.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But why does returning a Promise work? To understand that, we need to look at how Promises actually behave.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. What is a Promise, really?
&lt;/h2&gt;

&lt;p&gt;A Promise represents the eventual outcome of an asynchronous operation.&lt;/p&gt;

&lt;p&gt;It can be in one of three states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pending:&lt;/strong&gt; The operation hasn't settled yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fulfilled:&lt;/strong&gt; The operation completed successfully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected:&lt;/strong&gt; The operation failed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Promise that has fulfilled or rejected is called &lt;em&gt;settled&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Data loaded&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;value&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;Output after approximately one second:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data loaded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Promise starts pending. After the timer callback runs, it fulfills with &lt;code&gt;"Data loaded"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.then()&lt;/code&gt; callback runs as a Promise reaction, rather than being invoked immediately by the call to &lt;code&gt;resolve()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One important distinction: &lt;strong&gt;a Promise doesn't make an operation asynchronous by itself&lt;/strong&gt;. The operation may involve a timer, network request, or other asynchronous API. A Promise provides a way to represent and compose its outcome.&lt;/p&gt;

&lt;p&gt;Also, the Promise executor—the function passed to &lt;code&gt;new Promise()&lt;/code&gt;—runs synchronously.&lt;/p&gt;

&lt;p&gt;Let's verify that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;1. Before&lt;/span&gt;&lt;span class="dl"&gt;"&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;promise&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;2. Inside executor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&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="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;4.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;3. After&lt;/span&gt;&lt;span class="dl"&gt;"&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 plaintext"&gt;&lt;code&gt;1. Before
2. Inside executor
3. After
4. Done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JavaScript logs &lt;code&gt;"Before"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The Promise constructor immediately invokes its executor, so &lt;code&gt;"Inside executor"&lt;/code&gt; appears next.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resolve("Done")&lt;/code&gt; fulfills the Promise, but its &lt;code&gt;.then()&lt;/code&gt; reaction doesn't run inline.&lt;/li&gt;
&lt;li&gt;JavaScript continues with the remaining synchronous code.&lt;/li&gt;
&lt;li&gt;The Promise reaction runs as a microtask.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This distinction becomes important when you see a Promise inside another Promise.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. What happens when a Promise is inside another Promise?
&lt;/h2&gt;

&lt;p&gt;There are two patterns that developers often confuse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern A: Returning a Promise from another Promise
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outerPromise&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;innerResolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;innerResolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Inner operation completed&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="mi"&gt;1000&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="nx"&gt;outerPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;result&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;Output after approximately one second:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inner operation completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something important: &lt;code&gt;outerPromise&lt;/code&gt; doesn't fulfill with the inner Promise object as its final value.&lt;/p&gt;

&lt;p&gt;When a Promise is resolved with another Promise, it adopts the inner Promise's eventual state and outcome.&lt;/p&gt;

&lt;p&gt;In this example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The outer Promise's executor starts synchronously.&lt;/li&gt;
&lt;li&gt;The inner Promise is created and its executor also starts synchronously.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resolve(innerPromise)&lt;/code&gt; resolves the outer Promise to follow the inner Promise.&lt;/li&gt;
&lt;li&gt;The timer eventually fulfills the inner Promise.&lt;/li&gt;
&lt;li&gt;The outer Promise then fulfills with &lt;code&gt;"Inner operation completed"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The outer Promise's &lt;code&gt;.then()&lt;/code&gt; reaction receives that string.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outer Promise
     |
     | resolved with inner Promise
     v
Inner Promise
     |
     | pending for 1 second
     v
Fulfilled with a string
     |
     v
Outer Promise fulfills with the same outcome
     |
     v
.then() receives the string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behavior is part of Promise resolution. It's why Promise chains can be composed without manually inspecting whether each returned value is itself a Promise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern B: Creating a Promise but not returning it
&lt;/h3&gt;

&lt;p&gt;Now compare that with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outerPromise&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;innerResolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;innerResolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Inner operation completed&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Outer operation completed&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="nx"&gt;outerPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;result&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outer operation completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inner Promise still runs. After approximately one second, it fulfills with &lt;code&gt;"Inner operation completed"&lt;/code&gt;, but nothing consumes that result.&lt;/p&gt;

&lt;p&gt;The outer Promise doesn't wait for it because the inner Promise was neither returned from a relevant callback nor used to resolve the outer Promise.&lt;/p&gt;

&lt;p&gt;This is a subtle but important distinction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creating a Promise&lt;/strong&gt; starts the executor and establishes an asynchronous result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Returning a Promise from a &lt;code&gt;.then()&lt;/code&gt; callback&lt;/strong&gt; connects its outcome to the chain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolving a Promise with another Promise&lt;/strong&gt; makes the first Promise adopt the second Promise's outcome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are related concepts, but they aren't interchangeable.&lt;/p&gt;

&lt;h3&gt;
  
  
  A complete execution-order example
&lt;/h3&gt;

&lt;p&gt;Let's combine synchronous execution, nested Promise creation, a timer and &lt;code&gt;.then()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;0. Start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;1. Outer executor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;innerResolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;2. Inner executor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;4. Inner timer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nf"&gt;innerResolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fazal&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="mi"&gt;1000&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="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;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;5. User:&lt;/span&gt;&lt;span class="dl"&gt;"&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="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;3. End&lt;/span&gt;&lt;span class="dl"&gt;"&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 plaintext"&gt;&lt;code&gt;0. Start
1. Outer executor
2. Inner executor
3. End
4. Inner timer
5. User: Fazal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two executor messages appear immediately because both executors run synchronously. The &lt;code&gt;"End"&lt;/code&gt; message follows because JavaScript continues running synchronous code. The timer callback executes later and the &lt;code&gt;.then()&lt;/code&gt; callback runs after the Promise has fulfilled.&lt;/p&gt;

&lt;p&gt;You don't need to memorize this particular output. You need to understand &lt;strong&gt;which operations are synchronous, which callbacks are scheduled and which Promise outcomes are connected&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Nested &lt;code&gt;.then()&lt;/code&gt; callbacks vs. Promise chaining
&lt;/h2&gt;

&lt;p&gt;Let's return to the registration example.&lt;/p&gt;

&lt;p&gt;A nested version might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&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="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Email step completed&lt;/span&gt;&lt;span class="dl"&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;user&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="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;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;Registration flow completed for&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is valid JavaScript. The inner &lt;code&gt;.then()&lt;/code&gt; returns a Promise and the outer callback returns that Promise. The whole chain waits for the email operation.&lt;/p&gt;

&lt;p&gt;But nesting adds indentation and makes longer flows harder to follow.&lt;/p&gt;

&lt;p&gt;We can express the same dependency using a flat chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;registeredUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;registeredUser&lt;/span&gt; &lt;span class="o"&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;return&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Email step completed&lt;/span&gt;&lt;span class="dl"&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;registeredUser&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="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;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;Registration flow completed for&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both versions wait for the email operation.&lt;/p&gt;

&lt;p&gt;The flat chain makes the sequence easier to scan, although it uses a variable to preserve the user value. In production, you should consider whether that extra state is necessary and whether it makes the flow clearer.&lt;/p&gt;

&lt;p&gt;You can also preserve the user value without an outer variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&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="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, using &lt;code&gt;async/await&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There isn't a universal rule that every nested &lt;code&gt;.then()&lt;/code&gt; is wrong. Nesting is sometimes natural when a local operation has its own result handling. The problem is accidental nesting that hides dependencies, loses return values, or makes error handling confusing.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The missing &lt;code&gt;return&lt;/code&gt;: a small mistake with several consequences
&lt;/h2&gt;

&lt;p&gt;Let's examine the most common version of this bug more closely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 1: The next step starts too early
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&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="nf"&gt;chargePayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;updateOrderStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Order processing completed&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;updateOrderStatus()&lt;/code&gt; returns a Promise, the final callback doesn't wait for it.&lt;/p&gt;

&lt;p&gt;Correct version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&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="nf"&gt;chargePayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;updateOrderStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Order processing completed&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the next step waits for the status update.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 2: Errors don't propagate through the expected chain
&lt;/h3&gt;

&lt;p&gt;Suppose an inner operation rejects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&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="nf"&gt;chargePayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;updateOrderStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;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;Order processing failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;If &lt;code&gt;updateOrderStatus()&lt;/code&gt; returns a Promise that rejects, the &lt;code&gt;.catch()&lt;/code&gt; above won't catch that rejection through this chain because its Promise was never returned.&lt;/p&gt;

&lt;p&gt;Correct version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&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="nf"&gt;chargePayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;updateOrderStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;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;Order processing failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;Notice the &lt;code&gt;throw error&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Without it, the &lt;code&gt;.catch()&lt;/code&gt; callback would fulfill the chain with &lt;code&gt;undefined&lt;/code&gt; if it simply logged the error and returned nothing. Downstream code could then mistake the failure for success.&lt;/p&gt;

&lt;p&gt;You should decide whether to rethrow, recover with a fallback, or handle the error and intentionally return a successful result. The right choice depends on the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 3: The caller receives a result too early
&lt;/h3&gt;

&lt;p&gt;Imagine a function that should return the saved record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&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="nf"&gt;saveProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;refreshSearchIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&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;The caller receives a Promise that fulfills with &lt;code&gt;undefined&lt;/code&gt; after the callback finishes—not with the search-index operation's result.&lt;/p&gt;

&lt;p&gt;If the caller expects to wait for indexing too, return its Promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&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="nf"&gt;saveProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;refreshSearchIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&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;If the caller needs the saved profile as its result after indexing finishes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&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="nf"&gt;saveProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;refreshSearchIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;savedProfile&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 makes the intended result explicit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Don't return a Promise just to make every operation sequential. Return it when the caller needs to wait for that operation or depend on its outcome. Independent work may be better handled concurrently or in the background.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Is this bug specific to Promises, or does it also happen with &lt;code&gt;async/await&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;This is an excellent question because &lt;code&gt;async/await&lt;/code&gt; often makes asynchronous code easier to read, but it doesn't eliminate the underlying problem.&lt;/p&gt;

&lt;p&gt;The bug is &lt;strong&gt;generic to asynchronous control flow&lt;/strong&gt;. It happens whenever the program starts work but fails to connect that work to the sequence that depends on it.&lt;/p&gt;

&lt;p&gt;Let's translate the registration example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incorrect &lt;code&gt;async/await&lt;/code&gt; implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;sendWelcomeEmail&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;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;Registration completed successfully&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;registerUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output can still be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User saved to database
3. Registration completed successfully
2. Welcome email sent to Fazal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;sendWelcomeEmail(user)&lt;/code&gt; starts the operation, but the function doesn't &lt;code&gt;await&lt;/code&gt; its Promise.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;async&lt;/code&gt; keyword does not automatically wait for every Promise created inside the function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Correct implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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;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;Registration completed successfully&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;registerUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the function waits for the email operation before logging success.&lt;/p&gt;

&lt;p&gt;The difference is not that &lt;code&gt;async/await&lt;/code&gt; has magical asynchronous behavior. It provides syntax for expressing the dependency clearly.&lt;/p&gt;

&lt;p&gt;Compare the two patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Promise chaining&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Registration completed&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// async/await&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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;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;Registration completed&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;p&gt;Both can represent the same sequence of operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  A useful rule
&lt;/h3&gt;

&lt;p&gt;If a later step must wait for an asynchronous operation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With Promise chaining, &lt;strong&gt;return the Promise&lt;/strong&gt; from the callback.&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;async/await&lt;/code&gt;, &lt;strong&gt;await the Promise&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The underlying principle is the same: explicitly connect the operation to the control flow that depends on it.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Error handling: &lt;code&gt;.catch()&lt;/code&gt; vs. &lt;code&gt;try/catch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Correct sequencing is only half the story. We also need to understand how failures propagate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promise-based error handling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&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="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Registration completed&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="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;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;Registration failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;A rejection from &lt;code&gt;saveUser()&lt;/code&gt; or &lt;code&gt;sendWelcomeEmail()&lt;/code&gt; can propagate to the final &lt;code&gt;.catch()&lt;/code&gt; because each operation is connected to the chain.&lt;/p&gt;

&lt;p&gt;If the email operation rejects, the success callback is skipped and the error handler runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  The equivalent &lt;code&gt;async/await&lt;/code&gt; approach
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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;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;Registration completed&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;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;Registration failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;The &lt;code&gt;try/catch&lt;/code&gt; handles rejections from the awaited operations.&lt;/p&gt;

&lt;p&gt;However, consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;sendWelcomeEmail&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;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;Registration completed&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;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;Registration failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;If &lt;code&gt;sendWelcomeEmail()&lt;/code&gt; returns a Promise that rejects, this &lt;code&gt;catch&lt;/code&gt; won't catch that rejection through the &lt;code&gt;try&lt;/code&gt; block because the Promise wasn't awaited. It may instead become an unhandled rejection, depending on what else handles it.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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;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;Registration completed&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;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;Registration failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;There is one additional nuance: &lt;code&gt;try/catch&lt;/code&gt; catches synchronous exceptions thrown while executing the &lt;code&gt;try&lt;/code&gt; block, as well as rejections from awaited Promises. It doesn't automatically catch failures from unrelated asynchronous operations that you start and leave unawaited.&lt;/p&gt;

&lt;p&gt;That is why &lt;code&gt;await&lt;/code&gt; matters for error handling as well as sequencing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should you always rethrow an error?
&lt;/h3&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Rethrow when the caller needs to know the operation failed. Recover when you have a meaningful fallback. Handle the error without rethrowing only when the function's contract says the failure has been dealt with and downstream code should continue.&lt;/p&gt;

&lt;p&gt;For example, an optional analytics event might fail without preventing an order from being completed. A payment failure should not be silently swallowed.&lt;/p&gt;

&lt;p&gt;Error handling should reflect the business requirement, not just the syntax.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Promise vs. &lt;code&gt;async/await&lt;/code&gt;: which should you use?
&lt;/h2&gt;

&lt;p&gt;This isn't a competition in which one syntax is always correct. &lt;code&gt;async/await&lt;/code&gt; is built on Promises and is often easier to read for sequential workflows, while Promise methods remain valuable for composition and concurrency.&lt;/p&gt;

&lt;p&gt;Here's a practical comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario A: Sequential operations
&lt;/h3&gt;

&lt;p&gt;Suppose you need to fetch a user, then fetch that user's orders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Promise chaining:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchOrders&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;id&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;&lt;strong&gt;Using &lt;code&gt;async/await&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchOrders&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;id&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;orders&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;Both are valid. The second version can be easier to follow when the workflow contains many steps, conditions, or intermediate variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario B: Several independent operations
&lt;/h3&gt;

&lt;p&gt;Suppose a dashboard needs user information, notifications and recommendations. None depends on the others.&lt;/p&gt;

&lt;p&gt;This version unnecessarily runs the operations sequentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadDashboard&lt;/span&gt;&lt;span class="p"&gt;()&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&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;notifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchNotifications&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;recommendations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchRecommendations&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recommendations&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;If each operation takes time, the total duration can approach the sum of their durations.&lt;/p&gt;

&lt;p&gt;Instead, start the independent operations together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadDashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&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;notifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recommendations&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nf"&gt;fetchNotifications&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nf"&gt;fetchRecommendations&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="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;notifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recommendations&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;&lt;code&gt;Promise.all()&lt;/code&gt; fulfills when all supplied Promises fulfill. If one rejects, the returned Promise rejects with that failure, though the other operations aren't automatically cancelled and may continue running.&lt;/p&gt;

&lt;p&gt;This is a common example of using &lt;code&gt;async/await&lt;/code&gt; and Promise composition together. You don't need to choose one or the other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario C: Independent operations where partial results matter
&lt;/h3&gt;

&lt;p&gt;Suppose you're loading data from five optional integrations. One failing shouldn't prevent you from displaying the successful results.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;Promise.allSettled()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadIntegrations&lt;/span&gt;&lt;span class="p"&gt;()&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;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;fetchCalendar&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;fetchTasks&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;fetchNotifications&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fulfilled&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="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;Loaded:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Integration failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&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="nx"&gt;results&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 waits for every supplied Promise to settle and gives you the outcome of each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario D: You want a Promise chain without an &lt;code&gt;async&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;Sometimes a small function can be expressed naturally as a chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getDisplayName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;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;Unable to load user:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;You don't have to introduce &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; just because it exists. Promise chaining is still useful, particularly when transforming results or composing functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  A practical decision guide
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;A useful approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Several dependent steps&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;async/await&lt;/code&gt; or a returned Promise chain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Several independent operations&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Promise.all()&lt;/code&gt; with &lt;code&gt;async/await&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need the outcome of every operation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise.allSettled()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simple result transformation&lt;/td&gt;
&lt;td&gt;Promise chaining&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex branching and intermediate values&lt;/td&gt;
&lt;td&gt;Often &lt;code&gt;async/await&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Background work that shouldn't block the caller&lt;/td&gt;
&lt;td&gt;Explicit background-task handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to handle each operation's failure separately&lt;/td&gt;
&lt;td&gt;Local &lt;code&gt;try/catch&lt;/code&gt; or per-Promise &lt;code&gt;.catch()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are guidelines, not strict rules. Readability, error-handling requirements, cancellation needs and the behavior expected by the caller all matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. One real-world decision: should the email block registration?
&lt;/h2&gt;

&lt;p&gt;Our registration example assumes that registration isn't complete until the email has been sent.&lt;/p&gt;

&lt;p&gt;But is that always the correct design?&lt;/p&gt;

&lt;p&gt;Imagine the database save succeeds and the email provider takes five seconds to respond. Should the user wait five seconds before receiving a successful registration response?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;This is where we must distinguish a JavaScript bug from a product or architecture decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Email is part of the required workflow
&lt;/h3&gt;

&lt;p&gt;If the operation must finish before the caller can proceed, return or await the email Promise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The caller receives the user only after the awaited email operation fulfills. If it rejects, the function rejects unless the error is handled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B: Registration should succeed independently of email delivery
&lt;/h3&gt;

&lt;p&gt;If the user should be registered even when the email provider is temporarily unavailable, don't pretend that the email is part of the same success condition.&lt;/p&gt;

&lt;p&gt;A simple illustrative approach is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendWelcomeEmail&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;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;Welcome email failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Record or schedule a retry if the application supports it.&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;user&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 waits for the email attempt but doesn't let its failure reject registration. It is not truly non-blocking, though, because the function still waits for the attempt to settle.&lt;/p&gt;

&lt;p&gt;If email delivery should happen independently, a background job or durable queue is usually more appropriate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Registration request
       |
       v
Save user + record email job
       |
       v
Return registration result
       |
       v
Background worker
       |
       v
Send email and retry if needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a production system, you would need to consider how the job is persisted, retried and monitored. A simple fire-and-forget call such as &lt;code&gt;sendWelcomeEmail(user)&lt;/code&gt; is not a reliable substitute for a durable background-work mechanism.&lt;/p&gt;

&lt;p&gt;This illustrates an important lesson: &lt;strong&gt;waiting for an operation, handling its failure and deciding whether it belongs in the critical path are three separate decisions.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  10. How to debug confusing Promise execution flow
&lt;/h2&gt;

&lt;p&gt;When asynchronous code behaves unexpectedly, don't start by rewriting everything with &lt;code&gt;async/await&lt;/code&gt;. First establish which Promise represents which operation.&lt;/p&gt;

&lt;p&gt;Here is a practical checklist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Add logs at the boundaries
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&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;Starting update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;saveProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Profile saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;refreshSearchIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedProfile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Index refreshed&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log before and after each important operation. This helps you see whether the unexpected order is caused by missing Promise composition or by the operation itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Inspect every asynchronous callback
&lt;/h3&gt;

&lt;p&gt;For every &lt;code&gt;.then()&lt;/code&gt; callback, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this callback start another asynchronous operation?&lt;/li&gt;
&lt;li&gt;Does the next step need to wait for it?&lt;/li&gt;
&lt;li&gt;If yes, am I returning its Promise?&lt;/li&gt;
&lt;li&gt;Does this callback need to preserve a value for a later step?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For every &lt;code&gt;async&lt;/code&gt; function, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the relevant operation awaited?&lt;/li&gt;
&lt;li&gt;Does the function return the value the caller expects?&lt;/li&gt;
&lt;li&gt;Is the rejection handled at the correct level?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Inspect the returned value
&lt;/h3&gt;

&lt;p&gt;A callback with braces doesn't implicitly return its contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;transformResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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 callback returns &lt;code&gt;undefined&lt;/code&gt; unless it explicitly returns something.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;transformResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;And:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;transformResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The latter two return the result of &lt;code&gt;transformResult()&lt;/code&gt;, including its Promise if it returns one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Check rejection paths, not just successful execution
&lt;/h3&gt;

&lt;p&gt;A chain may appear correct when every operation succeeds but fail when one rejects.&lt;/p&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first operation rejects.&lt;/li&gt;
&lt;li&gt;An inner asynchronous operation rejects.&lt;/li&gt;
&lt;li&gt;A callback throws synchronously.&lt;/li&gt;
&lt;li&gt;A fallback handles an error.&lt;/li&gt;
&lt;li&gt;A caller expects a result but receives &lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A successful manual test alone isn't enough to establish correct error propagation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Write down the intended dependency
&lt;/h3&gt;

&lt;p&gt;Before changing code, express the desired workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Save user
   ↓ must finish before
Send email
   ↓ must finish before
Return success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the actual requirement is different, draw that flow instead. This helps distinguish a missing &lt;code&gt;return&lt;/code&gt; or &lt;code&gt;await&lt;/code&gt; from an incorrect assumption about which operations must be sequential.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Common misconceptions worth remembering
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Misconception 1: Every Promise runs asynchronously.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The executor passed to &lt;code&gt;new Promise()&lt;/code&gt; runs synchronously. Promise reactions, such as &lt;code&gt;.then()&lt;/code&gt; callbacks, run asynchronously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 2: Creating a Promise means the current function waits for it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It doesn't. You must connect its outcome to the relevant Promise chain or await it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 3: &lt;code&gt;async&lt;/code&gt; automatically waits for all Promises inside a function.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It doesn't. &lt;code&gt;async&lt;/code&gt; makes the function return a Promise. Individual asynchronous operations still need to be awaited or explicitly composed when their completion matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 4: Nested Promises are always bad code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not true. Resolving a Promise with another Promise and returning Promises from callbacks are normal parts of Promise composition. Deeply nested callbacks may hurt readability, but nesting itself isn't proof of a bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 5: &lt;code&gt;Promise.all()&lt;/code&gt; cancels the other operations when one rejects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It doesn't automatically cancel them. Its returned Promise rejects when one of its inputs rejects, but the remaining operations may continue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 6: Converting everything to &lt;code&gt;async/await&lt;/code&gt; fixes asynchronous bugs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It can improve readability, but forgetting &lt;code&gt;await&lt;/code&gt; creates the same fundamental problem as forgetting to return a Promise from a chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. A final debugging challenge
&lt;/h2&gt;

&lt;p&gt;Before finishing, predict the output of this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;C&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;D&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="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;E&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What order do you expect?&lt;/p&gt;

&lt;p&gt;The correct output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
E
B
C
D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's why:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; runs synchronously.&lt;/li&gt;
&lt;li&gt;The first &lt;code&gt;.then()&lt;/code&gt; callback is scheduled as a Promise reaction.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;E&lt;/code&gt; runs before Promise reactions are processed.&lt;/li&gt;
&lt;li&gt;The first callback runs and logs &lt;code&gt;B&lt;/code&gt;. It creates another Promise reaction but doesn't return that inner Promise.&lt;/li&gt;
&lt;li&gt;The inner reaction logs &lt;code&gt;C&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The next callback in the outer chain logs &lt;code&gt;D&lt;/code&gt; after the first callback's returned value—&lt;code&gt;undefined&lt;/code&gt;—fulfills the preceding chain Promise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This example shows why you can't simply assume that all nested Promise callbacks execute before the next step in the outer chain. Their scheduling and Promise dependencies both matter.&lt;/p&gt;

&lt;p&gt;Try modifying the example to return the inner Promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;C&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;D&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="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;E&lt;/span&gt;&lt;span class="dl"&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 output is still:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
E
B
C
D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The visible output happens to be the same in this example, but the Promise dependency is different. With the return, the outer chain explicitly waits for the inner Promise. Without it, the two branches are not connected, even though this particular output order looks identical.&lt;/p&gt;

&lt;p&gt;That's an important debugging lesson: &lt;strong&gt;a log sequence alone doesn't always prove that asynchronous operations are correctly connected&lt;/strong&gt;. Test the behavior and rejection paths, not just the happy-path output.&lt;/p&gt;




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

&lt;p&gt;Promises aren't inherently complicated, but their behavior becomes much easier to understand once you distinguish creating an operation from connecting its outcome to the rest of your code.&lt;/p&gt;

&lt;p&gt;If you take only a few lessons from this article, remember these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Return a Promise&lt;/strong&gt; from a &lt;code&gt;.then()&lt;/code&gt; callback when the chain must wait for that operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Await a Promise&lt;/strong&gt; inside an &lt;code&gt;async&lt;/code&gt; function when subsequent code depends on its outcome.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Propagate or handle errors intentionally&lt;/strong&gt; instead of accidentally converting failures into successful results.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Promise.all()&lt;/code&gt; for independent operations that can run concurrently and choose &lt;code&gt;Promise.allSettled()&lt;/code&gt; when you need every operation's outcome.&lt;/li&gt;
&lt;li&gt;Don't assume every asynchronous task should block the caller. Decide whether it belongs in the critical path or should be handled by a background-work mechanism.&lt;/li&gt;
&lt;li&gt;Debug the dependency between operations, not just the order of console messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And remember: the same control-flow bug can appear with Promise chains and &lt;code&gt;async/await&lt;/code&gt;. Changing syntax can make code easier to read, but it doesn't replace understanding the behavior you need.&lt;/p&gt;

&lt;p&gt;The next time your application logs “Done” before the work is actually done, look for the missing &lt;code&gt;return&lt;/code&gt;, the missing &lt;code&gt;await&lt;/code&gt;, or an operation that was never connected to the flow in the first place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's often where the real bug begins.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your turn:&lt;/strong&gt; Have you ever encountered a missing &lt;code&gt;return&lt;/code&gt; or &lt;code&gt;await&lt;/code&gt; that caused a race condition or made an error disappear? Share the scenario in the comments. Real debugging experiences are often the best way for all of us to learn.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>softwaredevelopment</category>
      <category>learning</category>
    </item>
    <item>
      <title>🧠 AI Context Engineering (Part 5): Context Optimization - Give AI What It Needs, Not Everything You Have</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sun, 06 Sep 2026 10:51:31 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/ai-context-engineering-part-5-context-optimization-give-ai-what-it-needs-not-everything-you-3lhl</link>
      <guid>https://dev.to/fazal_mansuri_/ai-context-engineering-part-5-context-optimization-give-ai-what-it-needs-not-everything-you-3lhl</guid>
      <description>&lt;p&gt;We've come a long way in this series.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 1&lt;/strong&gt;, we introduced &lt;strong&gt;Context Engineering&lt;/strong&gt; and why it goes beyond writing better prompts.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 2&lt;/strong&gt;, we explored &lt;strong&gt;tokens, context windows and memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 3&lt;/strong&gt;, we looked at how AI applications get information through &lt;strong&gt;RAG, Tool Calling and MCP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And in &lt;strong&gt;Part 4&lt;/strong&gt;, we explored how &lt;strong&gt;AI agents&lt;/strong&gt; use context and tools to execute multi-step tasks.&lt;/p&gt;

&lt;p&gt;Now there's a problem.&lt;/p&gt;

&lt;p&gt;A problem that becomes increasingly important as your AI application becomes more capable.&lt;/p&gt;

&lt;p&gt;Imagine an agent working on a task for 30 minutes.&lt;/p&gt;

&lt;p&gt;During that time, it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads 20 files.&lt;/li&gt;
&lt;li&gt;Calls 15 tools.&lt;/li&gt;
&lt;li&gt;Retrieves dozens of documents.&lt;/li&gt;
&lt;li&gt;Receives thousands of lines of tool output.&lt;/li&gt;
&lt;li&gt;Makes several decisions.&lt;/li&gt;
&lt;li&gt;Encounters and resolves errors.&lt;/li&gt;
&lt;li&gt;Maintains conversation history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually, you could end up with something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System instructions
        +
Conversation history
        +
Tool definitions
        +
Retrieved documents
        +
Tool results
        +
Agent state
        +
Memory
        +
Current request
        ↓
      LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Great. The model has everything it needs."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But there's a catch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Having everything doesn't necessarily mean having the right context.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's what Part 5 is about.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 The Real Goal of Context Engineering
&lt;/h1&gt;

&lt;p&gt;The goal isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ Put as much information as possible into the context window.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ Build the smallest useful set of information required for the model to make the current decision correctly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think of context as a &lt;strong&gt;limited working budget&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You have a task.&lt;/p&gt;

&lt;p&gt;You have a certain amount of useful information.&lt;/p&gt;

&lt;p&gt;Your job is to decide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What should stay?
What should go?
What should be summarized?
What should be retrieved later?
What should be cached?
What should never enter the context?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's Context Engineering.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚨 More Context Can Become a Problem
&lt;/h1&gt;

&lt;p&gt;Consider this request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Why is the payment service returning 500?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose your system retrieves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Payment service logs
✓ Recent deployment
✓ Database errors
✓ Relevant code
✓ Configuration
✓ Recent incidents
✓ Unrelated authentication logs
✓ Old deployment logs
✓ 500 pages of documentation
✓ 20 previous conversations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, the model has more information.&lt;/p&gt;

&lt;p&gt;But did we improve the context?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;We introduced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More tokens&lt;/li&gt;
&lt;li&gt;More latency&lt;/li&gt;
&lt;li&gt;More cost&lt;/li&gt;
&lt;li&gt;More irrelevant information&lt;/li&gt;
&lt;li&gt;More opportunities for conflicting information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The useful information can become harder to distinguish from everything else.&lt;/p&gt;

&lt;p&gt;This is why:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Context quality matters more than context quantity.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recent production guidance and research on context management similarly emphasize that long agent trajectories can accumulate irrelevant history and tool output, making selection and compression important engineering problems.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 Five Ways to Optimize Context
&lt;/h1&gt;

&lt;p&gt;A practical context pipeline usually has several levers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Information
                     │
                     ▼
               ┌───────────┐
               │  Select   │
               └─────┬─────┘
                     │
                     ▼
               ┌───────────┐
               │ Retrieve  │
               └─────┬─────┘
                     │
                     ▼
               ┌───────────┐
               │ Compress  │
               └─────┬─────┘
                     │
                     ▼
               ┌───────────┐
               │  Cache    │
               └─────┬─────┘
                     │
                     ▼
               ┌───────────┐
               │   LLM     │
               └───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand each one.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣ Selection — Don't Send What You Don't Need
&lt;/h1&gt;

&lt;p&gt;The cheapest token is often the token you never send.&lt;/p&gt;

&lt;p&gt;Suppose an AI coding assistant is debugging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;payment-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Does it need the entire repository?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;It might only need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;payment/
 ├── handler.go
 ├── service.go
 ├── payment.go
 └── payment_test.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Entire Repository
        ↓
      LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Question
      ↓
Identify Relevant Files
      ↓
Only Relevant Files
      ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;strong&gt;context selection&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And it can happen before compression.&lt;/p&gt;

&lt;p&gt;Why compress information that shouldn't have been included in the first place?&lt;/p&gt;




&lt;h1&gt;
  
  
  💡 A Simple Rule
&lt;/h1&gt;

&lt;p&gt;Before adding something to context, ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Does the model need this information to make the current decision?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is no, don't send it.&lt;/p&gt;

&lt;p&gt;This sounds obvious.&lt;/p&gt;

&lt;p&gt;But it's one of the easiest things to get wrong in real systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  2️⃣ Retrieval — Fetch Information Just in Time
&lt;/h1&gt;

&lt;p&gt;Part 3 introduced RAG.&lt;/p&gt;

&lt;p&gt;Now we can look at RAG from a different perspective.&lt;/p&gt;

&lt;p&gt;Instead of loading everything upfront:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
      ↓
Load 1,000 Documents
      ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;retrieve information when it is actually relevant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
      ↓
Understand Need
      ↓
Retrieve Relevant Information
      ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful for large knowledge bases.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"What's our refund policy for enterprise customers?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no reason to load:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HR policies&lt;/li&gt;
&lt;li&gt;Engineering documentation&lt;/li&gt;
&lt;li&gt;Marketing documentation&lt;/li&gt;
&lt;li&gt;Old product specifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The retrieval layer should narrow the information down.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔍 Retrieval Is a Trade-Off
&lt;/h1&gt;

&lt;p&gt;There is no universal rule that says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Always use RAG."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have a short document that fits comfortably into the context window and is directly relevant, retrieving chunks may add unnecessary complexity.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Document: 2 pages
User: "Summarize this document."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just provide the document.&lt;/p&gt;

&lt;p&gt;But if you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 million documents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you obviously cannot send them all.&lt;/p&gt;

&lt;p&gt;Retrieval becomes valuable.&lt;/p&gt;

&lt;p&gt;The engineering question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What information should be available now and what can be fetched later?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  3️⃣ Compression — Keep the Meaning, Remove the Bulk
&lt;/h1&gt;

&lt;p&gt;Now let's say we really do need the information.&lt;/p&gt;

&lt;p&gt;But the information is huge.&lt;/p&gt;

&lt;p&gt;Consider a tool response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /orders/12345

{
    "id": 12345,
    "customer": {...},
    "shipping": {...},
    "billing": {...},
    "items": [...],
    "auditLogs": [...],
    "metadata": {...},
    "internalDebugInformation": {...}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe the agent only needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order ID: 12345
Status: FAILED
Payment Status: DECLINED
Failure Reason: Insufficient funds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why send the entire response?&lt;/p&gt;

&lt;p&gt;We can transform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Large Tool Output
        ↓
Relevant Information
        ↓
Compact Context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;strong&gt;context compression&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🗜️ Compression Is Not the Same as Deletion
&lt;/h1&gt;

&lt;p&gt;This distinction matters.&lt;/p&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;50 messages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and replace them with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"The user wants to migrate PostgreSQL
from version 14 to 16 and cannot tolerate
more than 5 minutes of downtime."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've reduced the number of tokens.&lt;/p&gt;

&lt;p&gt;But we also potentially lost information.&lt;/p&gt;

&lt;p&gt;Compression is therefore &lt;strong&gt;lossy&lt;/strong&gt; unless the representation preserves everything required for the task.&lt;/p&gt;

&lt;p&gt;Recent research on long-horizon agents specifically studies this trade-off: compressing accumulated interaction history can reduce memory requirements while trying to preserve task performance.&lt;/p&gt;

&lt;p&gt;So don't blindly summarize everything.&lt;/p&gt;

&lt;p&gt;Instead, identify what must survive.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 What Should Survive Compression?
&lt;/h1&gt;

&lt;p&gt;For an agent working on a task, a useful compact state might preserve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Goal
Current progress
Important decisions
Constraints
Known failures
Important outputs
Pending actions
Relevant identifiers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;/p&gt;

&lt;h3&gt;
  
  
  Before
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
We need to migrate the database.

Assistant:
Let's inspect the schema.

Tool:
500 lines...

Assistant:
There are 3 large tables.

Tool:
800 lines...

Assistant:
We should migrate table A first.

Tool:
...

Assistant:
Migration failed because...

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  After compaction
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Goal:
Migrate PostgreSQL database.

Progress:
Tables A and B analyzed.

Decision:
Migrate table A first.

Constraint:
Maximum downtime: 5 minutes.

Failure:
Previous migration failed due to missing index.

Next step:
Create the required index and retry.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much smaller.&lt;/p&gt;

&lt;p&gt;But much more useful.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ Don't Summarize Blindly
&lt;/h1&gt;

&lt;p&gt;This is one of the most important practical lessons.&lt;/p&gt;

&lt;p&gt;A generic instruction like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Summarize everything above."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;doesn't guarantee that the summary will preserve the information your application needs later.&lt;/p&gt;

&lt;p&gt;Imagine the original context contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Maximum allowed downtime: 5 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the summary accidentally removes that constraint, the agent might make a technically valid but operationally dangerous decision.&lt;/p&gt;

&lt;p&gt;So compression should have &lt;strong&gt;explicit preservation rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Always preserve:
- User requirements
- Hard constraints
- IDs
- Decisions
- Pending actions
- Important errors
- Security restrictions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much safer than generic summarization.&lt;/p&gt;




&lt;h1&gt;
  
  
  4️⃣ Caching — Don't Recompute What Hasn't Changed
&lt;/h1&gt;

&lt;p&gt;Now let's talk about something different.&lt;/p&gt;

&lt;p&gt;Suppose your application repeatedly sends a large, mostly stable piece of context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System Instructions
+
Tool Definitions
+
Large Reference Information
+
User Request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the first three parts rarely change, repeatedly processing them can be wasteful.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;prompt caching / provider-side caching mechanisms&lt;/strong&gt; can help, depending on the model provider.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────┐
│ Stable Context              │
│                             │
│ System Instructions         │
│ Tool Definitions            │
│ Reference Information       │
└──────────────┬──────────────┘
               │
             CACHE
               │
               ▼
       Current User Request
               │
               ▼
              LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact caching behavior, eligibility rules, pricing and cache lifetime depend on the provider.&lt;/p&gt;

&lt;p&gt;So don't assume:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Caching means the model remembers everything."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;Caching is an &lt;strong&gt;infrastructure optimization&lt;/strong&gt;, not the same thing as memory.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 Memory ≠ Cache ≠ Context
&lt;/h1&gt;

&lt;p&gt;This is worth clarifying because these concepts are frequently mixed together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;Information available to the model for the current inference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current request
+
Relevant history
+
Retrieved information
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Memory
&lt;/h3&gt;

&lt;p&gt;Information intentionally retained for future interactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User preference
+
Long-term facts
+
Previous task state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cache
&lt;/h3&gt;

&lt;p&gt;Previously processed/reusable information used to reduce repeated work, depending on the implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stable prompt prefix
+
Reusable computation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They solve different problems.&lt;/p&gt;




&lt;h1&gt;
  
  
  5️⃣ Structure — Context Isn't Just About What You Send
&lt;/h1&gt;

&lt;p&gt;There's another subtle aspect:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How you organize the information matters.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine giving an engineer this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database:
PostgreSQL

Issue:
Connection timeout

Logs:
...

User:
...

Instructions:
...

Relevant configuration:
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYSTEM INSTRUCTIONS

TASK

CONSTRAINTS

RELEVANT EVIDENCE

TOOL RESULTS

CURRENT STATE

USER REQUEST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structured context makes it easier for both developers and models to distinguish different types of information.&lt;/p&gt;

&lt;p&gt;A useful pattern is to separate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stable information
        +
Dynamic information
        +
Retrieved information
        +
Current task
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also makes your system easier to debug.&lt;/p&gt;

&lt;p&gt;When something goes wrong, you can inspect &lt;strong&gt;which context component caused the problem&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  💰 Token Optimization Is More Than "Use Fewer Tokens"
&lt;/h1&gt;

&lt;p&gt;Suppose an agent executes 20 steps.&lt;/p&gt;

&lt;p&gt;And each step sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000 input tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's potentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20 × 10,000
=
200,000 input tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;across the run.&lt;/p&gt;

&lt;p&gt;Now imagine that 6,000 of those tokens were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Old tool outputs&lt;/li&gt;
&lt;li&gt;Repeated instructions&lt;/li&gt;
&lt;li&gt;Irrelevant history&lt;/li&gt;
&lt;li&gt;Duplicate documents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may have spent tokens carrying information the model didn't need.&lt;/p&gt;

&lt;p&gt;This is why optimizing an agent requires looking at the &lt;strong&gt;whole execution&lt;/strong&gt;, not just one prompt.&lt;/p&gt;

&lt;p&gt;Recent work on context optimization explicitly treats long-running agents as a lifecycle problem involving accumulated histories, tool outputs, retrieval and repeated model calls.&lt;/p&gt;




&lt;h1&gt;
  
  
  📊 Think in Terms of a Context Budget
&lt;/h1&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How much context can my model handle?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How much context should I spend on this task?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Context Budget: 20,000 tokens

System Instructions      2,000
Tool Definitions         3,000
Conversation             2,000
Retrieved Documents      5,000
Agent State              2,000
Current Request          1,000
Safety / Constraints     1,000
--------------------------------
Total                   16,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You still have some room.&lt;/p&gt;

&lt;p&gt;But if retrieval suddenly returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15,000 tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you have a problem.&lt;/p&gt;

&lt;p&gt;A context budget makes that visible.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧹 What Should We Remove First?
&lt;/h1&gt;

&lt;p&gt;When context becomes too large, don't immediately summarize everything.&lt;/p&gt;

&lt;p&gt;Use a hierarchy.&lt;/p&gt;

&lt;h3&gt;
  
  
  First: Remove unnecessary information
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Irrelevant tool output
Old duplicate results
Unrelated documents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Then: Reduce verbose outputs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000-line log
        ↓
Relevant error lines
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Then: Retrieve only what matters
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100 documents
        ↓
Top relevant documents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Then: Compress history
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;50 conversation turns
        ↓
Task state + important decisions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finally: Consider architectural changes
&lt;/h3&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate agent contexts&lt;/li&gt;
&lt;li&gt;Store large artifacts externally&lt;/li&gt;
&lt;li&gt;Retrieve information on demand&lt;/li&gt;
&lt;li&gt;Split complex tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach avoids using expensive compression when simple filtering would have solved the problem.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧰 Keep Large Artifacts Outside the Context
&lt;/h1&gt;

&lt;p&gt;This is particularly important for coding agents and document-heavy systems.&lt;/p&gt;

&lt;p&gt;Suppose a tool generates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;50,000 lines of logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't necessarily place all 50,000 lines into the next model request.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool
 ↓
Large Artifact
 ↓
External Storage
 ↓
Relevant Extract
 ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model can receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Application crashed at 14:32:08.
Relevant stack trace:
..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while the complete artifact remains available for retrieval if needed.&lt;/p&gt;

&lt;p&gt;This pattern is especially useful when dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Large files&lt;/li&gt;
&lt;li&gt;Database exports&lt;/li&gt;
&lt;li&gt;Build artifacts&lt;/li&gt;
&lt;li&gt;Test reports&lt;/li&gt;
&lt;li&gt;Large API responses&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧠 Context Engineering Is a Selection Problem
&lt;/h1&gt;

&lt;p&gt;At this point, we can define the problem more precisely.&lt;/p&gt;

&lt;p&gt;Every model call has a potential information pool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 ALL AVAILABLE INFORMATION
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
       Memory             RAG             Tools
          │                │                │
          └────────────────┼────────────────┘
                           ▼
                     SELECT / RANK
                           │
                           ▼
                       COMPRESS
                           │
                           ▼
                    CONTEXT BUDGET
                           │
                           ▼
                          LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM doesn't need everything your system knows.&lt;/p&gt;

&lt;p&gt;It needs the &lt;strong&gt;right working set for the current decision&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's perhaps the most important idea in this entire series.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧪 But How Do You Know Your Context Strategy Is Working?
&lt;/h1&gt;

&lt;p&gt;This is where many AI projects stop too early.&lt;/p&gt;

&lt;p&gt;They measure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Did the model produce a good answer?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that's not enough.&lt;/p&gt;

&lt;p&gt;You should also ask:&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Did we retrieve the right documents?&lt;/li&gt;
&lt;li&gt;How often are irrelevant documents included?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How large is the context?&lt;/li&gt;
&lt;li&gt;Which components consume most tokens?&lt;/li&gt;
&lt;li&gt;How often are contexts compressed?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Agent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How many steps does a task require?&lt;/li&gt;
&lt;li&gt;How often does the agent repeat a tool call?&lt;/li&gt;
&lt;li&gt;How often does it need to recover from an error?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cost
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Input tokens per request&lt;/li&gt;
&lt;li&gt;Output tokens&lt;/li&gt;
&lt;li&gt;Tokens per successful task&lt;/li&gt;
&lt;li&gt;Cache utilization where applicable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quality
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Task success rate&lt;/li&gt;
&lt;li&gt;Incorrect answers&lt;/li&gt;
&lt;li&gt;Missing information&lt;/li&gt;
&lt;li&gt;Failures after compression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A context optimization that saves 50% of tokens but causes 20% more task failures isn't necessarily an optimization.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚖️ Optimize for Cost &lt;strong&gt;and&lt;/strong&gt; Quality
&lt;/h1&gt;

&lt;p&gt;This is an important mindset.&lt;/p&gt;

&lt;p&gt;Don't optimize:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tokens ↓↓↓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;at any cost.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             Quality
                ▲
                │
                │      ●
                │   ●
                │ ●
                └────────────────►
                     Cost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is to find a useful balance between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accuracy&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;Context size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes sending more context is absolutely worth it.&lt;/p&gt;

&lt;p&gt;Sometimes it isn't.&lt;/p&gt;

&lt;p&gt;Context Engineering is about making that decision intentionally.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚨 Common Context Engineering Mistakes
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ❌ 1. "Let's send everything"
&lt;/h2&gt;

&lt;p&gt;More context isn't automatically better.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ 2. "Let's summarize everything"
&lt;/h2&gt;

&lt;p&gt;Compression can remove information that becomes important later.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ 3. "The model has a huge context window, so we're fine"
&lt;/h2&gt;

&lt;p&gt;A large context window is a capability—not a reason to fill it unnecessarily.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ 4. "RAG will solve it"
&lt;/h2&gt;

&lt;p&gt;Poor retrieval produces poor context.&lt;/p&gt;

&lt;p&gt;RAG doesn't magically make irrelevant documents relevant.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ 5. "Just truncate the oldest messages"
&lt;/h2&gt;

&lt;p&gt;The oldest information isn't necessarily the least important.&lt;/p&gt;

&lt;p&gt;A previous decision or constraint may still matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ 6. "We'll optimize tokens later"
&lt;/h2&gt;

&lt;p&gt;Context architecture can affect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Retrieval&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Agent behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It becomes increasingly difficult to retrofit once the application grows.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗️ A Practical Context Pipeline
&lt;/h1&gt;

&lt;p&gt;Putting everything together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         USER REQUEST
                              │
                              ▼
                    ┌──────────────────┐
                    │ Understand Task  │
                    └────────┬─────────┘
                             │
            ┌────────────────┼────────────────┐
            ▼                ▼                ▼
         Memory             RAG             Tools
            │                │                │
            └────────────────┼────────────────┘
                             ▼
                       SELECT RELEVANT
                             │
                             ▼
                       REMOVE NOISE
                             │
                             ▼
                      COMPRESS IF NEEDED
                             │
                             ▼
                       CONTEXT BUDGET
                             │
                             ▼
                            LLM
                             │
                             ▼
                       Evaluate Result
                             │
                    ┌────────┴────────┐
                    │                 │
                 Continue            Done
                    │
                    ▼
              Next Agent Step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the mental model I'd keep.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 A Simple Production Checklist
&lt;/h1&gt;

&lt;p&gt;Before shipping an AI feature, ask:&lt;/p&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] What information does the model actually need?&lt;/li&gt;
&lt;li&gt;[ ] Which information is unnecessary?&lt;/li&gt;
&lt;li&gt;[ ] What is retrieved dynamically?&lt;/li&gt;
&lt;li&gt;[ ] What is persistent memory?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tokens
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Do we have a context budget?&lt;/li&gt;
&lt;li&gt;[ ] Are large tool outputs filtered?&lt;/li&gt;
&lt;li&gt;[ ] Are duplicate documents removed?&lt;/li&gt;
&lt;li&gt;[ ] Are long histories compressed when appropriate?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Agents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] What is the maximum number of steps?&lt;/li&gt;
&lt;li&gt;[ ] What happens when a tool fails?&lt;/li&gt;
&lt;li&gt;[ ] What happens when the model chooses the wrong tool?&lt;/li&gt;
&lt;li&gt;[ ] Can the agent loop indefinitely?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cost &amp;amp; Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Are repeated stable inputs cacheable?&lt;/li&gt;
&lt;li&gt;[ ] Are large artifacts kept outside the context?&lt;/li&gt;
&lt;li&gt;[ ] Are we measuring tokens per successful task?&lt;/li&gt;
&lt;li&gt;[ ] Are we measuring latency?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quality
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Does compression preserve important constraints?&lt;/li&gt;
&lt;li&gt;[ ] Are retrieved documents relevant?&lt;/li&gt;
&lt;li&gt;[ ] Are tool results trustworthy and validated?&lt;/li&gt;
&lt;li&gt;[ ] Do we have evaluations for context-related failures?&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧠 The Bigger Picture
&lt;/h1&gt;

&lt;p&gt;Let's step back.&lt;/p&gt;

&lt;p&gt;When we started this series, Context Engineering sounded like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Writing better context for an LLM."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After five parts, we can see that it's much broader.&lt;/p&gt;

&lt;p&gt;A production AI system may need to decide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What should the model see?

        ↓

What should it retrieve?

        ↓

What should it remember?

        ↓

What should it forget?

        ↓

What should be compressed?

        ↓

What should be cached?

        ↓

What should be fetched only when needed?

        ↓

What should the model act on?

        ↓

What should never enter the context?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a very different problem from simply writing a better prompt.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 The Five-Part Mental Model
&lt;/h1&gt;

&lt;p&gt;Let's bring the entire series together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 1 — Context Engineering
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Give the model the right information.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2 — Tokens, Context &amp;amp; Memory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Understand the constraints around that information.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 3 — RAG, Tools &amp;amp; MCP
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Retrieve information and connect the model to external capabilities.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 4 — AI Agents
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Let the system use that context and tools across multiple steps.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 5 — Context Optimization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Continuously decide what information should enter, stay, change or leave the context.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that gives us the bigger picture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   USER
                     │
                     ▼
               ┌──────────┐
               │   GOAL   │
               └────┬─────┘
                    │
                    ▼
            ┌───────────────┐
            │ Context Layer │
            │               │
            │ Memory        │
            │ Retrieval     │
            │ Tools         │
            │ History       │
            └───────┬───────┘
                    │
                    ▼
              Select / Rank
                    │
                    ▼
               Compress
                    │
                    ▼
              Context Budget
                    │
                    ▼
                   LLM
                    │
                    ▼
                  Agent
                    │
              ┌─────┴─────┐
              ▼           ▼
           Tool          Done
              │
              ▼
          New Context
              │
              └──────────►
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that loop can continue for as long as the task requires.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏁 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;One of the biggest shifts happening in AI engineering is that we're moving away from thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How do I write the perfect prompt?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and toward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How do I build the right information environment for the model at every step?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's Context Engineering.&lt;/p&gt;

&lt;p&gt;The model matters.&lt;/p&gt;

&lt;p&gt;The prompt matters.&lt;/p&gt;

&lt;p&gt;But so do:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;retrieval, memory, tools, context selection, compression, caching, state, evaluation and orchestration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And as AI systems become more agentic, this problem becomes even more important.&lt;/p&gt;

&lt;p&gt;Because the question isn't simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How much can the model see?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What should the model see right now?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the engineering problem.&lt;/p&gt;




&lt;h1&gt;
  
  
  📌 Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;More context isn't automatically better context.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Treat the context window as a resource that needs to be managed.&lt;/li&gt;
&lt;li&gt;Remove irrelevant information before trying to compress it.&lt;/li&gt;
&lt;li&gt;Retrieve information when it's needed instead of loading everything upfront.&lt;/li&gt;
&lt;li&gt;Compress long histories carefully and preserve important decisions, constraints and state.&lt;/li&gt;
&lt;li&gt;Keep large artifacts outside the context when possible and retrieve only the relevant portions.&lt;/li&gt;
&lt;li&gt;Don't confuse &lt;strong&gt;context, memory and caching&lt;/strong&gt;—they solve different problems.&lt;/li&gt;
&lt;li&gt;Set practical token budgets for agent runs.&lt;/li&gt;
&lt;li&gt;Measure &lt;strong&gt;task success&lt;/strong&gt;, not just token reduction.&lt;/li&gt;
&lt;li&gt;Context optimization is a trade-off between &lt;strong&gt;quality, cost, latency and reliability&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The goal isn't to give the model everything.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The goal is to give the model what it needs for the decision it has to make right now.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>🤖 AI Context Engineering (Part 4): AI Agents - From Tool Calling to Multi-Step Workflows</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sat, 08 Aug 2026 07:22:18 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/ai-context-engineering-part-4-ai-agents-from-tool-calling-to-multi-step-workflows-28mo</link>
      <guid>https://dev.to/fazal_mansuri_/ai-context-engineering-part-4-ai-agents-from-tool-calling-to-multi-step-workflows-28mo</guid>
      <description>&lt;p&gt;In &lt;strong&gt;Part 1&lt;/strong&gt;, we explored why modern AI systems need more than carefully written prompts.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 2&lt;/strong&gt;, we looked at &lt;strong&gt;tokens, context windows and memory&lt;/strong&gt; and why simply adding more context doesn't necessarily produce better results.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 3&lt;/strong&gt;, we went one step further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RAG&lt;/strong&gt; helps retrieve relevant information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Calling&lt;/strong&gt; lets an AI application interact with external systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; provides a standardized way for AI applications to interact with tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there's one important question left:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who decides what should happen next?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose a user asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Find the latest failed deployment,
identify the root cause,
create a GitHub issue,
and notify the team on Slack.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's no longer a single API call.&lt;/p&gt;

&lt;p&gt;The system may need to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Find the deployment
2. Retrieve its logs
3. Analyze the failure
4. Decide whether there is enough evidence
5. Create a GitHub issue
6. Send a Slack notification
7. Verify that everything succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something has to coordinate these steps.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;AI agents&lt;/strong&gt; come in.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 First: What Actually Makes Something an AI Agent?
&lt;/h1&gt;

&lt;p&gt;The word &lt;strong&gt;agent&lt;/strong&gt; is used very loosely today.&lt;/p&gt;

&lt;p&gt;Almost every application with an LLM is sometimes called an "AI agent."&lt;/p&gt;

&lt;p&gt;That's not particularly useful.&lt;/p&gt;

&lt;p&gt;A simple chatbot that answers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What's the capital of France?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;isn't necessarily an agent.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Summarize this document.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;doesn't automatically make an application agentic.&lt;/p&gt;

&lt;p&gt;A useful way to think about an agent is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;An AI agent is a system where an LLM participates in deciding and executing the steps required to accomplish a goal, often using tools and continuing until a defined completion condition is reached.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important part is &lt;strong&gt;workflow execution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input → LLM → Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we have something closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Goal
 ↓
LLM decides next step
 ↓
Tool / Action
 ↓
Result
 ↓
LLM evaluates result
 ↓
Next step
 ↓
...
 ↓
Final result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This iterative loop is one of the core patterns behind agentic systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 The Agent Loop
&lt;/h1&gt;

&lt;p&gt;Let's take a simple example.&lt;/p&gt;

&lt;p&gt;The user says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Find the latest deployment failure and create a GitHub issue for it."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A possible agent execution could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    User Goal
                       │
                       ▼
                 ┌───────────┐
                 │    LLM    │
                 └─────┬─────┘
                       │
                Choose next action
                       │
                       ▼
                Deployment Tool
                       │
                       ▼
                Tool Result
                       │
                       ▼
                 ┌───────────┐
                 │    LLM    │
                 └─────┬─────┘
                       │
                 Analyze result
                       │
                       ▼
                 GitHub Tool
                       │
                       ▼
                 Tool Result
                       │
                       ▼
                 ┌───────────┐
                 │    LLM    │
                 └─────┬─────┘
                       │
                       ▼
                 Final Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what's different.&lt;/p&gt;

&lt;p&gt;The application doesn't necessarily hard-code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1 → Step 2 → Step 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, the model can participate in deciding which available action should happen next.&lt;/p&gt;

&lt;p&gt;That's the important shift.&lt;/p&gt;




&lt;h1&gt;
  
  
  🆚 Workflow vs Agent
&lt;/h1&gt;

&lt;p&gt;This distinction is extremely important.&lt;/p&gt;

&lt;p&gt;Imagine you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1 → Fetch Order
Step 2 → Validate Payment
Step 3 → Generate Invoice
Step 4 → Send Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sequence is always the same.&lt;/p&gt;

&lt;p&gt;You probably don't need an agent.&lt;/p&gt;

&lt;p&gt;A normal deterministic workflow is simpler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Fetch Order
 ↓
Validate Payment
 ↓
Generate Invoice
 ↓
Send Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Investigate why this customer's order failed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't necessarily know beforehand what steps are required.&lt;/p&gt;

&lt;p&gt;The system might need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look up the order&lt;/li&gt;
&lt;li&gt;Check payment status&lt;/li&gt;
&lt;li&gt;Inspect inventory&lt;/li&gt;
&lt;li&gt;Search support tickets&lt;/li&gt;
&lt;li&gt;Check logs&lt;/li&gt;
&lt;li&gt;Compare previous attempts&lt;/li&gt;
&lt;li&gt;Decide whether another investigation is necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The path depends on what the system discovers.&lt;/p&gt;

&lt;p&gt;That's a much better candidate for an agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  A useful rule:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If the workflow is predictable, prefer deterministic code. If the workflow requires dynamic decisions over multiple steps, an agent may be useful.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even current agent guidance recommends starting with simpler deterministic approaches where they are sufficient rather than introducing unnecessary autonomy.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 An Agent Is Not "Just an LLM"
&lt;/h1&gt;

&lt;p&gt;A production agent normally consists of several pieces.&lt;/p&gt;

&lt;p&gt;At a high level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             ┌───────────────────┐
             │       Agent       │
             │                   │
             │   Instructions    │
             │        +          │
             │       LLM         │
             └─────────┬─────────┘
                       │
          ┌────────────┼────────────┐
          ▼            ▼            ▼
       Memory         RAG         Tools
          │            │            │
          ▼            ▼            ▼
       State        Knowledge    Actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is only one component.&lt;/p&gt;

&lt;p&gt;The surrounding system provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instructions&lt;/li&gt;
&lt;li&gt;Tools&lt;/li&gt;
&lt;li&gt;Context&lt;/li&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Guardrails&lt;/li&gt;
&lt;li&gt;Execution limits&lt;/li&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly where &lt;strong&gt;Context Engineering&lt;/strong&gt; becomes especially important.&lt;/p&gt;




&lt;h1&gt;
  
  
  📦 The Agent's Context Keeps Changing
&lt;/h1&gt;

&lt;p&gt;Here's an important connection to Parts 1–3.&lt;/p&gt;

&lt;p&gt;In a simple LLM request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Prompt
 ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the context is relatively straightforward.&lt;/p&gt;

&lt;p&gt;But an agent might execute several actions.&lt;/p&gt;

&lt;p&gt;After the first tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User request
+
Tool result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the second:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User request
+
Tool result 1
+
Tool result 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the third:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User request
+
Tool result 1
+
Tool result 2
+
Tool result 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;If you keep everything forever, the context can become unnecessarily large.&lt;/p&gt;

&lt;p&gt;Remember Part 2:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;More context ≠ better context.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An agent therefore needs to manage context carefully.&lt;/p&gt;

&lt;p&gt;It may need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep important state&lt;/li&gt;
&lt;li&gt;Remove irrelevant tool output&lt;/li&gt;
&lt;li&gt;Summarize previous steps&lt;/li&gt;
&lt;li&gt;Retrieve information again when necessary&lt;/li&gt;
&lt;li&gt;Preserve the user's original goal&lt;/li&gt;
&lt;li&gt;Track what has already been completed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one reason &lt;strong&gt;agent engineering and context engineering are deeply connected&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔧 Tools Give Agents Their Hands
&lt;/h1&gt;

&lt;p&gt;We discussed Tool Calling in Part 3.&lt;/p&gt;

&lt;p&gt;Now look at it from the agent's perspective.&lt;/p&gt;

&lt;p&gt;A tool might expose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_order(order_id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_payment_status(order_id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create_github_issue(title, body)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;send_slack_message(channel, message)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent can decide which tool is useful for the current step.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Goal
   │
   ▼
  Agent
   │
   ├── get_order()
   │
   ├── get_payment_status()
   │
   ├── create_github_issue()
   │
   └── send_slack_message()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there's an important engineering principle here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Giving an agent a tool does not mean the agent should always be allowed to use it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A tool that reads data is very different from a tool that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;delete_database()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transfer_money()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;send_email()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where guardrails become critical.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛑 Agents Need Boundaries
&lt;/h1&gt;

&lt;p&gt;Autonomy sounds exciting until the system makes the wrong decision.&lt;/p&gt;

&lt;p&gt;Imagine an agent has this tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;delete_customer()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model interprets a user's request incorrectly.&lt;/p&gt;

&lt;p&gt;Without safeguards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
LLM
 ↓
delete_customer()
 ↓
💥
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production system should instead introduce controls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Agent
 ↓
Tool Request
 ↓
Permission Check
 ↓
Validation
 ↓
Human Approval? ── Yes ──→ Human
 ↓ No
Execute Tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the action, you might require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;Input validation&lt;/li&gt;
&lt;li&gt;Business-rule validation&lt;/li&gt;
&lt;li&gt;Rate limits&lt;/li&gt;
&lt;li&gt;Human approval&lt;/li&gt;
&lt;li&gt;Audit logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more consequential the action, the stronger the controls should be.&lt;/p&gt;

&lt;p&gt;Agent systems therefore aren't just an AI problem.&lt;/p&gt;

&lt;p&gt;They're also a &lt;strong&gt;systems engineering and security problem&lt;/strong&gt;. Current agent guidance explicitly treats guardrails and controlled tool access as important parts of agent design.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔁 What About ReAct?
&lt;/h1&gt;

&lt;p&gt;You may have heard the term &lt;strong&gt;ReAct&lt;/strong&gt; while reading about AI agents.&lt;/p&gt;

&lt;p&gt;ReAct stands for:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reason + Act&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The research introduced a pattern where a model alternates between reasoning about a task and taking actions through tools, using the resulting observations to continue the task.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Question
   ↓
Reason
   ↓
Action
   ↓
Observation
   ↓
Reason
   ↓
Action
   ↓
Observation
   ↓
Final Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
"Why did deployment #482 fail?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent might need to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;→ Get deployment #482
→ Inspect failure details
→ Retrieve relevant logs
→ Analyze the error
→ Decide whether more information is needed
→ Produce an explanation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important lesson isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Every agent must use ReAct."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It shouldn't be treated that way.&lt;/p&gt;

&lt;p&gt;ReAct is one influential approach to combining reasoning and action. Modern agent systems can use different orchestration strategies depending on the problem.&lt;/p&gt;




&lt;h1&gt;
  
  
  👨‍💻 What Does an Agent Loop Look Like in Go?
&lt;/h1&gt;

&lt;p&gt;You don't need an AI framework to understand the underlying architecture.&lt;/p&gt;

&lt;p&gt;At its core, an agent can be thought of as a loop.&lt;/p&gt;

&lt;p&gt;Here's a simplified orchestration skeleton:&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;ToolResult&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;Name&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="kt"&gt;string&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;AgentDecision&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;ToolName&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Input&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Done&lt;/span&gt;     &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Answer&lt;/span&gt;   &lt;span class="kt"&gt;string&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;runAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&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;goal&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;ToolResult&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&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;step&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;decision&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;askModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&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="k"&gt;return&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="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&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;decision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Answer&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="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToolName&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;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unknown tool: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToolName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;result&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;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Input&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="k"&gt;return&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="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ToolResult&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="n"&gt;decision&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToolName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&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="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"agent exceeded maximum steps"&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 important part isn't the exact implementation.&lt;/p&gt;

&lt;p&gt;It's the architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        ┌───────────────┐
        │   Ask Model   │
        └───────┬───────┘
                │
                ▼
        Tool needed?
          /       \
        Yes        No
         │          │
         ▼          ▼
     Execute      Finish
       Tool
         │
         ▼
    Tool Result
         │
         └──────────────┐
                        │
                        ▼
                   Ask Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Notice the safety mechanism:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&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;step&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not just an implementation detail.&lt;/p&gt;

&lt;p&gt;It's an &lt;strong&gt;execution boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without a maximum number of steps, a poorly behaving agent could continue looping indefinitely.&lt;/p&gt;

&lt;p&gt;Real systems need explicit termination conditions and failure handling. Agent orchestration commonly uses limits such as maximum turns, successful final output, tool completion or errors to stop execution.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ Why "Fully Autonomous" Isn't Always Better
&lt;/h1&gt;

&lt;p&gt;There's a tendency to think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;More autonomy
     =
Better agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Imagine two systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  System A
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent
 ↓
20 tools
 ↓
Unlimited steps
 ↓
No approval
 ↓
No validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sounds powerful.&lt;/p&gt;

&lt;p&gt;It is also difficult to predict, debug, secure and operate.&lt;/p&gt;

&lt;h3&gt;
  
  
  System B
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent
 ↓
5 well-defined tools
 ↓
Maximum 8 steps
 ↓
Permission checks
 ↓
Human approval for risky actions
 ↓
Full tracing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;System B may be much more useful in production.&lt;/p&gt;

&lt;p&gt;The goal isn't maximum autonomy.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Enough autonomy to solve the problem while keeping behavior observable, bounded and controllable.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  🧠 Single Agent vs Multi-Agent
&lt;/h1&gt;

&lt;p&gt;Once developers understand agents, another idea quickly appears:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why not create multiple agents?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Manager Agent
                 /     |     \
                /      |      \
               ▼       ▼       ▼
          Research   Coding   Testing
            Agent     Agent    Agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be useful for genuinely different responsibilities.&lt;/p&gt;

&lt;p&gt;But it also introduces additional complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More model calls&lt;/li&gt;
&lt;li&gt;More context passing&lt;/li&gt;
&lt;li&gt;More failure points&lt;/li&gt;
&lt;li&gt;More latency&lt;/li&gt;
&lt;li&gt;More difficult debugging&lt;/li&gt;
&lt;li&gt;More coordination logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need multiple agents just because you can build them.&lt;/p&gt;

&lt;p&gt;A single agent with good tools can often handle many workflows.&lt;/p&gt;

&lt;p&gt;A sensible progression is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deterministic Workflow
        ↓
Single Agent
        ↓
Multiple Specialized Agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move to the next level only when the problem actually requires it. Current agent design guidance similarly recommends starting incrementally rather than immediately building complex multi-agent architectures.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔍 The Part Developers Often Miss: Observability
&lt;/h1&gt;

&lt;p&gt;Here's where agent systems become very different from normal APIs.&lt;/p&gt;

&lt;p&gt;Imagine your API returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;500 Internal Server Error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You inspect logs.&lt;/p&gt;

&lt;p&gt;Fine.&lt;/p&gt;

&lt;p&gt;But an agent might fail because:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
    ↓
Tool A
    ↓
Tool B
    ↓
Wrong tool selected
    ↓
Bad result
    ↓
Agent makes another decision
    ↓
Final answer is incorrect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final output alone doesn't tell you what happened.&lt;/p&gt;

&lt;p&gt;You need visibility into the execution trace.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run ID: 8f21

Step 1
Tool: search_deployments
Input: production
Result: deployment #482

Step 2
Tool: get_logs
Input: #482
Result: database connection timeout

Step 3
Tool: search_docs
Input: database connection timeout
Result: connection pool documentation

Step 4
Decision: create GitHub issue

Step 5
Tool: create_issue
Result: issue #921
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes agent behavior much easier to debug.&lt;/p&gt;

&lt;p&gt;Observability and tracing are now treated as important parts of production agent development because the system's behavior spans multiple model and tool steps.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 The Complete Picture
&lt;/h1&gt;

&lt;p&gt;Now let's connect everything from Parts 1–4.&lt;/p&gt;

&lt;p&gt;A modern AI application might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         USER
                           │
                           ▼
                  ┌─────────────────┐
                  │  AI Application │
                  └────────┬────────┘
                           │
                           ▼
                    ┌─────────────┐
                    │    AGENT    │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
             RAG         Tools        Memory
              │            │            │
              └────────────┼────────────┘
                           ▼
                    Context Builder
                           │
                           ▼
                          LLM
                           │
                           ▼
                    Next Decision
                           │
                           └──────→ Tool / RAG
                                      │
                                      └──→ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where the entire series starts to come together.&lt;/p&gt;




&lt;h1&gt;
  
  
  📌 The Mental Model
&lt;/h1&gt;

&lt;p&gt;If you remember only four things from this article, remember this:&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 1 - Context Engineering
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Give the model the right information for the task.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Part 2 - Context Management
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't confuse more context with better context.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Part 3 - RAG + Tools + MCP
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Retrieve knowledge and give the system controlled access to external capabilities.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Part 4 - Agents
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Let the system decide and execute multiple steps toward a goal-within defined boundaries.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the progression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prompt
  ↓
Context
  ↓
Context + Tools
  ↓
Context + Tools + Decisions
  ↓
Agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚨 When Should You NOT Build an Agent?
&lt;/h1&gt;

&lt;p&gt;This might be the most important advice in the entire article.&lt;/p&gt;

&lt;p&gt;If your workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Receive Request
     ↓
Validate
     ↓
Insert Database Row
     ↓
Return Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't build an agent.&lt;/p&gt;

&lt;p&gt;Use normal application code.&lt;/p&gt;

&lt;p&gt;If your workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Understand user's goal
     ↓
Find relevant information
     ↓
Choose among several tools
     ↓
Inspect results
     ↓
Decide what to do next
     ↓
Possibly perform more actions
     ↓
Stop when the goal is satisfied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent may make sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use agents where dynamic decision-making provides real value-not simply because agents are trending.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;An AI agent is more than an LLM wrapped in a chatbot.&lt;/li&gt;
&lt;li&gt;Agents use models to participate in multi-step workflow execution.&lt;/li&gt;
&lt;li&gt;Tools allow agents to retrieve information or take actions.&lt;/li&gt;
&lt;li&gt;An agent typically operates through an iterative loop: &lt;strong&gt;decide → act → observe → decide again&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;RAG provides knowledge; tools provide capabilities.&lt;/li&gt;
&lt;li&gt;Context changes as an agent executes more steps, making context management especially important.&lt;/li&gt;
&lt;li&gt;Not every workflow needs an agent. Deterministic workflows are often simpler and more predictable.&lt;/li&gt;
&lt;li&gt;Agents should have explicit boundaries such as step limits, permissions, validation and approval for sensitive actions.&lt;/li&gt;
&lt;li&gt;Observability is critical because the final answer doesn't tell you everything that happened during an agent run.&lt;/li&gt;
&lt;li&gt;Multi-agent systems can be useful, but they also introduce additional complexity and should not be the default.&lt;/li&gt;
&lt;li&gt;The goal isn't maximum autonomy. It's &lt;strong&gt;useful autonomy with control&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🚀 What's Next?
&lt;/h1&gt;

&lt;p&gt;We've now built the foundation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 1:&lt;/strong&gt; What is Context Engineering?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2:&lt;/strong&gt; Tokens, Context Windows &amp;amp; Memory&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 3:&lt;/strong&gt; RAG, Tool Calling &amp;amp; MCP&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 4:&lt;/strong&gt; AI Agents &amp;amp; Multi-Step Workflows&lt;/p&gt;

&lt;p&gt;But there's a problem.&lt;/p&gt;

&lt;p&gt;An agent can have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thousands of documents&lt;/li&gt;
&lt;li&gt;Dozens of tools&lt;/li&gt;
&lt;li&gt;Long conversation history&lt;/li&gt;
&lt;li&gt;Multiple tool results&lt;/li&gt;
&lt;li&gt;Previous execution state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if we keep putting everything into the context...&lt;/p&gt;

&lt;p&gt;💸 &lt;strong&gt;Token costs increase.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🐌 &lt;strong&gt;Latency increases.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Relevant information gets buried.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And eventually, simply giving the model &lt;em&gt;more&lt;/em&gt; context can make the system worse.&lt;/p&gt;

&lt;p&gt;So the next question becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How do we decide what context an AI actually needs-and what should be removed?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's where we go next.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;AI Context Engineering - Part 5: Context Optimization&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We'll look at practical techniques such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context compression&lt;/li&gt;
&lt;li&gt;Summarization&lt;/li&gt;
&lt;li&gt;Relevance ranking&lt;/li&gt;
&lt;li&gt;Context pruning&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Token optimization&lt;/li&gt;
&lt;li&gt;Context prioritization&lt;/li&gt;
&lt;li&gt;And how to reduce cost without sacrificing useful information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because in production AI systems:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The goal isn't to give the model everything.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is to give it exactly what it needs.&lt;/strong&gt; 🚀&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>🚀 AI Context Engineering (Part 3): How AI Actually Finds Information - RAG, Tool Calling &amp; MCP Explained</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sat, 25 Jul 2026 06:49:16 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/ai-context-engineering-part-3-how-ai-actually-finds-information-rag-tool-calling-mcp-4d77</link>
      <guid>https://dev.to/fazal_mansuri_/ai-context-engineering-part-3-how-ai-actually-finds-information-rag-tool-calling-mcp-4d77</guid>
      <description>&lt;p&gt;In &lt;strong&gt;Part 1&lt;/strong&gt;, we explored why modern AI systems need more than just good prompts.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 2&lt;/strong&gt;, we learned how &lt;strong&gt;tokens&lt;/strong&gt;, &lt;strong&gt;context windows&lt;/strong&gt;, and &lt;strong&gt;memory&lt;/strong&gt; shape the quality of an AI application's responses.&lt;/p&gt;

&lt;p&gt;By now, we know one important fact:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The quality of an AI system depends heavily on the quality of the context it receives.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that naturally raises another question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Where does all that context actually come from?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine asking an AI assistant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is our company's leave policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or perhaps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain this private function in our GitHub repository.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How many orders were placed today?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can an AI answer questions about information that &lt;strong&gt;was never part of its training data?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It wasn't trained on your company's HR handbook.&lt;/p&gt;

&lt;p&gt;It doesn't know your private GitHub repository.&lt;/p&gt;

&lt;p&gt;It certainly doesn't know how many orders your application processed five minutes ago.&lt;/p&gt;

&lt;p&gt;Yet modern AI applications answer these questions surprisingly well.&lt;/p&gt;

&lt;p&gt;How?&lt;/p&gt;

&lt;p&gt;Because today's AI applications do far more than simply send your prompt to a language model.&lt;/p&gt;

&lt;p&gt;They &lt;strong&gt;search&lt;/strong&gt;, &lt;strong&gt;retrieve&lt;/strong&gt;, &lt;strong&gt;call tools&lt;/strong&gt;, and &lt;strong&gt;assemble relevant information&lt;/strong&gt; before asking the model to generate a response.&lt;/p&gt;

&lt;p&gt;That's exactly what we'll explore in this article.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 The Biggest Misconception About AI
&lt;/h1&gt;

&lt;p&gt;Many people imagine AI applications working like this:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6h6pqpyot41fvk1w7e48.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6h6pqpyot41fvk1w7e48.png" alt=" " width="684" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It feels simple.&lt;/p&gt;

&lt;p&gt;Ask a question.&lt;/p&gt;

&lt;p&gt;Receive an answer.&lt;/p&gt;

&lt;p&gt;But modern AI systems are much more sophisticated.&lt;/p&gt;

&lt;p&gt;A more accurate picture looks like this:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqjta43rwgy4z2c0c06zj.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqjta43rwgy4z2c0c06zj.png" alt=" " width="800" height="732"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice something important.&lt;/p&gt;

&lt;p&gt;The LLM isn't doing everything.&lt;/p&gt;

&lt;p&gt;Instead, the application surrounding the LLM is responsible for gathering the right information before asking the model to generate a response.&lt;/p&gt;

&lt;p&gt;This is Context Engineering in practice.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Language Models Don't Know Everything
&lt;/h1&gt;

&lt;p&gt;Large Language Models are trained on enormous amounts of publicly available text.&lt;/p&gt;

&lt;p&gt;That training gives them remarkable reasoning and language capabilities.&lt;/p&gt;

&lt;p&gt;However, training has limits.&lt;/p&gt;

&lt;p&gt;A model typically &lt;strong&gt;cannot&lt;/strong&gt; know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your company's internal documentation&lt;/li&gt;
&lt;li&gt;Private GitHub repositories&lt;/li&gt;
&lt;li&gt;Customer databases&lt;/li&gt;
&lt;li&gt;Current inventory&lt;/li&gt;
&lt;li&gt;Live weather&lt;/li&gt;
&lt;li&gt;Today's stock prices&lt;/li&gt;
&lt;li&gt;This morning's support tickets&lt;/li&gt;
&lt;li&gt;The latest production deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if the information exists somewhere, it may have been created &lt;strong&gt;after&lt;/strong&gt; the model finished training.&lt;/p&gt;

&lt;p&gt;This distinction is important.&lt;/p&gt;

&lt;p&gt;The model isn't "searching the internet" every time you ask a question.&lt;/p&gt;

&lt;p&gt;Instead, the surrounding application decides whether additional information needs to be retrieved.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 Retrieval-Augmented Generation (RAG)
&lt;/h1&gt;

&lt;p&gt;One of the most common techniques for providing that information is called &lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;, commonly known as &lt;strong&gt;RAG&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The name sounds complicated.&lt;/p&gt;

&lt;p&gt;The idea isn't.&lt;/p&gt;

&lt;p&gt;Think about an open-book exam.&lt;/p&gt;

&lt;p&gt;During the exam, you're allowed to search the textbook.&lt;/p&gt;

&lt;p&gt;You don't memorize every page beforehand.&lt;/p&gt;

&lt;p&gt;Instead, you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the question.&lt;/li&gt;
&lt;li&gt;Find the relevant chapter.&lt;/li&gt;
&lt;li&gt;Read only those pages.&lt;/li&gt;
&lt;li&gt;Write the answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's exactly how RAG works.&lt;/p&gt;

&lt;p&gt;The language model doesn't memorize every document.&lt;/p&gt;

&lt;p&gt;Instead, the application retrieves relevant information first, then includes it as part of the context sent to the model.&lt;/p&gt;

&lt;p&gt;Conceptually:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffsolvjdvs6r47jav9yr9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffsolvjdvs6r47jav9yr9.png" alt=" " width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model hasn't learned anything new.&lt;/p&gt;

&lt;p&gt;It simply received better context.&lt;/p&gt;




&lt;h1&gt;
  
  
  RAG Does &lt;strong&gt;Not&lt;/strong&gt; Retrain the Model
&lt;/h1&gt;

&lt;p&gt;This is another common misconception.&lt;/p&gt;

&lt;p&gt;Sometimes people say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We added documents to our RAG system, so we trained the model."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not how RAG works.&lt;/p&gt;

&lt;p&gt;Training changes the model's parameters through a computationally intensive learning process.&lt;/p&gt;

&lt;p&gt;RAG doesn't modify the model at all.&lt;/p&gt;

&lt;p&gt;Instead, it changes &lt;strong&gt;the information available during inference&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of it this way.&lt;/p&gt;

&lt;p&gt;Training is like teaching someone a new language.&lt;/p&gt;

&lt;p&gt;RAG is like handing them the correct reference book before asking a question.&lt;/p&gt;

&lt;p&gt;The person's knowledge hasn't changed.&lt;/p&gt;

&lt;p&gt;They simply have access to additional information.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Practical Example
&lt;/h1&gt;

&lt;p&gt;Suppose your company has thousands of pages of internal documentation.&lt;/p&gt;

&lt;p&gt;A developer asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How do I deploy the billing service?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without RAG:&lt;/p&gt;

&lt;p&gt;The model can only rely on general knowledge.&lt;/p&gt;

&lt;p&gt;It might produce a reasonable deployment process - but not &lt;em&gt;your&lt;/em&gt; company's process.&lt;/p&gt;

&lt;p&gt;With RAG:&lt;/p&gt;

&lt;p&gt;The application first searches your documentation.&lt;/p&gt;

&lt;p&gt;Perhaps it retrieves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Billing deployment guide&lt;/li&gt;
&lt;li&gt;Kubernetes manifest&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Rollback procedure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only these relevant documents are attached to the request.&lt;/p&gt;

&lt;p&gt;The model now has enough context to generate an accurate answer.&lt;/p&gt;

&lt;p&gt;Notice something interesting.&lt;/p&gt;

&lt;p&gt;The user still asked the same question.&lt;/p&gt;

&lt;p&gt;The improvement came entirely from &lt;strong&gt;better context&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Good RAG Isn't About Retrieving More
&lt;/h1&gt;

&lt;p&gt;Many beginners assume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;More documents = Better answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually, the opposite is true.&lt;/p&gt;

&lt;p&gt;Imagine asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How do I reset my password?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would you rather provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The password reset documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every document in your company?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearly, the first option is better.&lt;/p&gt;

&lt;p&gt;The goal of RAG isn't to retrieve &lt;strong&gt;everything&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal is to retrieve &lt;strong&gt;only what matters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This connects directly to what we learned in Part 2.&lt;/p&gt;

&lt;p&gt;Remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;More context doesn't automatically produce better answers.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Retrieving unnecessary information wastes tokens, increases latency, and may distract the model from the information that actually matters.&lt;/p&gt;

&lt;p&gt;Good RAG systems focus on &lt;strong&gt;precision&lt;/strong&gt;, not volume.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Simple Go Example
&lt;/h1&gt;

&lt;p&gt;Imagine you have internal documentation stored in a database.&lt;/p&gt;

&lt;p&gt;Without RAG, your application might simply forward the user's question to the LLM:&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;prompt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"How do I deploy the billing service?"&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;callLLM&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model has no access to your documentation.&lt;/p&gt;

&lt;p&gt;Now imagine a simplified RAG workflow.&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;question&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"How do I deploy the billing service?"&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;searchKnowledgeBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`
Relevant Documentation:

%s

User Question:
%s
`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&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="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\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;question&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;callLLM&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something important.&lt;/p&gt;

&lt;p&gt;The model wasn't changed.&lt;/p&gt;

&lt;p&gt;The only difference is that your application retrieved relevant information &lt;strong&gt;before&lt;/strong&gt; sending the request.&lt;/p&gt;

&lt;p&gt;That's the essence of Retrieval-Augmented Generation.&lt;/p&gt;




&lt;h1&gt;
  
  
  How Does the Application Find the Right Documents?
&lt;/h1&gt;

&lt;p&gt;At this point, you might be wondering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How does the application know which documents are relevant?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's an excellent question.&lt;/p&gt;

&lt;p&gt;Modern RAG systems typically rely on &lt;strong&gt;embeddings&lt;/strong&gt; and &lt;strong&gt;vector search&lt;/strong&gt; to retrieve semantically similar documents rather than performing simple keyword matching.&lt;/p&gt;

&lt;p&gt;Those topics deserve their own deep dive because they involve concepts like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embedding models&lt;/li&gt;
&lt;li&gt;Vector databases&lt;/li&gt;
&lt;li&gt;Similarity search&lt;/li&gt;
&lt;li&gt;Chunking strategies&lt;/li&gt;
&lt;li&gt;Ranking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, it's enough to understand that the retrieval system attempts to find the most relevant pieces of information and passes only those into the context.&lt;/p&gt;

&lt;p&gt;The important takeaway is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The LLM isn't searching your documents directly. The application retrieves them first.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🤖 Retrieval Gives Knowledge. But What If the AI Needs to Take an Action?
&lt;/h1&gt;

&lt;p&gt;So far, we've looked at questions like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is our refund policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain this deployment guide.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are &lt;strong&gt;knowledge retrieval&lt;/strong&gt; problems.&lt;/p&gt;

&lt;p&gt;But now consider a different request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a new GitHub issue.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Send this report to Slack.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Book a meeting for tomorrow at 3 PM.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading documentation isn't enough anymore.&lt;/p&gt;

&lt;p&gt;The AI now needs to &lt;strong&gt;perform an action&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;How does that happen?&lt;/p&gt;

&lt;p&gt;Does the language model directly call APIs?&lt;/p&gt;

&lt;p&gt;Can it create GitHub issues on its own?&lt;/p&gt;

&lt;p&gt;Can it send Slack messages by itself?&lt;/p&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Tool Calling&lt;/strong&gt; enters the picture - and it's one of the most misunderstood concepts in modern AI systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔧 Tool Calling: Giving AI the Ability to Act
&lt;/h1&gt;

&lt;p&gt;So far, we've seen how RAG helps AI answer questions by retrieving relevant information.&lt;/p&gt;

&lt;p&gt;But sometimes answering a question isn't enough.&lt;/p&gt;

&lt;p&gt;Imagine asking an AI assistant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a GitHub issue titled "Fix login bug".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Send today's deployment report to Slack.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What's the current CPU usage of our production server?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These aren't knowledge problems anymore.&lt;/p&gt;

&lt;p&gt;They're &lt;strong&gt;action problems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The AI now needs to interact with external systems.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Tool Calling&lt;/strong&gt; comes into the picture.&lt;/p&gt;




&lt;h1&gt;
  
  
  🤔 Does the LLM Execute APIs?
&lt;/h1&gt;

&lt;p&gt;One of the biggest misconceptions is that language models directly execute code or call APIs.&lt;/p&gt;

&lt;p&gt;They don't.&lt;/p&gt;

&lt;p&gt;A Large Language Model generates text.&lt;/p&gt;

&lt;p&gt;That's its primary capability.&lt;/p&gt;

&lt;p&gt;When an application enables Tool Calling, the model can decide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"To answer this request correctly, I need to use a specific tool."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The application then executes that tool and returns the result to the model.&lt;/p&gt;

&lt;p&gt;The model never talks to GitHub, Slack, or your database directly.&lt;/p&gt;

&lt;p&gt;The application does.&lt;/p&gt;

&lt;p&gt;Think of it like this:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4uutxmkpxe1b30pe0vp.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4uutxmkpxe1b30pe0vp.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The LLM makes the decision.&lt;/p&gt;

&lt;p&gt;The application performs the action.&lt;/p&gt;

&lt;p&gt;This separation is important because it allows developers to validate permissions, handle authentication, retry failures, log requests, and control exactly what the model is allowed to do.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Simple Go Example
&lt;/h1&gt;

&lt;p&gt;Suppose your application exposes a tool for fetching the current weather.&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;WeatherTool&lt;/span&gt; &lt;span class="k"&gt;struct&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;WeatherTool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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="kt"&gt;error&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: 29°C, Clear Sky"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What's the weather in Ahmedabad?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application might work like this:&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;tool&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;WeatherTool&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;weather&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;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ahmedabad"&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;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`
Weather Information:

%s

Answer the user's question naturally.
`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weather&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;callLLM&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;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="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something important.&lt;/p&gt;

&lt;p&gt;The weather API wasn't called by the language model.&lt;/p&gt;

&lt;p&gt;It was called by your Go application.&lt;/p&gt;

&lt;p&gt;The model simply received the weather information as additional context before generating the response.&lt;/p&gt;

&lt;p&gt;Once again, Context Engineering is doing the heavy lifting.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 RAG Retrieves Knowledge. Tools Perform Actions.
&lt;/h1&gt;

&lt;p&gt;This distinction is worth remembering.&lt;/p&gt;

&lt;p&gt;Imagine asking these questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is our leave policy?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need documentation.&lt;/p&gt;

&lt;p&gt;RAG is the right choice.&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Approve leave request #1245.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the AI must interact with your HR system.&lt;/p&gt;

&lt;p&gt;A tool needs to execute that action.&lt;/p&gt;




&lt;p&gt;Another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain today's failed deployment.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrieve deployment logs.&lt;/p&gt;

&lt;p&gt;RAG.&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Restart the Kubernetes deployment.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute kubectl or a deployment API.&lt;/p&gt;

&lt;p&gt;Tool Calling.&lt;/p&gt;




&lt;p&gt;One retrieves information.&lt;/p&gt;

&lt;p&gt;The other performs work.&lt;/p&gt;

&lt;p&gt;Many production AI applications use both together.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 What Happens When You Have Hundreds of Tools?
&lt;/h1&gt;

&lt;p&gt;Now imagine your AI assistant can interact with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Jira&lt;/li&gt;
&lt;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Google Drive&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Filesystem&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;AWS&lt;/li&gt;
&lt;li&gt;Internal APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each system exposes its own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;API format&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;SDK&lt;/li&gt;
&lt;li&gt;Request structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without standardization, integrating each tool becomes increasingly complex.&lt;/p&gt;

&lt;p&gt;That's exactly the problem &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; was designed to solve.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌉 What Is MCP?
&lt;/h1&gt;

&lt;p&gt;Think of USB.&lt;/p&gt;

&lt;p&gt;Before USB existed:&lt;/p&gt;

&lt;p&gt;Every device required a different connector.&lt;/p&gt;

&lt;p&gt;Different cables.&lt;/p&gt;

&lt;p&gt;Different ports.&lt;/p&gt;

&lt;p&gt;Different drivers.&lt;/p&gt;

&lt;p&gt;USB introduced a common standard.&lt;/p&gt;

&lt;p&gt;Manufacturers still built different devices.&lt;/p&gt;

&lt;p&gt;But computers interacted with them in a consistent way.&lt;/p&gt;

&lt;p&gt;MCP plays a similar role for AI applications.&lt;/p&gt;

&lt;p&gt;Instead of every tool exposing a completely different interface, MCP defines a standard way for AI applications to discover and interact with tools.&lt;/p&gt;

&lt;p&gt;The protocol doesn't replace your APIs.&lt;/p&gt;

&lt;p&gt;It standardizes how AI systems communicate with them.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗️ A Simplified MCP Architecture
&lt;/h1&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcemhrd5u54btc112ehlw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcemhrd5u54btc112ehlw.png" alt=" " width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each MCP server exposes capabilities using the same protocol.&lt;/p&gt;

&lt;p&gt;The client no longer needs to understand dozens of different integrations individually.&lt;/p&gt;

&lt;p&gt;This makes adding new tools significantly easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  MCP Is Not a Replacement for APIs
&lt;/h1&gt;

&lt;p&gt;Another common misconception is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"MCP replaces REST APIs."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;REST APIs still exist.&lt;/p&gt;

&lt;p&gt;Databases still exist.&lt;/p&gt;

&lt;p&gt;GitHub APIs still exist.&lt;/p&gt;

&lt;p&gt;Slack APIs still exist.&lt;/p&gt;

&lt;p&gt;MCP simply provides a standardized interface that AI applications can use to interact with those systems more consistently.&lt;/p&gt;

&lt;p&gt;Think of MCP as a translator sitting between AI applications and external tools.&lt;/p&gt;




&lt;h1&gt;
  
  
  Putting It All Together
&lt;/h1&gt;

&lt;p&gt;Let's revisit our original question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a GitHub issue summarizing today's failed deployment.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what might happen behind the scenes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    User
                      │
                      ▼
            AI Application
                      │
      ┌───────────────┼────────────────┐
      ▼                                ▼
Retrieve Deployment Logs        GitHub Tool
      │                                │
      └───────────────┬────────────────┘
                      ▼
             Build Context
                      │
                      ▼
                    LLM
                      │
                      ▼
      "Create issue titled...
       Include deployment summary..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something interesting.&lt;/p&gt;

&lt;p&gt;This single request used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieval (deployment logs)&lt;/li&gt;
&lt;li&gt;Tool Calling (GitHub)&lt;/li&gt;
&lt;li&gt;Context Engineering (combining everything)&lt;/li&gt;
&lt;li&gt;The LLM (reasoning and language generation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern AI assistants rarely rely on only one technique.&lt;/p&gt;

&lt;p&gt;They're orchestration systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  RAG vs Tool Calling vs MCP
&lt;/h1&gt;

&lt;p&gt;These concepts are often confused because they frequently appear together.&lt;/p&gt;

&lt;p&gt;Here's an easy way to distinguish them.&lt;/p&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;RAG&lt;/th&gt;
&lt;th&gt;Tool Calling&lt;/th&gt;
&lt;th&gt;MCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary Goal&lt;/td&gt;
&lt;td&gt;Retrieve information&lt;/td&gt;
&lt;td&gt;Execute actions&lt;/td&gt;
&lt;td&gt;Standardize tool integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changes external state&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes (can)&lt;/td&gt;
&lt;td&gt;Depends on the tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reads knowledge&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Sometimes&lt;/td&gt;
&lt;td&gt;Depends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Calls external systems&lt;/td&gt;
&lt;td&gt;Indirectly&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Provides the interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical Example&lt;/td&gt;
&lt;td&gt;Company documentation&lt;/td&gt;
&lt;td&gt;GitHub, Slack, Database&lt;/td&gt;
&lt;td&gt;GitHub MCP Server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important point is that these technologies complement one another rather than compete.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 A Simple Mental Model
&lt;/h1&gt;

&lt;p&gt;Whenever you're unsure which concept applies, ask yourself one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What is the AI trying to do?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ Think &lt;strong&gt;RAG&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Perform an action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ Think &lt;strong&gt;Tool Calling&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Connect AI to many different tools consistently&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ Think &lt;strong&gt;MCP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This simple mental model eliminates much of the confusion surrounding these terms.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Production Best Practices
&lt;/h1&gt;

&lt;p&gt;If you're building AI-powered applications, keep these principles in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Retrieve only relevant information
&lt;/h3&gt;

&lt;p&gt;More documents don't automatically improve answers.&lt;/p&gt;

&lt;p&gt;High-quality retrieval almost always beats high-volume retrieval.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Keep retrieved context concise
&lt;/h3&gt;

&lt;p&gt;Every additional token increases cost and latency.&lt;/p&gt;

&lt;p&gt;Only include information that helps answer the current question.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Design tools to do one thing well
&lt;/h3&gt;

&lt;p&gt;Instead of creating one massive "do everything" tool, expose smaller, focused capabilities.&lt;/p&gt;

&lt;p&gt;They're easier for both developers and language models to use correctly.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Validate every tool invocation
&lt;/h3&gt;

&lt;p&gt;Never assume the model made the correct decision.&lt;/p&gt;

&lt;p&gt;Your application should validate permissions, inputs, authentication, and business rules before executing any action.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Treat tool outputs as untrusted input
&lt;/h3&gt;

&lt;p&gt;External systems can fail.&lt;/p&gt;

&lt;p&gt;APIs can return unexpected data.&lt;/p&gt;

&lt;p&gt;Always handle errors gracefully before sending results back to the model.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Monitor retrieval quality
&lt;/h3&gt;

&lt;p&gt;Poor RAG often isn't caused by the language model.&lt;/p&gt;

&lt;p&gt;It's caused by retrieving the wrong documents.&lt;/p&gt;

&lt;p&gt;Measure retrieval quality just as carefully as you evaluate model responses.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏁 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;When people first begin exploring AI, they often focus on the language model itself.&lt;/p&gt;

&lt;p&gt;But as you've seen throughout this series, the model is only one part of the system.&lt;/p&gt;

&lt;p&gt;The real intelligence often comes from the application surrounding it.&lt;/p&gt;

&lt;p&gt;That application decides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What information should be retrieved.&lt;/li&gt;
&lt;li&gt;Which tools should be available.&lt;/li&gt;
&lt;li&gt;How context is assembled.&lt;/li&gt;
&lt;li&gt;What actions are permitted.&lt;/li&gt;
&lt;li&gt;How responses are validated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why two applications built on the same underlying model can produce dramatically different results.&lt;/p&gt;

&lt;p&gt;The difference usually isn't the model.&lt;/p&gt;

&lt;p&gt;It's the quality of the surrounding engineering.&lt;/p&gt;

&lt;p&gt;And that's exactly what Context Engineering is all about.&lt;/p&gt;




&lt;h1&gt;
  
  
  📌 Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Large Language Models don't automatically know your private or real-time data.&lt;/li&gt;
&lt;li&gt;RAG improves responses by retrieving relevant information before sending the request to the model.&lt;/li&gt;
&lt;li&gt;RAG doesn't retrain or modify the model - it enriches the context during inference.&lt;/li&gt;
&lt;li&gt;Tool Calling enables AI applications to perform actions by letting the application execute external operations.&lt;/li&gt;
&lt;li&gt;The language model decides &lt;strong&gt;when&lt;/strong&gt; a tool is needed, but the application executes it.&lt;/li&gt;
&lt;li&gt;MCP provides a standardized way for AI applications to interact with many different tools.&lt;/li&gt;
&lt;li&gt;Effective AI systems combine retrieval, tool execution, and carefully constructed context to produce accurate and useful responses.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🚀 Coming Up in Part 4
&lt;/h1&gt;

&lt;p&gt;So far, we've explored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why prompts alone aren't enough.&lt;/li&gt;
&lt;li&gt;How tokens and context windows influence AI.&lt;/li&gt;
&lt;li&gt;How AI retrieves information and interacts with external tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But one fascinating question still remains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How does an AI decide what to do first?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a request requires searching documentation, querying a database, calling multiple APIs, verifying results, and finally generating a response…&lt;/p&gt;

&lt;p&gt;Who plans those steps?&lt;/p&gt;

&lt;p&gt;Who decides whether another tool should be used?&lt;/p&gt;

&lt;p&gt;Who determines that the answer needs to be checked before responding?&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;AI Agents&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 4&lt;/strong&gt;, we'll go beyond the buzzword and explore how modern AI agents think, plan, reason and orchestrate complex workflows - along with the patterns that power today's most capable AI systems.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>mcp</category>
      <category>rag</category>
    </item>
    <item>
      <title>📦 AI Context Engineering (Part 2): Tokens, Context Windows &amp; Memory - Why More Context Isn't Always Better</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sun, 05 Jul 2026 06:23:35 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/ai-context-engineering-part-2-tokens-context-windows-memory-why-more-context-isnt-always-453e</link>
      <guid>https://dev.to/fazal_mansuri_/ai-context-engineering-part-2-tokens-context-windows-memory-why-more-context-isnt-always-453e</guid>
      <description>&lt;p&gt;In &lt;strong&gt;Part 1&lt;/strong&gt;, we learned that building great AI applications isn't just about writing better prompts.&lt;/p&gt;

&lt;p&gt;It's about providing the &lt;strong&gt;right context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But that naturally leads to another question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How much context can an AI actually understand?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've used ChatGPT, Claude, Gemini, Cursor or any AI coding assistant for a while, you've probably experienced something like this.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 "Didn't I Already Tell You That?"
&lt;/h2&gt;

&lt;p&gt;Imagine you're debugging a production issue with an AI assistant.&lt;/p&gt;

&lt;p&gt;You start by explaining the architecture.&lt;/p&gt;

&lt;p&gt;Then you share the API flow.&lt;/p&gt;

&lt;p&gt;Then database schema.&lt;/p&gt;

&lt;p&gt;Then logs.&lt;/p&gt;

&lt;p&gt;Then stack traces.&lt;/p&gt;

&lt;p&gt;After 30 minutes of conversation, you ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"So what's causing the bug?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of giving the answer, the AI responds:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Could you share your database schema?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You stare at the screen.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"I already did..."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes it even forgets details from earlier in the same conversation.&lt;/p&gt;

&lt;p&gt;Naturally, people assume:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The AI has bad memory.&lt;/li&gt;
&lt;li&gt;The model is unreliable.&lt;/li&gt;
&lt;li&gt;The conversation is broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality, something completely different is happening.&lt;/p&gt;

&lt;p&gt;You're running into one of the most important concepts in modern AI systems:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Context Window.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Understanding this concept changes how you interact with AI—and more importantly, how you build AI-powered applications.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 Before We Talk About Context Windows…
&lt;/h1&gt;

&lt;p&gt;We first need to understand something much smaller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tokens.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Almost every AI provider mentions them.&lt;/p&gt;

&lt;p&gt;Pricing is based on them.&lt;/p&gt;

&lt;p&gt;Context windows are measured using them.&lt;/p&gt;

&lt;p&gt;Yet many developers still think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;1 token = 1 word&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That isn't true.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔤 What Exactly Is a Token?
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;token&lt;/strong&gt; is the basic unit of text that an AI model processes.&lt;/p&gt;

&lt;p&gt;Humans naturally read text as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Characters&lt;/li&gt;
&lt;li&gt;Words&lt;/li&gt;
&lt;li&gt;Sentences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Large Language Models don't.&lt;/p&gt;

&lt;p&gt;Before text reaches the model, it's converted into smaller pieces called &lt;strong&gt;tokens&lt;/strong&gt; by a tokenizer.&lt;/p&gt;

&lt;p&gt;The model never sees your original sentence.&lt;/p&gt;

&lt;p&gt;It only sees a sequence of tokens.&lt;/p&gt;

&lt;p&gt;Think of a tokenizer as a translator between humans and AI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You write English
        ↓
Tokenizer
        ↓
Sequence of Tokens
        ↓
LLM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tokenizer decides how text is split.&lt;/p&gt;

&lt;p&gt;And that's why &lt;strong&gt;tokens aren't the same as words&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  Tokens ≠ Words
&lt;/h1&gt;

&lt;p&gt;This is probably the biggest misconception about LLMs.&lt;/p&gt;

&lt;p&gt;Consider this sentence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 words = 2 tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes that's true.&lt;/p&gt;

&lt;p&gt;Sometimes it isn't.&lt;/p&gt;

&lt;p&gt;Now consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;internationalization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One word.&lt;/p&gt;

&lt;p&gt;But depending on the tokenizer, it may be split into multiple tokens because the model has learned common sub-word patterns rather than every possible English word.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;authentication
authorization
microservices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;may also become multiple tokens.&lt;/p&gt;

&lt;p&gt;The tokenizer isn't trying to understand grammar.&lt;/p&gt;

&lt;p&gt;It's trying to represent text efficiently based on patterns it learned during training.&lt;/p&gt;




&lt;h1&gt;
  
  
  📦 Different Types of Content Produce Different Numbers of Tokens
&lt;/h1&gt;

&lt;p&gt;One reason token counting surprises developers is that not all text is equal.&lt;/p&gt;

&lt;p&gt;Take these examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1 — Simple English
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The server is running normally.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is relatively efficient because it contains common words.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example 2 — JSON
&lt;/h3&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;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isActive"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;Even though this looks short, punctuation, quotes, braces and field names also become tokens.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example 3 — Source Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Programming languages introduce symbols, keywords, indentation and identifiers, all of which contribute to the token count.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example 4 — URLs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com/api/v1/users/123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;URLs often tokenize differently because of slashes, punctuation and path segments.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example 5 — Emojis
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🚀🔥🎉
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even emojis are tokenized.&lt;/p&gt;

&lt;p&gt;Different models may tokenize the same emoji sequence differently.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 The Important Lesson
&lt;/h2&gt;

&lt;p&gt;Tokens are &lt;strong&gt;not based on what humans consider words.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They're based on how the tokenizer breaks text into pieces.&lt;/p&gt;

&lt;p&gt;That's why two pieces of text with the same number of characters can consume very different numbers of tokens.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Why Should Developers Care About Tokens?
&lt;/h1&gt;

&lt;p&gt;Many developers only think about tokens when they receive an API bill.&lt;/p&gt;

&lt;p&gt;In reality, tokens influence almost everything about an AI system.&lt;/p&gt;

&lt;p&gt;They affect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Context size&lt;/li&gt;
&lt;li&gt;Response quality&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every AI request starts with a token budget.&lt;/p&gt;

&lt;p&gt;The more tokens you consume, the more work the model has to perform.&lt;/p&gt;




&lt;h1&gt;
  
  
  💰 Everything Consumes Tokens
&lt;/h1&gt;

&lt;p&gt;Here's something many people don't realize.&lt;/p&gt;

&lt;p&gt;When you send a request to an LLM, you're not paying only for your latest prompt.&lt;/p&gt;

&lt;p&gt;The model processes &lt;strong&gt;everything&lt;/strong&gt; included in the request.&lt;/p&gt;

&lt;p&gt;That may include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Content&lt;/th&gt;
&lt;th&gt;Uses Tokens?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System Instructions&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User Prompt&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conversation History&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uploaded Documents&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieved RAG Results&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool Outputs&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function Call Results&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Response&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Even if you only typed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Summarize this.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model might actually receive thousands of tokens.&lt;/p&gt;

&lt;p&gt;Imagine asking an AI coding assistant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Why is this function failing?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, the application might automatically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System instructions&lt;/li&gt;
&lt;li&gt;Current source file&lt;/li&gt;
&lt;li&gt;Nearby functions&lt;/li&gt;
&lt;li&gt;Package imports&lt;/li&gt;
&lt;li&gt;Build configuration&lt;/li&gt;
&lt;li&gt;Previous conversation&lt;/li&gt;
&lt;li&gt;Compiler errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your four-word prompt becomes a request containing thousands of tokens.&lt;/p&gt;

&lt;p&gt;This is another example of &lt;strong&gt;Context Engineering&lt;/strong&gt; in action.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Every New Request Starts Again
&lt;/h1&gt;

&lt;p&gt;This surprises many engineers.&lt;/p&gt;

&lt;p&gt;Suppose your conversation looks like this:&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;User&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;Explain&lt;/span&gt; &lt;span class="n"&gt;JWT&lt;/span&gt; &lt;span class="n"&gt;Authentication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Assistant&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;Can&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Go&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Assistant&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;Can&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many people imagine the model simply remembers everything internally.&lt;/p&gt;

&lt;p&gt;That's not how most stateless LLM API interactions work.&lt;/p&gt;

&lt;p&gt;For each new request, the application typically sends the conversation history (or a selected portion of it) again so the model has the necessary context to continue the conversation coherently.&lt;/p&gt;

&lt;p&gt;Conceptually, it looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1

System Prompt
User Message

↓

LLM

------------------------

Request 2

System Prompt
Conversation History
New User Message

↓

LLM

------------------------

Request 3

System Prompt
Conversation History
Latest User Message

↓

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

&lt;/div&gt;



&lt;p&gt;As the conversation grows longer, more tokens are often included with each request unless the application trims, summarizes or otherwise manages the context.&lt;/p&gt;

&lt;p&gt;This is one reason token usage can increase significantly during long conversations.&lt;/p&gt;




&lt;h1&gt;
  
  
  🪟 What Is a Context Window?
&lt;/h1&gt;

&lt;p&gt;Now we can finally answer the question from the beginning.&lt;/p&gt;

&lt;p&gt;If tokens are the building blocks…&lt;/p&gt;

&lt;p&gt;Then what is the &lt;strong&gt;Context Window?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A context window is the maximum amount of information (measured in tokens) that a model can consider at one time while generating a response.&lt;/p&gt;

&lt;p&gt;Think of it like a whiteboard.&lt;/p&gt;

&lt;p&gt;Imagine you're solving a difficult problem with a teammate.&lt;/p&gt;

&lt;p&gt;Everything written on the whiteboard is available to both of you.&lt;/p&gt;

&lt;p&gt;You can read it.&lt;/p&gt;

&lt;p&gt;Reference it.&lt;/p&gt;

&lt;p&gt;Connect ideas.&lt;/p&gt;

&lt;p&gt;Reason about it.&lt;/p&gt;

&lt;p&gt;But the whiteboard isn't infinite.&lt;/p&gt;

&lt;p&gt;Eventually, it fills up.&lt;/p&gt;

&lt;p&gt;To continue working, you have two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Erase older notes.&lt;/li&gt;
&lt;li&gt;Replace them with a summary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Large Language Models work in a very similar way.&lt;/p&gt;

&lt;p&gt;The context window is that whiteboard.&lt;/p&gt;

&lt;p&gt;Everything currently inside it is visible to the model while it generates its next response.&lt;/p&gt;

&lt;p&gt;Everything outside it is invisible unless your application decides to bring it back.&lt;/p&gt;




&lt;h1&gt;
  
  
  📖 What's Actually Inside the Context Window?
&lt;/h1&gt;

&lt;p&gt;One common misconception is that the context window contains only your prompt.&lt;/p&gt;

&lt;p&gt;In reality, modern AI applications often build a much richer context before sending the request.&lt;/p&gt;

&lt;p&gt;A simplified request might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System Instructions

↓

Conversation History

↓

Retrieved Knowledge (RAG)

↓

Uploaded Files

↓

Tool Results

↓

Current User Prompt

↓

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

&lt;/div&gt;



&lt;p&gt;Notice something interesting.&lt;/p&gt;

&lt;p&gt;Your latest message may only be a tiny fraction of everything the model receives.&lt;/p&gt;

&lt;p&gt;The application has already assembled the rest of the context behind the scenes.&lt;/p&gt;

&lt;p&gt;This is why two AI tools using the same underlying model can produce very different answers.&lt;/p&gt;

&lt;p&gt;The difference often isn't the model itself.&lt;/p&gt;

&lt;p&gt;It's &lt;strong&gt;how effectively each application constructs the context before making the request.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🤔 Does a Bigger Context Window Always Mean Better AI?
&lt;/h1&gt;

&lt;p&gt;At first glance, it sounds obvious.&lt;/p&gt;

&lt;p&gt;If an AI model can process more information, shouldn't the answers always improve?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Imagine you're preparing for an interview.&lt;/p&gt;

&lt;p&gt;Someone gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your resume&lt;/li&gt;
&lt;li&gt;The job description&lt;/li&gt;
&lt;li&gt;Company documentation&lt;/li&gt;
&lt;li&gt;Engineering handbook&lt;/li&gt;
&lt;li&gt;API documentation&lt;/li&gt;
&lt;li&gt;Meeting notes&lt;/li&gt;
&lt;li&gt;Internal wiki&lt;/li&gt;
&lt;li&gt;Product roadmap&lt;/li&gt;
&lt;li&gt;Last year's planning documents&lt;/li&gt;
&lt;li&gt;Random Slack conversations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Could you answer the interview questions?&lt;/p&gt;

&lt;p&gt;Probably.&lt;/p&gt;

&lt;p&gt;Would all that information actually help?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;In fact, it might make things worse because you'd spend time filtering out irrelevant information before focusing on what matters.&lt;/p&gt;

&lt;p&gt;Large Language Models face a similar challenge.&lt;/p&gt;

&lt;p&gt;A larger context window allows the model to &lt;strong&gt;see more information&lt;/strong&gt;, but it doesn't mean every piece of that information is equally useful.&lt;/p&gt;

&lt;p&gt;Good Context Engineering isn't about maximizing context.&lt;/p&gt;

&lt;p&gt;It's about &lt;strong&gt;optimizing context&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 More Context ≠ Better Context
&lt;/h1&gt;

&lt;p&gt;One of the biggest mistakes in AI applications is thinking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If some context helps,
more context must help even more.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's rarely true.&lt;/p&gt;

&lt;p&gt;Imagine building an AI coding assistant.&lt;/p&gt;

&lt;p&gt;A developer asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Why is this API returning 500?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option A:&lt;/p&gt;

&lt;p&gt;Provide only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The API handler&lt;/li&gt;
&lt;li&gt;Relevant service&lt;/li&gt;
&lt;li&gt;Error log&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Option B:&lt;/p&gt;

&lt;p&gt;Provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entire repository&lt;/li&gt;
&lt;li&gt;All dependencies&lt;/li&gt;
&lt;li&gt;Every README&lt;/li&gt;
&lt;li&gt;CI/CD configuration&lt;/li&gt;
&lt;li&gt;Kubernetes manifests&lt;/li&gt;
&lt;li&gt;Previous conversations&lt;/li&gt;
&lt;li&gt;All database schemas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, the model has more information.&lt;/p&gt;

&lt;p&gt;Practically, you've introduced noise.&lt;/p&gt;

&lt;p&gt;Finding the relevant signal becomes harder.&lt;/p&gt;

&lt;p&gt;This is why mature AI systems spend significant effort deciding &lt;strong&gt;what not to include&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Context Engineering is often about removing information rather than adding it.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔍 The "Lost in the Middle" Problem
&lt;/h1&gt;

&lt;p&gt;Researchers have observed an interesting behavior in long-context language models.&lt;/p&gt;

&lt;p&gt;When a prompt becomes very large, information buried in the middle of the context may receive less attention than information closer to the beginning or end.&lt;/p&gt;

&lt;p&gt;This phenomenon is commonly referred to as the &lt;strong&gt;"Lost in the Middle"&lt;/strong&gt; effect.&lt;/p&gt;

&lt;p&gt;Imagine reading a 300-page document.&lt;/p&gt;

&lt;p&gt;You usually remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The introduction&lt;/li&gt;
&lt;li&gt;The conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But details from page 147?&lt;/p&gt;

&lt;p&gt;Much harder.&lt;/p&gt;

&lt;p&gt;Language models can exhibit similar behavior under certain conditions.&lt;/p&gt;

&lt;p&gt;This doesn't mean long-context models are ineffective.&lt;/p&gt;

&lt;p&gt;It means that &lt;strong&gt;how information is organized inside the context matters&lt;/strong&gt;, not just how much information is included.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 Context Is NOT Memory
&lt;/h1&gt;

&lt;p&gt;This is probably the biggest misconception about modern AI.&lt;/p&gt;

&lt;p&gt;People often say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"ChatGPT remembered what I told it last week."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What actually happened depends on the application.&lt;/p&gt;

&lt;p&gt;It's important to distinguish between &lt;strong&gt;context&lt;/strong&gt; and &lt;strong&gt;memory&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Context is the information available &lt;strong&gt;only for the current request&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the request is complete, the model itself doesn't retain that context for future API calls.&lt;/p&gt;

&lt;p&gt;Think of it as a whiteboard used during a meeting.&lt;/p&gt;

&lt;p&gt;Erase the whiteboard and the discussion is gone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory
&lt;/h2&gt;

&lt;p&gt;Memory is information that an application intentionally stores and later reintroduces into future conversations.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;You tell an AI assistant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I primarily write Go and React.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application might choose to save that preference.&lt;/p&gt;

&lt;p&gt;Next week, when you ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generate an API example.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application retrieves your stored preference and injects it into the new request.&lt;/p&gt;

&lt;p&gt;The model appears to "remember."&lt;/p&gt;

&lt;p&gt;In reality, the application supplied that information again.&lt;/p&gt;

&lt;p&gt;The memory lives in the application—not inside the language model itself.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗️ A Simple Mental Model
&lt;/h1&gt;

&lt;p&gt;Think of an AI application as three separate components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                User

                  │
                  ▼

      ┌─────────────────────┐
      │   Memory Store      │
      └─────────────────────┘
                  │
                  ▼
      ┌─────────────────────┐
      │ Context Builder     │
      │ - System Prompt     │
      │ - History           │
      │ - RAG Results       │
      │ - Tool Outputs      │
      └─────────────────────┘
                  │
                  ▼
      ┌─────────────────────┐
      │        LLM          │
      └─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM only sees the final assembled context.&lt;/p&gt;

&lt;p&gt;It doesn't know where each piece of information came from.&lt;/p&gt;




&lt;h1&gt;
  
  
  💰 Why Tokens Matter for Cost and Performance
&lt;/h1&gt;

&lt;p&gt;We've already learned that everything consumes tokens.&lt;/p&gt;

&lt;p&gt;But token usage affects much more than pricing.&lt;/p&gt;

&lt;p&gt;It also impacts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request latency&lt;/li&gt;
&lt;li&gt;Throughput&lt;/li&gt;
&lt;li&gt;Infrastructure cost&lt;/li&gt;
&lt;li&gt;User experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider these two requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Efficient Request
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System Prompt

Relevant API documentation

Current User Question
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Inefficient Request
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System Prompt

Entire conversation

Complete codebase

Multiple PDFs

Large JSON payloads

Old logs

Current User Question
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second request requires the model to process significantly more information before generating a response.&lt;/p&gt;

&lt;p&gt;Even if the answer only depends on a small portion of that data.&lt;/p&gt;

&lt;p&gt;More tokens generally mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More computation&lt;/li&gt;
&lt;li&gt;Higher latency&lt;/li&gt;
&lt;li&gt;Higher cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why production AI systems invest heavily in efficient context management.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ How Production AI Systems Manage Context
&lt;/h1&gt;

&lt;p&gt;Well-designed AI applications rarely send everything they know to the model.&lt;/p&gt;

&lt;p&gt;Instead, they carefully construct the context.&lt;/p&gt;

&lt;p&gt;Some common strategies include:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Retrieve Only What's Relevant
&lt;/h3&gt;

&lt;p&gt;Instead of sending an entire knowledge base,&lt;/p&gt;

&lt;p&gt;retrieve only the documents related to the user's question.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Summarize Long Conversations
&lt;/h3&gt;

&lt;p&gt;Rather than sending hundreds of previous messages,&lt;/p&gt;

&lt;p&gt;summarize earlier parts while preserving important facts.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;150 previous messages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Conversation Summary:

• User uses Go
• Building REST APIs
• Uses PostgreSQL
• Currently debugging authentication
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Far fewer tokens.&lt;/p&gt;

&lt;p&gt;Much easier for the model.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Keep System Prompts Focused
&lt;/h3&gt;

&lt;p&gt;System instructions should define behavior,&lt;/p&gt;

&lt;p&gt;not contain an entire company handbook.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Separate Long-Term Memory from Current Context
&lt;/h3&gt;

&lt;p&gt;Store reusable preferences separately.&lt;/p&gt;

&lt;p&gt;Retrieve them only when needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Measure Token Usage
&lt;/h3&gt;

&lt;p&gt;Don't optimize blindly.&lt;/p&gt;

&lt;p&gt;Most AI SDKs expose token usage statistics.&lt;/p&gt;

&lt;p&gt;Monitoring them helps identify unnecessary context and control costs.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚫 Common Context Engineering Mistakes
&lt;/h1&gt;

&lt;p&gt;Here are some patterns that often reduce AI quality rather than improve it.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Dumping entire documents into every request
&lt;/h3&gt;

&lt;p&gt;More information isn't automatically better.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ Sending the full conversation forever
&lt;/h3&gt;

&lt;p&gt;Long conversations should be summarized or trimmed when appropriate.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ Treating memory as conversation history
&lt;/h3&gt;

&lt;p&gt;They're different concepts.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ Ignoring token usage
&lt;/h3&gt;

&lt;p&gt;Unexpected token growth often leads to higher costs and slower responses.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ Assuming bigger context windows solve everything
&lt;/h3&gt;

&lt;p&gt;Context quality matters far more than context quantity.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Best Practices
&lt;/h1&gt;

&lt;p&gt;If you're building AI-powered applications, keep these principles in mind:&lt;/p&gt;

&lt;p&gt;✅ Send only the information required for the current task.&lt;/p&gt;

&lt;p&gt;✅ Prefer relevant context over larger context.&lt;/p&gt;

&lt;p&gt;✅ Separate memory from conversation history.&lt;/p&gt;

&lt;p&gt;✅ Summarize older interactions instead of continuously expanding prompts.&lt;/p&gt;

&lt;p&gt;✅ Monitor token usage in production.&lt;/p&gt;

&lt;p&gt;✅ Design context deliberately instead of simply appending more text.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏁 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;When people first start working with AI, they often focus on prompts.&lt;/p&gt;

&lt;p&gt;Then they discover Context Engineering.&lt;/p&gt;

&lt;p&gt;Eventually, they realize another important truth:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not all context is equally valuable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern AI systems succeed because they carefully decide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What to include&lt;/li&gt;
&lt;li&gt;What to exclude&lt;/li&gt;
&lt;li&gt;What to summarize&lt;/li&gt;
&lt;li&gt;What to retrieve&lt;/li&gt;
&lt;li&gt;What to remember&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That decision-making process is often more important than the prompt itself.&lt;/p&gt;

&lt;p&gt;The best AI applications aren't the ones with the biggest context windows.&lt;/p&gt;

&lt;p&gt;They're the ones that provide &lt;strong&gt;the right information at the right time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that's exactly what Context Engineering is about.&lt;/p&gt;




&lt;h1&gt;
  
  
  📌 Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Tokens are the fundamental units processed by language models—they are not the same as words.&lt;/li&gt;
&lt;li&gt;Every request consumes tokens, including system prompts, conversation history, retrieved documents, tool outputs and the model's response.&lt;/li&gt;
&lt;li&gt;A context window defines how much information a model can consider at once.&lt;/li&gt;
&lt;li&gt;Larger context windows are useful, but more context doesn't automatically lead to better answers.&lt;/li&gt;
&lt;li&gt;Context and memory are different: context exists for the current request, while memory is information intentionally stored and reintroduced by the application.&lt;/li&gt;
&lt;li&gt;Effective Context Engineering is about sending &lt;strong&gt;relevant&lt;/strong&gt; information, not &lt;strong&gt;all&lt;/strong&gt; available information.&lt;/li&gt;
&lt;li&gt;Good context management improves response quality, reduces costs and lowers latency.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🚀 Coming Up in Part 3
&lt;/h1&gt;

&lt;p&gt;So far, we've answered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Context Engineering?&lt;/li&gt;
&lt;li&gt;What are tokens?&lt;/li&gt;
&lt;li&gt;How do context windows work?&lt;/li&gt;
&lt;li&gt;Why isn't bigger context always better?&lt;/li&gt;
&lt;li&gt;What's the difference between context and memory?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But another important question remains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Where does all this context actually come from?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How do AI applications automatically search documentation, query databases, call APIs, execute tools and decide what information should be sent to the model?&lt;/p&gt;

&lt;p&gt;That's where concepts like &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;, &lt;strong&gt;Tool Calling&lt;/strong&gt;, &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; and &lt;strong&gt;AI Agents&lt;/strong&gt; come into the picture.&lt;/p&gt;

&lt;p&gt;We'll break each of them down in &lt;strong&gt;Part 3&lt;/strong&gt; with practical examples and real-world engineering scenarios.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>llm</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🧠 AI Context Engineering (Part 1): Why Great AI Systems Need More Than Great Prompts</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sat, 27 Jun 2026 11:15:39 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/ai-context-engineering-why-great-ai-systems-need-more-than-great-prompts-part-1-25dd</link>
      <guid>https://dev.to/fazal_mansuri_/ai-context-engineering-why-great-ai-systems-need-more-than-great-prompts-part-1-25dd</guid>
      <description>&lt;p&gt;A couple of years ago, almost every AI discussion revolved around one thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt Engineering.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;People shared prompts like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Use this prompt to become a senior software engineer."&lt;/li&gt;
&lt;li&gt;"Use this prompt to write perfect SQL."&lt;/li&gt;
&lt;li&gt;"Use this prompt to generate production-ready code."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The assumption was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Better prompt = Better AI output.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While prompts certainly matter, engineers building production AI systems quickly realized something important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The prompt is only one piece of the puzzle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern AI applications - whether it's ChatGPT, Claude, Cursor, GitHub Copilot or AI coding agents - don't rely on a single prompt.&lt;/p&gt;

&lt;p&gt;They combine multiple sources of information before generating a response.&lt;/p&gt;

&lt;p&gt;That broader discipline is known as &lt;strong&gt;Context Engineering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And understanding it is becoming one of the most valuable skills for engineers building AI-powered products.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Is Context Engineering?
&lt;/h1&gt;

&lt;p&gt;Context Engineering is the practice of providing an AI model with the &lt;strong&gt;right information at the right time&lt;/strong&gt; so it can generate accurate, relevant, and reliable responses.&lt;/p&gt;

&lt;p&gt;Think of it this way:&lt;/p&gt;

&lt;p&gt;Prompt Engineering asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What should I ask the model?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Context Engineering asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What information should the model have before it answers?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference might sound subtle.&lt;/p&gt;

&lt;p&gt;In reality, it changes everything.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Simple Analogy
&lt;/h1&gt;

&lt;p&gt;Imagine you ask two developers the same question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I fix this production bug?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Developer A
&lt;/h3&gt;

&lt;p&gt;You only tell them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The application is broken."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Can they help?&lt;/p&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;But they'll probably ask dozens of follow-up questions.&lt;/p&gt;




&lt;h3&gt;
  
  
  Developer B
&lt;/h3&gt;

&lt;p&gt;Instead, you provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error logs&lt;/li&gt;
&lt;li&gt;Stack trace&lt;/li&gt;
&lt;li&gt;API request&lt;/li&gt;
&lt;li&gt;Database query&lt;/li&gt;
&lt;li&gt;Recent deployment&lt;/li&gt;
&lt;li&gt;Service architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now they're much more likely to identify the issue quickly.&lt;/p&gt;

&lt;p&gt;Did they become smarter?&lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;You simply gave them &lt;strong&gt;better context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Large Language Models work the same way.&lt;/p&gt;




&lt;h1&gt;
  
  
  Prompt vs Context
&lt;/h1&gt;

&lt;p&gt;Suppose you ask an AI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;Write&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="k"&gt;fetch&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a perfectly valid prompt.&lt;/p&gt;

&lt;p&gt;But now imagine providing additional context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PostgreSQL&lt;/span&gt;

&lt;span class="n"&gt;Tables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;

&lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;ACTIVE&lt;/span&gt;
&lt;span class="n"&gt;INACTIVE&lt;/span&gt;
&lt;span class="n"&gt;BLOCKED&lt;/span&gt;

&lt;span class="k"&gt;Return&lt;/span&gt; &lt;span class="k"&gt;only&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="k"&gt;after&lt;/span&gt; &lt;span class="n"&gt;January&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt itself barely changed.&lt;/p&gt;

&lt;p&gt;What improved was the &lt;strong&gt;context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And naturally, the quality of the output improves as well.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Prompt Engineering Alone Isn't Enough
&lt;/h1&gt;

&lt;p&gt;Imagine building an AI customer support assistant.&lt;/p&gt;

&lt;p&gt;If every user message is handled using only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
Where is my order?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the model has no idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which customer is asking&lt;/li&gt;
&lt;li&gt;Which order they mean&lt;/li&gt;
&lt;li&gt;Whether it has already been shipped&lt;/li&gt;
&lt;li&gt;Previous conversations&lt;/li&gt;
&lt;li&gt;Company refund policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without that information, the model can only guess.&lt;/p&gt;

&lt;p&gt;Instead, production AI systems enrich the request with additional context before sending it to the model.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System Instructions

Customer Name

Previous Conversation

Order Status

Shipping Details

Refund Policy

Current User Question
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model now has everything it needs to generate a useful answer.&lt;/p&gt;

&lt;p&gt;Notice something interesting:&lt;/p&gt;

&lt;p&gt;The user's prompt didn't become dramatically better.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;available context&lt;/strong&gt; did.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Actually Forms the Context?
&lt;/h1&gt;

&lt;p&gt;Many developers think context means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The text I type into ChatGPT."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's only part of it.&lt;/p&gt;

&lt;p&gt;In reality, the model usually receives much more information.&lt;/p&gt;

&lt;p&gt;A typical request may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System instructions&lt;/li&gt;
&lt;li&gt;User prompt&lt;/li&gt;
&lt;li&gt;Conversation history&lt;/li&gt;
&lt;li&gt;Retrieved documentation&lt;/li&gt;
&lt;li&gt;Project files&lt;/li&gt;
&lt;li&gt;Tool outputs&lt;/li&gt;
&lt;li&gt;Function call results&lt;/li&gt;
&lt;li&gt;Memory from previous interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this together forms the &lt;strong&gt;context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The model doesn't distinguish whether information came from you, a database, or another tool.&lt;/p&gt;

&lt;p&gt;It simply processes the complete context it receives.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Real-World Example
&lt;/h1&gt;

&lt;p&gt;Consider an AI coding assistant.&lt;/p&gt;

&lt;p&gt;You ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain this function.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How does it know which function you're referring to?&lt;/p&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;The IDE silently provides additional context such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The currently opened file&lt;/li&gt;
&lt;li&gt;Surrounding code&lt;/li&gt;
&lt;li&gt;Project structure&lt;/li&gt;
&lt;li&gt;Imported packages&lt;/li&gt;
&lt;li&gt;Programming language&lt;/li&gt;
&lt;li&gt;Cursor position&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You only typed four words.&lt;/p&gt;

&lt;p&gt;Yet the model received thousands of tokens of additional information behind the scenes.&lt;/p&gt;

&lt;p&gt;That's Context Engineering in action.&lt;/p&gt;




&lt;h1&gt;
  
  
  Another Example: ChatGPT
&lt;/h1&gt;

&lt;p&gt;Suppose you ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Summarize this document.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What actually reaches the model?&lt;/p&gt;

&lt;p&gt;Something closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System Instructions

Conversation History

Uploaded PDF

User Prompt

Formatting Rules

Safety Instructions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, the prompt is only a small part of the overall request.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Mental Shift
&lt;/h1&gt;

&lt;p&gt;Many developers spend hours refining prompts like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Act as a senior software engineer with 20 years of experience...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes it helps.&lt;/p&gt;

&lt;p&gt;But often, providing the model with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better documentation&lt;/li&gt;
&lt;li&gt;Relevant code&lt;/li&gt;
&lt;li&gt;Correct API schemas&lt;/li&gt;
&lt;li&gt;Business rules&lt;/li&gt;
&lt;li&gt;Examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;produces significantly better results than endlessly tweaking the wording of the prompt.&lt;/p&gt;

&lt;p&gt;The question changes from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How should I ask?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What information is the model missing?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the mindset of Context Engineering.&lt;/p&gt;




&lt;h1&gt;
  
  
  Common Misconceptions
&lt;/h1&gt;

&lt;h3&gt;
  
  
  ❌ "A bigger prompt always gives better answers."
&lt;/h3&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Adding irrelevant information can confuse the model.&lt;/p&gt;

&lt;p&gt;Good context is &lt;strong&gt;relevant&lt;/strong&gt;, &lt;strong&gt;accurate&lt;/strong&gt;, and &lt;strong&gt;focused&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ "Prompt Engineering is no longer useful."
&lt;/h3&gt;

&lt;p&gt;Prompt Engineering is still important.&lt;/p&gt;

&lt;p&gt;A clear prompt helps the model understand the task.&lt;/p&gt;

&lt;p&gt;Context Engineering simply expands the scope by ensuring the model also has the information required to perform that task well.&lt;/p&gt;

&lt;p&gt;Think of prompt engineering as one part of the larger Context Engineering process.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ "Only AI engineers need to know this."
&lt;/h3&gt;

&lt;p&gt;If you build software that integrates AI in any form—chatbots, coding assistants, document search, customer support, or internal tools—understanding how context influences responses will help you design more reliable systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why This Matters More Than Ever
&lt;/h1&gt;

&lt;p&gt;Modern AI applications are no longer just chat interfaces.&lt;/p&gt;

&lt;p&gt;They're becoming agents that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read documents&lt;/li&gt;
&lt;li&gt;Search knowledge bases&lt;/li&gt;
&lt;li&gt;Execute tools&lt;/li&gt;
&lt;li&gt;Call APIs&lt;/li&gt;
&lt;li&gt;Generate code&lt;/li&gt;
&lt;li&gt;Reason over project files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The quality of these systems depends less on writing a "magic prompt" and more on giving the model the &lt;strong&gt;right context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that's exactly what Context Engineering is about.&lt;/p&gt;




&lt;h1&gt;
  
  
  What's Coming in Part 2?
&lt;/h1&gt;

&lt;p&gt;Now that we understand why context matters, another important question arises:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How much context should we provide?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Is more always better?&lt;/p&gt;

&lt;p&gt;What are &lt;strong&gt;tokens&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;What is a &lt;strong&gt;context window&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Why do AI tools sometimes forget earlier parts of a conversation?&lt;/p&gt;

&lt;p&gt;And why can adding too much information actually reduce response quality?&lt;/p&gt;

&lt;p&gt;We'll answer all of these in &lt;strong&gt;Part 2&lt;/strong&gt;, where we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context Windows&lt;/li&gt;
&lt;li&gt;Tokens&lt;/li&gt;
&lt;li&gt;Conversation History&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Why bigger context isn't always better&lt;/li&gt;
&lt;li&gt;Practical strategies used by modern AI applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding these concepts will completely change how you think about interacting with—and building—AI systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Prompt Engineering and Context Engineering are related, but not the same.&lt;/li&gt;
&lt;li&gt;Great AI systems rely on much more than the user's prompt.&lt;/li&gt;
&lt;li&gt;Context includes system instructions, conversation history, retrieved information, tool outputs, and more.&lt;/li&gt;
&lt;li&gt;Better context often improves AI responses more than endlessly refining prompts.&lt;/li&gt;
&lt;li&gt;Thinking in terms of &lt;strong&gt;"What information is the model missing?"&lt;/strong&gt; is the first step toward building effective AI-powered applications.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you've ever wondered why the same prompt produces excellent results in one AI application and poor results in another, the answer often isn't the model itself.&lt;/p&gt;

&lt;p&gt;It's the &lt;strong&gt;context&lt;/strong&gt; behind the scenes.&lt;/p&gt;

&lt;p&gt;See you in &lt;strong&gt;Part 2&lt;/strong&gt; 👋&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>llm</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🚨 CSS Specificity — The Hidden Reason Your UI Breaks</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sat, 06 Jun 2026 06:57:43 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/css-specificity-the-hidden-reason-your-ui-breaks-2jhp</link>
      <guid>https://dev.to/fazal_mansuri_/css-specificity-the-hidden-reason-your-ui-breaks-2jhp</guid>
      <description>&lt;p&gt;Most developers learn CSS specificity once.&lt;/p&gt;

&lt;p&gt;They remember:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.class&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then move on.&lt;/p&gt;

&lt;p&gt;Until one day…&lt;/p&gt;

&lt;p&gt;Everything looks correct.&lt;/p&gt;

&lt;p&gt;The CSS is present.&lt;/p&gt;

&lt;p&gt;The selector is correct.&lt;/p&gt;

&lt;p&gt;The z-index looks higher.&lt;/p&gt;

&lt;p&gt;And yet the UI is broken.&lt;/p&gt;

&lt;p&gt;That’s when CSS specificity stops being a beginner topic and becomes a production debugging problem.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Production Incident That Started This
&lt;/h1&gt;

&lt;p&gt;Recently, I was working on a microfrontend application.&lt;/p&gt;

&lt;p&gt;Everything worked fine initially.&lt;/p&gt;

&lt;p&gt;I opened a page, launched a modal and the UI looked correct.&lt;/p&gt;

&lt;p&gt;Then I navigated to another microfrontend.&lt;/p&gt;

&lt;p&gt;Its CSS got loaded.&lt;/p&gt;

&lt;p&gt;After returning to the original microfrontend, suddenly:&lt;/p&gt;

&lt;p&gt;❌ Modal appeared behind page content&lt;br&gt;
❌ Overlay behaved incorrectly&lt;br&gt;
❌ z-index looked correct but wasn't working&lt;/p&gt;

&lt;p&gt;DevTools showed my CSS rule still existed.&lt;/p&gt;

&lt;p&gt;Yet another CSS rule was winning.&lt;/p&gt;

&lt;p&gt;The culprit?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CSS Specificity.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  🧠 What is CSS Specificity?
&lt;/h1&gt;

&lt;p&gt;CSS specificity is the algorithm browsers use to decide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which CSS rule wins when multiple rules target the same element.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Browsers don't simply apply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The last CSS rule."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's one of the biggest misconceptions.&lt;/p&gt;

&lt;p&gt;Specificity is calculated first.&lt;/p&gt;

&lt;p&gt;Only when specificity is equal does source order become important.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⚔️ Example
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9999&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.some-library&lt;/span&gt; &lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&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;HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"some-library"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many developers expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to win because the value is larger.&lt;/p&gt;

&lt;p&gt;But CSS doesn't compare values first.&lt;/p&gt;

&lt;p&gt;It compares selectors.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧮 How Specificity Works
&lt;/h1&gt;

&lt;p&gt;Specificity is usually represented as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID - CLASS - TYPE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Specificity Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Selector&lt;/th&gt;
&lt;th&gt;Specificity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0-0-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;div&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0-0-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.modal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[type="text"]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:hover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#dialog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1-0-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inline Style&lt;/td&gt;
&lt;td&gt;Highest&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;MDN defines specificity as the weight browsers calculate to determine which declaration gets applied when multiple selectors match the same element.&lt;/p&gt;




&lt;h1&gt;
  
  
  Example Calculation
&lt;/h1&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;     &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-0-1&lt;/span&gt;
&lt;span class="nc"&gt;.primary&lt;/span&gt;   &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-1-0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0-1-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Another selector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#header&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#header&lt;/span&gt;   &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;-0-0&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-0-1&lt;/span&gt;
&lt;span class="nc"&gt;.primary&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-1-0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1-1-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This selector wins.&lt;/p&gt;




&lt;h1&gt;
  
  
  ❌ Myth #1 — Last CSS Always Wins
&lt;/h1&gt;

&lt;p&gt;Many developers believe:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The CSS rule written last wins.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not always.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&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;HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Hello
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Red
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#header = 1-0-0
div     = 0-0-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specificity wins before source order.&lt;/p&gt;




&lt;h1&gt;
  
  
  ❌ Myth #2 — Higher z-index Always Wins
&lt;/h1&gt;

&lt;p&gt;This causes countless production bugs.&lt;/p&gt;

&lt;p&gt;Developers often write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;99999&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;And expect it to appear above everything.&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;z-index works inside stacking contexts.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  🧠 What is a Stacking Context?
&lt;/h1&gt;

&lt;p&gt;A stacking context is a separate layering environment.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;999999&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;Even with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;999999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the child cannot escape its parent's stacking context.&lt;/p&gt;

&lt;p&gt;This is why modal, tooltip, dropdown, and popover bugs often feel confusing.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Microfrontend Problem
&lt;/h1&gt;

&lt;p&gt;This is where specificity becomes extremely important.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;/p&gt;

&lt;h3&gt;
  
  
  Microfrontend A
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9999&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;
  
  
  Microfrontend B
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.layout&lt;/span&gt; &lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&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;Specificity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-1-0&lt;/span&gt;

&lt;span class="nc"&gt;.layout&lt;/span&gt; &lt;span class="nc"&gt;.modal&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-2-0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Microfrontend B wins.&lt;/p&gt;

&lt;p&gt;Even if your CSS is still loaded.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why My Fix Worked
&lt;/h1&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9999&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;But another selector had higher specificity.&lt;/p&gt;

&lt;p&gt;So I wrapped the modal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dialog-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Modal&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.dialog-wrapper&lt;/span&gt; &lt;span class="nc"&gt;.modal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9999&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;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.modal&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-1-0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.dialog-wrapper&lt;/span&gt; &lt;span class="nc"&gt;.modal&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;-2-0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now my selector became more specific and started winning.&lt;/p&gt;

&lt;p&gt;The CSS value never changed.&lt;/p&gt;

&lt;p&gt;Only specificity changed.&lt;/p&gt;

&lt;p&gt;And the issue disappeared.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚨 Why This Happens More in Microfrontends
&lt;/h1&gt;

&lt;p&gt;Microfrontends often share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same DOM&lt;/li&gt;
&lt;li&gt;Same global CSS&lt;/li&gt;
&lt;li&gt;Same class names&lt;/li&gt;
&lt;li&gt;Same browser environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS leakage&lt;/li&gt;
&lt;li&gt;Style collisions&lt;/li&gt;
&lt;li&gt;Unexpected overrides&lt;/li&gt;
&lt;li&gt;Load-order changes after navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes specificity bugs significantly more common.&lt;/p&gt;




&lt;h1&gt;
  
  
  Modern CSS Specificity Features Developers Often Miss
&lt;/h1&gt;




&lt;h1&gt;
  
  
  1️⃣ &lt;code&gt;:is()&lt;/code&gt;
&lt;/h1&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.link&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;:is()&lt;/code&gt; pseudo-class itself doesn't add specificity.&lt;/p&gt;

&lt;p&gt;Instead, it takes the specificity of the most specific selector inside it.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;#header&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1-0-0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#header&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is most specific.&lt;/p&gt;




&lt;h1&gt;
  
  
  2️⃣ &lt;code&gt;:not()&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Many developers think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.hidden&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;adds nothing.&lt;/p&gt;

&lt;p&gt;Not true.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:not()&lt;/code&gt; itself doesn't contribute specificity.&lt;/p&gt;

&lt;p&gt;But selectors inside it do.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.hidden&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0-1-0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  3️⃣ &lt;code&gt;:where()&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;One of the most underrated CSS features.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0-0-0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:where()&lt;/code&gt; intentionally has zero specificity.&lt;/p&gt;

&lt;p&gt;This makes it extremely useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design systems&lt;/li&gt;
&lt;li&gt;Component libraries&lt;/li&gt;
&lt;li&gt;Shared UI frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because consumers can easily override styles.&lt;/p&gt;




&lt;h1&gt;
  
  
  How to Debug CSS Specificity Issues
&lt;/h1&gt;

&lt;p&gt;When CSS isn't applying:&lt;/p&gt;

&lt;p&gt;Check these in order:&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Is the rule present?
&lt;/h2&gt;

&lt;p&gt;Open DevTools.&lt;/p&gt;

&lt;p&gt;Verify the CSS exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Is it crossed out?
&lt;/h2&gt;

&lt;p&gt;Crossed-out CSS usually means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another rule won.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Which selector is winning?
&lt;/h2&gt;

&lt;p&gt;DevTools shows the winning selector.&lt;/p&gt;

&lt;p&gt;Inspect it carefully.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Compare specificity
&lt;/h2&gt;

&lt;p&gt;Many bugs become obvious here.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Check CSS load order
&lt;/h2&gt;

&lt;p&gt;When specificity is equal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Last rule wins.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Check stacking contexts
&lt;/h2&gt;

&lt;p&gt;Especially for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modals&lt;/li&gt;
&lt;li&gt;Dropdowns&lt;/li&gt;
&lt;li&gt;Tooltips&lt;/li&gt;
&lt;li&gt;Popovers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Check portals
&lt;/h2&gt;

&lt;p&gt;React portals often render outside expected DOM hierarchy.&lt;/p&gt;

&lt;p&gt;This changes how CSS behaves.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Best Practices
&lt;/h1&gt;

&lt;p&gt;✅ Prefer class selectors over IDs&lt;/p&gt;

&lt;p&gt;✅ Avoid deeply nested selectors&lt;/p&gt;

&lt;p&gt;✅ Use low-specificity CSS in shared libraries&lt;/p&gt;

&lt;p&gt;✅ Use &lt;code&gt;:where()&lt;/code&gt; for easily overridable styles&lt;/p&gt;

&lt;p&gt;✅ Be careful with global CSS in microfrontends&lt;/p&gt;

&lt;p&gt;✅ Avoid excessive &lt;code&gt;!important&lt;/code&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Most developers think CSS specificity is a beginner topic.&lt;/p&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's one of the most common reasons production UIs break unexpectedly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Especially in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large applications&lt;/li&gt;
&lt;li&gt;Design systems&lt;/li&gt;
&lt;li&gt;Microfrontends&lt;/li&gt;
&lt;li&gt;Shared component libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tricky part is that the CSS often looks correct.&lt;/p&gt;

&lt;p&gt;The rule exists.&lt;/p&gt;

&lt;p&gt;The value is correct.&lt;/p&gt;

&lt;p&gt;And yet another selector silently wins.&lt;/p&gt;

&lt;p&gt;Understanding specificity deeply transforms CSS debugging from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trial and Error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Predictable Engineering
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;CSS does not simply apply the last rule&lt;/li&gt;
&lt;li&gt;Specificity determines which selector wins&lt;/li&gt;
&lt;li&gt;Higher z-index does not always mean higher visibility&lt;/li&gt;
&lt;li&gt;Microfrontends make specificity issues more common&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:is()&lt;/code&gt;, &lt;code&gt;:not()&lt;/code&gt;, and &lt;code&gt;:where()&lt;/code&gt; have special specificity behavior&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!important&lt;/code&gt; should be a last resort&lt;/li&gt;
&lt;li&gt;DevTools can quickly reveal specificity conflicts when used correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding CSS specificity is one of those skills that feels minor — until it saves you hours of debugging a production UI issue.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>webdev</category>
      <category>css</category>
      <category>learning</category>
    </item>
    <item>
      <title>API Pagination - Offset vs Cursor Pagination Explained</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sat, 16 May 2026 10:42:41 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/api-pagination-offset-vs-cursor-pagination-explained-2bb5</link>
      <guid>https://dev.to/fazal_mansuri_/api-pagination-offset-vs-cursor-pagination-explained-2bb5</guid>
      <description>&lt;p&gt;Most APIs don’t return all records at once.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Millions of users&lt;/li&gt;
&lt;li&gt;Thousands of orders&lt;/li&gt;
&lt;li&gt;Endless social media posts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Returning everything in a single response would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consume huge memory&lt;/li&gt;
&lt;li&gt;Slow down queries&lt;/li&gt;
&lt;li&gt;Increase network payload&lt;/li&gt;
&lt;li&gt;Crash clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why APIs use:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pagination&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But here’s where many developers make mistakes:&lt;/p&gt;

&lt;p&gt;Not all pagination strategies are equal.&lt;/p&gt;

&lt;p&gt;The two most common approaches are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offset Pagination&lt;/li&gt;
&lt;li&gt;Cursor Pagination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And choosing the wrong one can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow APIs&lt;/li&gt;
&lt;li&gt;Duplicate records&lt;/li&gt;
&lt;li&gt;Missing data&lt;/li&gt;
&lt;li&gt;Poor user experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s understand everything properly.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 What is Pagination?
&lt;/h1&gt;

&lt;p&gt;Pagination means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Splitting large datasets into smaller chunks (pages).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?page=1&amp;amp;limit=10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This improves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;User experience&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📦 Offset Pagination
&lt;/h1&gt;

&lt;p&gt;Offset pagination is the most common approach.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?offset=20&amp;amp;limit=10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skip first 20 rows&lt;/li&gt;
&lt;li&gt;Return next 10 rows&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚙️ SQL Behind It
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Simple Go Example - Offset Pagination
&lt;/h1&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&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;Post&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;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&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="n"&gt;i&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;100&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Post "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&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="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="n"&gt;getPosts&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;query&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;URL&lt;/span&gt;&lt;span class="o"&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;offset&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&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="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;limit&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&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="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"limit"&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;limit&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;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;&amp;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;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;offset&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;posts&lt;/span&gt;&lt;span class="p"&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;end&lt;/span&gt; &lt;span class="o"&gt;&amp;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;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;end&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;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;end&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;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;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;"/posts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getPosts&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server running on http://localhost:8080"&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;Fatal&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="no"&gt;nil&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;h1&gt;
  
  
  ▶️ Run It
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run offset-pagination.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  📡 API Call
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"http://localhost:8080/posts?offset=20&amp;amp;limit=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  📦 Response
&lt;/h1&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 21"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 22"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 23"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 24"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 25"&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;h1&gt;
  
  
  ✅ Advantages of Offset Pagination
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Simple to implement&lt;/li&gt;
&lt;li&gt;Easy to understand&lt;/li&gt;
&lt;li&gt;Supports random page access&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?page=50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ❌ Problems with Offset Pagination
&lt;/h1&gt;

&lt;p&gt;This is where things become interesting.&lt;/p&gt;

&lt;h1&gt;
  
  
  ⚠️ Problem 1 — Slow Queries at Scale
&lt;/h1&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Database still scans and skips 1 million rows.&lt;/p&gt;

&lt;p&gt;💥 Very expensive.&lt;/p&gt;

&lt;h1&gt;
  
  
  ⚠️ Problem 2 — Duplicate / Missing Records
&lt;/h1&gt;

&lt;p&gt;Suppose user loads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meanwhile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New rows inserted&lt;/li&gt;
&lt;li&gt;Old rows deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now user loads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate rows&lt;/li&gt;
&lt;li&gt;Missing rows&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  📉 Visual Problem
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before:

1 2 3 4 5 6 7 8 9 10

User fetches:
OFFSET 0 LIMIT 5

Gets:
1 2 3 4 5

Now new record inserted at top:

0 1 2 3 4 5 6 7 8 9 10

User fetches:
OFFSET 5 LIMIT 5

Gets:
5 6 7 8 9

⚠️ Duplicate "5"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 Cursor Pagination
&lt;/h1&gt;

&lt;p&gt;Cursor pagination solves these problems.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skipping rows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give records AFTER this specific item.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?cursor=20&amp;amp;limit=10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give next 10 posts after ID 20&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚙️ SQL Behind It
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&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;p&gt;Database uses index efficiently.&lt;/p&gt;




&lt;h1&gt;
  
  
  Simple Go Example — Cursor Pagination
&lt;/h1&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&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;Post&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;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&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="n"&gt;i&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;100&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Post "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&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="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="n"&gt;getPosts&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;query&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;URL&lt;/span&gt;&lt;span class="o"&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;cursor&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&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="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cursor"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;limit&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&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="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"limit"&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;limit&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;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;posts&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;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&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;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&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="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;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;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;"/posts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getPosts&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server running on http://localhost:8080"&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;Fatal&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="no"&gt;nil&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;h1&gt;
  
  
  ▶️ Run It
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run cursor-pagination.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  📡 API Call
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"http://localhost:8080/posts?cursor=10&amp;amp;limit=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  📦 Response
&lt;/h1&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 11"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 12"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 13"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 14"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 15"&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;h1&gt;
  
  
  ✅ Advantages of Cursor Pagination
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Fast for large datasets&lt;/li&gt;
&lt;li&gt;Uses indexes efficiently&lt;/li&gt;
&lt;li&gt;No duplicate/missing rows issue&lt;/li&gt;
&lt;li&gt;Better for real-time systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚠️ Trade-Offs of Cursor Pagination
&lt;/h1&gt;

&lt;p&gt;Not perfect either.&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ No Random Page Access
&lt;/h2&gt;

&lt;p&gt;You cannot easily jump to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need sequential navigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ More Complex Implementation
&lt;/h2&gt;

&lt;p&gt;Need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stable sorting&lt;/li&gt;
&lt;li&gt;Unique cursor&lt;/li&gt;
&lt;li&gt;Cursor encoding sometimes&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧠 What Companies Usually Do
&lt;/h1&gt;




&lt;h2&gt;
  
  
  🟢 Offset Pagination
&lt;/h2&gt;

&lt;p&gt;Used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin panels&lt;/li&gt;
&lt;li&gt;Internal dashboards&lt;/li&gt;
&lt;li&gt;Small datasets&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🟣 Cursor Pagination
&lt;/h2&gt;

&lt;p&gt;Used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Social media feeds&lt;/li&gt;
&lt;li&gt;Infinite scroll&lt;/li&gt;
&lt;li&gt;Messaging apps&lt;/li&gt;
&lt;li&gt;Large-scale APIs&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔥 Real-World Example
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Instagram / Twitter Feed
&lt;/h2&gt;

&lt;p&gt;Do you think they use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;5000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❌ No chance.&lt;/p&gt;

&lt;p&gt;They use cursor-based pagination.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚡ Performance Difference
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Offset Pagination
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DB scans huge rows ❌&lt;/p&gt;




&lt;h2&gt;
  
  
  Cursor Pagination
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Direct index lookup ✅&lt;/p&gt;




&lt;h1&gt;
  
  
  🔐 Important Cursor Pagination Rule
&lt;/h1&gt;

&lt;p&gt;Cursor field must be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Indexed&lt;/li&gt;
&lt;li&gt;Unique&lt;/li&gt;
&lt;li&gt;Stable&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;ID&lt;/li&gt;
&lt;li&gt;Created timestamp&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚠️ Common Developer Mistakes
&lt;/h1&gt;

&lt;h3&gt;
  
  
  ❌ Using OFFSET for infinite scroll
&lt;/h3&gt;

&lt;p&gt;Bad at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Cursor based on non-unique column
&lt;/h3&gt;

&lt;p&gt;Can create duplicates.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Forgetting stable ordering
&lt;/h3&gt;

&lt;p&gt;Pagination becomes inconsistent.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 Key Mental Model
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Offset Pagination
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Skip N rows”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cursor Pagination
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Continue after this row”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  📊 Quick Comparison
&lt;/h1&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;Offset Pagination&lt;/th&gt;
&lt;th&gt;Cursor Pagination&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Easy implementation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random page access&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large dataset performance&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infinite scroll&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate/missing record safety&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  🏁 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Pagination seems simple.&lt;/p&gt;

&lt;p&gt;But poor pagination strategy can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow down APIs&lt;/li&gt;
&lt;li&gt;Break user experience&lt;/li&gt;
&lt;li&gt;Create inconsistent data&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🎯 Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Offset pagination is simple but doesn’t scale well&lt;/li&gt;
&lt;li&gt;Cursor pagination is efficient and production-friendly&lt;/li&gt;
&lt;li&gt;Infinite scroll systems should prefer cursor pagination&lt;/li&gt;
&lt;li&gt;Always use indexed &amp;amp; stable cursor fields&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Good API design is not just about returning data.&lt;/p&gt;

&lt;p&gt;It’s about returning data efficiently — even at massive scale.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>api</category>
      <category>softwaredevelopment</category>
      <category>performance</category>
    </item>
    <item>
      <title>GraphQL vs REST - Which One Should You Really Use?</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sun, 26 Apr 2026 07:04:52 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/graphql-vs-rest-which-one-should-you-really-use-2na0</link>
      <guid>https://dev.to/fazal_mansuri_/graphql-vs-rest-which-one-should-you-really-use-2na0</guid>
      <description>&lt;p&gt;For years, REST APIs have been the standard.&lt;/p&gt;

&lt;p&gt;Then GraphQL came in with promises like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Fetch exactly what you need”&lt;/li&gt;
&lt;li&gt;“Reduce API calls”&lt;/li&gt;
&lt;li&gt;“More flexible APIs”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here’s the reality:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GraphQL is not a replacement for REST.&lt;br&gt;
It’s a different trade-off.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s break it down — with &lt;strong&gt;real code you can run&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 What is REST?
&lt;/h1&gt;

&lt;p&gt;REST is a resource-based API design.&lt;/p&gt;

&lt;p&gt;You expose endpoints like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users/1
GET /users/1/orders
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each endpoint returns &lt;strong&gt;fixed structure data&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ REST API — Fully Working Go Example
&lt;/h1&gt;

&lt;p&gt;👉 Save as &lt;code&gt;rest.go&lt;/code&gt;&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&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;type&lt;/span&gt; &lt;span class="n"&gt;User&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;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&lt;/span&gt;
    &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"email"`&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;getUserHandler&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;user&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&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;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&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;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&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;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;"/users/1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getUserHandler&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"REST server running on http://localhost:8080"&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;Fatal&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="no"&gt;nil&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;
  
  
  ▶️ Run it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run rest.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📡 Call API
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/users/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📦 Response
&lt;/h3&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.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;h1&gt;
  
  
  🧠 What is GraphQL?
&lt;/h1&gt;

&lt;p&gt;GraphQL is a &lt;strong&gt;query-based API system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of multiple endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You use a &lt;strong&gt;single endpoint&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Client decides what data it needs&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚙️ GraphQL API — Fully Working Go Example
&lt;/h1&gt;

&lt;p&gt;👉 Save as &lt;code&gt;graphql.go&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install dependency
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init graphql-example
go get github.com/graphql-go/graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Full working code
&lt;/h3&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/graphql-go/graphql"&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;User&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;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&lt;/span&gt;
    &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"email"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&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;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"john@example.com"&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="c"&gt;// Define User type&lt;/span&gt;
    &lt;span class="n"&gt;userType&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectConfig&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="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Fields&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fields&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;graphql&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="p"&gt;},&lt;/span&gt;
            &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;graphql&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="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// Root query&lt;/span&gt;
    &lt;span class="n"&gt;rootQuery&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectConfig&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="s"&gt;"Query"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Fields&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fields&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="o"&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;p&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResolveParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="kt"&gt;error&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;userData&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="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;schema&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;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemaConfig&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="n"&gt;rootQuery&lt;/span&gt;&lt;span class="p"&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;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;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// GraphQL handler&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;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/graphql"&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;params&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;Query&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"query"`&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&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;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;params&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 request body"&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;StatusBadRequest&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;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Params&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;RequestString&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&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;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GraphQL server running on http://localhost:8080/graphql"&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;Fatal&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="no"&gt;nil&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;
  
  
  ▶️ Run it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run graphql.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📡 Call API
&lt;/h3&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; POST http://localhost:8080/graphql &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"query": "{ user { name email } }"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📦 Response
&lt;/h3&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;"data"&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="nl"&gt;"user"&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="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.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;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;h1&gt;
  
  
  REST vs GraphQL — Visual Understanding
&lt;/h1&gt;

&lt;h2&gt;
  
  
  REST Flow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  |
  |---- GET /users/1 ----------&amp;gt; Server
  |---- GET /users/1/orders ---&amp;gt; Server
  |---- GET /orders/101/items -&amp;gt; Server

Multiple requests ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  GraphQL Flow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="err"&gt;Client&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;|----&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/graphql&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;---------&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="k"&gt;query&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="n"&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="n"&gt;orders&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="n"&gt;items&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;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;Single&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;✅&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ⚠️ The Real Problem GraphQL Solves
&lt;/h1&gt;

&lt;h2&gt;
  
  
  REST Problem → Over-fetching
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users/1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;phone&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if you need only &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  REST Problem → Under-fetching
&lt;/h2&gt;

&lt;p&gt;You need multiple calls to build UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  GraphQL Solution
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&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="n"&gt;name&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;p&gt;👉 Exact data only.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚖️ REST vs GraphQL — Honest Comparison
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🧩 REST
&lt;/h2&gt;

&lt;p&gt;✅ Simple&lt;br&gt;
✅ Easy caching&lt;br&gt;
✅ Easy debugging&lt;br&gt;
❌ Multiple calls&lt;br&gt;
❌ Over-fetching&lt;/p&gt;


&lt;h2&gt;
  
  
  🧩 GraphQL
&lt;/h2&gt;

&lt;p&gt;✅ Flexible&lt;br&gt;
✅ Single request&lt;br&gt;
❌ Complex&lt;br&gt;
❌ Hard caching&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: REST uses native HTTP caching (like CDNs and browser headers), while GraphQL requires complex, custom caching strategies because queries are typically sent via POST.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;❌ Query abuse risk&lt;/p&gt;


&lt;h1&gt;
  
  
  ⚠️ Common Mistakes
&lt;/h1&gt;
&lt;h3&gt;
  
  
  ❌ “GraphQL is always better”
&lt;/h3&gt;

&lt;p&gt;No.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Using GraphQL for simple CRUD
&lt;/h3&gt;

&lt;p&gt;Overkill.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Ignoring query complexity
&lt;/h3&gt;

&lt;p&gt;Bad query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users → posts → comments → replies → ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💥 Performance issue&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 When to Use What
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ✅ Use REST when:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simple APIs&lt;/li&gt;
&lt;li&gt;CRUD operations&lt;/li&gt;
&lt;li&gt;Strong caching needed&lt;/li&gt;
&lt;li&gt;Easy debugging required&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Use GraphQL when:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Complex frontend&lt;/li&gt;
&lt;li&gt;Aggregated data&lt;/li&gt;
&lt;li&gt;Multiple services&lt;/li&gt;
&lt;li&gt;Frequent UI changes&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔗 Real-World Architecture
&lt;/h1&gt;

&lt;p&gt;Many companies use the GraphQL Gateway (or BFF) pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend → GraphQL Gateway → REST microservices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 GraphQL acts as an aggregation layer, allowing you to combine multiple REST responses into one, without refactoring the legacy backend.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏁 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;GraphQL vs REST is not a battle.&lt;/p&gt;

&lt;p&gt;It’s a &lt;strong&gt;design decision&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🎯 Key Takeaways:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;REST = simple and predictable&lt;/li&gt;
&lt;li&gt;GraphQL = flexible but complex&lt;/li&gt;
&lt;li&gt;Both solve real problems&lt;/li&gt;
&lt;li&gt;Choose based on use-case&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🚀 Final Tip
&lt;/h1&gt;

&lt;p&gt;If your API:&lt;/p&gt;

&lt;p&gt;👉 Is simple → use REST&lt;br&gt;
👉 Needs flexibility → use GraphQL&lt;/p&gt;

</description>
      <category>backend</category>
      <category>programming</category>
      <category>api</category>
      <category>learning</category>
    </item>
    <item>
      <title>⚠️ Race Conditions in APIs - The Bug You Can’t See</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sat, 18 Apr 2026 09:02:13 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/race-conditions-in-apis-the-bug-you-cant-see-5c0h</link>
      <guid>https://dev.to/fazal_mansuri_/race-conditions-in-apis-the-bug-you-cant-see-5c0h</guid>
      <description>&lt;p&gt;There's a category of bugs that don't show up in tests. They don't throw errors. They don't crash your server. They just silently corrupt your data at the exact moment two users do the same thing at the same time.&lt;/p&gt;

&lt;p&gt;That's a race condition.&lt;/p&gt;

&lt;p&gt;And if you've ever seen a user's account balance go wrong, a product's stock count go negative, or a post get double-liked - you've seen one in production.&lt;/p&gt;

&lt;p&gt;Let's break down exactly what's happening and how to fix it.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Is a Race Condition?
&lt;/h3&gt;

&lt;p&gt;A race condition happens when two concurrent operations read shared data, make a decision based on it, and write back — and neither knows the other exists.&lt;/p&gt;

&lt;p&gt;The classic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread A reads stock = 10
Thread B reads stock = 10
Thread A writes stock = 9  (decremented by 1)
Thread B writes stock = 9  (also decremented from 10 — wrong!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two orders placed. One decrement applied. You just oversold your inventory.&lt;/p&gt;

&lt;p&gt;The reason this is invisible: each individual operation is correct. Thread A did nothing wrong. Thread B did nothing wrong. The bug lives in the &lt;em&gt;gap between the read and the write&lt;/em&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  A Real Scenario: The Inventory API
&lt;/h3&gt;

&lt;p&gt;Say you have an endpoint that handles a purchase:&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="c"&gt;// ❌ NOT safe under concurrent load&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;purchaseItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&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;itemID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="kt"&gt;int&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SELECT stock FROM items WHERE id = $1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;stock&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&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;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"out of stock"&lt;/span&gt;&lt;span class="p"&gt;)&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UPDATE items SET stock = $1 WHERE id = $2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="o"&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;itemID&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;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks fine. In a single-user world, it is fine. But under load — say, a flash sale with 500 concurrent requests — the gap between &lt;code&gt;SELECT&lt;/code&gt; and &lt;code&gt;UPDATE&lt;/code&gt; is enough for dozens of threads to read the same stock value and all decrement from it simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Negative stock. Oversold orders. Angry customers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Three Ways to Fix It
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Fix 1 — Atomic SQL Update (the simplest approach)
&lt;/h4&gt;

&lt;p&gt;The fastest fix is to eliminate the read-then-write pattern entirely and let the database handle the decrement atomically:&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="c"&gt;// ✅ Safe — single atomic statement&lt;/span&gt;
&lt;span class="n"&gt;result&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`
    UPDATE items
    SET stock = stock - 1
    WHERE id = $1 AND stock &amp;gt; 0
`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;rowsAffected&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RowsAffected&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;rowsAffected&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"out of stock or already taken"&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;No read. No gap. The database engine serializes this at the row level. This works well for simple decrements and is the right default when you don't need the old value.&lt;/p&gt;




&lt;h4&gt;
  
  
  Fix 2 — Pessimistic Locking (SELECT FOR UPDATE)
&lt;/h4&gt;

&lt;p&gt;When you genuinely need to read the value before deciding what to write — for example, checking business rules before an update — use &lt;code&gt;SELECT FOR UPDATE&lt;/code&gt; to hold a row lock:&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="c"&gt;// ✅ Safe — row is locked until transaction commits&lt;/span&gt;
&lt;span class="n"&gt;tx&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BeginTx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="c"&gt;// error handling omitted for brevity&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rollback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="kt"&gt;int&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;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`
    SELECT stock FROM items WHERE id = $1 FOR UPDATE
`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;stock&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;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"out of stock"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UPDATE items SET stock = $1 WHERE id = $2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="o"&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;itemID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;FOR UPDATE&lt;/code&gt; tells the database: lock this row. Any other transaction that tries to read it with &lt;code&gt;FOR UPDATE&lt;/code&gt; will block until this one commits or rolls back. Completely safe — but it creates a queue, so it can become a bottleneck under heavy concurrent traffic.&lt;/p&gt;




&lt;h4&gt;
  
  
  Fix 3 — Optimistic Locking with CAS (Compare-And-Swap)
&lt;/h4&gt;

&lt;p&gt;Optimistic locking says: don't block anyone. Just verify before writing that the world still looks the way you expected when you read it.&lt;/p&gt;

&lt;p&gt;You add a &lt;code&gt;version&lt;/code&gt; column to the row, then make your update conditional:&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="c"&gt;// ✅ Safe — version mismatch causes retry, not corruption&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Item&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;ID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Stock&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Version&lt;/span&gt; &lt;span class="kt"&gt;int&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;purchaseWithCAS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&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;itemID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&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;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SELECT id, stock, version FROM items WHERE id = $1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&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;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stock&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"out of stock"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;result&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`
            UPDATE items
            SET stock = $1, version = $2
            WHERE id = $3 AND version = $4
        `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stock&lt;/span&gt;&lt;span class="o"&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;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="o"&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;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;rows&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RowsAffected&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;rows&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&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="c"&gt;// success&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// version mismatch — someone else wrote first, retry&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"too many concurrent modifications, try again"&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;If two threads both read &lt;code&gt;version=5&lt;/code&gt;, only the first one that writes &lt;code&gt;version=6&lt;/code&gt; wins. The second sees &lt;code&gt;rowsAffected=0&lt;/code&gt; and retries with a fresh read. No locks held, no blocking — just retry on conflict.&lt;/p&gt;




&lt;h3&gt;
  
  
  When to Use Which Fix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Best approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple increment/decrement&lt;/td&gt;
&lt;td&gt;Atomic SQL (&lt;code&gt;UPDATE ... SET x = x - 1&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex business logic before write&lt;/td&gt;
&lt;td&gt;Pessimistic locking (&lt;code&gt;SELECT FOR UPDATE&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-read, low-conflict workloads&lt;/td&gt;
&lt;td&gt;Optimistic locking (CAS + version)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distributed systems / no shared DB&lt;/td&gt;
&lt;td&gt;Distributed locks (Redis &lt;code&gt;SET NX&lt;/code&gt;, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  The Distributed Case: Redis to the Rescue
&lt;/h3&gt;

&lt;p&gt;When your API runs across multiple servers and the database lock isn't enough (or too slow), you need a distributed lock. Redis handles this elegantly:&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="c"&gt;// ✅ Distributed lock using Redis SET NX (set if not exists)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;acquireLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&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;rdb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&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="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ok&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;rdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetNX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"lock:"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&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;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;releaseLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&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;rdb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"lock:"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;key&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;purchaseWithRedisLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&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;rdb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;acquired&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;acquireLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&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;Second&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;acquired&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not acquire lock, try again"&lt;/span&gt;&lt;span class="p"&gt;)&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;releaseLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// safe to read and write now — only one server can be here at a time&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;purchaseItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itemID&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;SET NX&lt;/code&gt; command is atomic in Redis — only one caller gets &lt;code&gt;true&lt;/code&gt;. All others get &lt;code&gt;false&lt;/code&gt; and back off. The TTL ensures the lock is released even if your server crashes mid-operation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ One important caveat: &lt;code&gt;SET NX&lt;/code&gt; alone isn't enough for production. Use &lt;strong&gt;Redlock&lt;/strong&gt; (Redis's official distributed locking algorithm) when you need strong guarantees — especially if you have multiple Redis nodes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Summary: The Mental Model
&lt;/h3&gt;

&lt;p&gt;Race conditions happen in the gap between &lt;strong&gt;read&lt;/strong&gt; and &lt;strong&gt;write&lt;/strong&gt;. The longer that gap, the higher the chance of corruption. Your goal is to shrink or eliminate that gap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomic operations&lt;/strong&gt; collapse the gap to zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pessimistic locks&lt;/strong&gt; block others from entering the gap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic locks&lt;/strong&gt; let everyone in but detect and reject stale writes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no universally best answer. Pick the approach that matches your read/write ratio, your tolerance for blocking, and whether your system is distributed.&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A race condition is not a bug in any single thread — it's a bug in &lt;em&gt;timing&lt;/em&gt; between threads.&lt;/li&gt;
&lt;li&gt;Any "read, decide, write" pattern is vulnerable unless protected.&lt;/li&gt;
&lt;li&gt;The simplest fix is often a single atomic SQL statement — reach for it first.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SELECT FOR UPDATE&lt;/code&gt; is your safety net when you need business logic between the read and write.&lt;/li&gt;
&lt;li&gt;Optimistic locking with a version column is ideal for high-concurrency, low-conflict scenarios.&lt;/li&gt;
&lt;li&gt;In distributed systems, move to Redis-based locking.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Have you been bitten by a race condition in production? How did you track it down? Drop a comment - these bugs have some of the best war stories.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>backend</category>
      <category>database</category>
      <category>api</category>
      <category>security</category>
    </item>
    <item>
      <title>🚀 Feature Flags - The Secret Behind Safe Deployments</title>
      <dc:creator>Fazal Mansuri</dc:creator>
      <pubDate>Sun, 15 Mar 2026 07:49:04 +0000</pubDate>
      <link>https://dev.to/fazal_mansuri_/feature-flags-the-secret-behind-safe-deployments-4ine</link>
      <guid>https://dev.to/fazal_mansuri_/feature-flags-the-secret-behind-safe-deployments-4ine</guid>
      <description>&lt;p&gt;Shipping software used to be risky.&lt;/p&gt;

&lt;p&gt;A new deployment could introduce bugs, break critical workflows or affect thousands (or millions) of users instantly.&lt;/p&gt;

&lt;p&gt;For many teams, releasing software meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying late at night 🌙&lt;/li&gt;
&lt;li&gt;Monitoring dashboards anxiously 📊&lt;/li&gt;
&lt;li&gt;Hoping nothing breaks 🤞&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern engineering teams solved this problem using &lt;strong&gt;Feature Flags&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Feature flags allow developers to &lt;strong&gt;release code without immediately exposing new features to users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of deploying and hoping everything works, teams can &lt;strong&gt;control feature visibility dynamically&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 What Are Feature Flags?
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;Feature Flag&lt;/strong&gt; (also called a &lt;strong&gt;Feature Toggle&lt;/strong&gt;) is a mechanism that &lt;strong&gt;enables or disables functionality in an application without deploying new code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In simple terms:&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;if&lt;/span&gt; &lt;span class="n"&gt;feature_flag_enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;show_new_feature&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="nf"&gt;use_old_behavior&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application contains &lt;strong&gt;both code paths&lt;/strong&gt;, but the &lt;strong&gt;feature flag decides which one runs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This allows developers to &lt;strong&gt;separate deployment from release&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key idea:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt; → Shipping code to production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Release&lt;/strong&gt; → Making the feature available to users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feature flags allow these two processes to happen &lt;strong&gt;independently&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%2F6xz6apnge29zrt51mbp8.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%2F6xz6apnge29zrt51mbp8.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Why Feature Flags Matter
&lt;/h1&gt;

&lt;p&gt;Feature flags dramatically reduce the &lt;strong&gt;risk of releasing software&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Without Feature Flags
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deploy → Feature immediately live
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something breaks, the only option is &lt;strong&gt;rollback&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  With Feature Flags
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deploy → Feature disabled → Enable gradually
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something goes wrong, simply &lt;strong&gt;turn the feature off&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No redeployment required.&lt;/p&gt;




&lt;h3&gt;
  
  
  Benefits of Feature Flags
&lt;/h3&gt;

&lt;p&gt;Feature flags enable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Safer releases&lt;/li&gt;
&lt;li&gt;✅ Gradual rollouts&lt;/li&gt;
&lt;li&gt;✅ Instant rollback&lt;/li&gt;
&lt;li&gt;✅ Production testing&lt;/li&gt;
&lt;li&gt;✅ Controlled experiments&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🛒 Real-World Example
&lt;/h1&gt;

&lt;p&gt;Imagine launching a &lt;strong&gt;new checkout system&lt;/strong&gt; for an e-commerce platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Without Feature Flags
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deploy new checkout → All users see it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If checkout fails → &lt;strong&gt;Revenue stops immediately&lt;/strong&gt; 💥&lt;/p&gt;




&lt;h3&gt;
  
  
  With Feature Flags
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deploy new checkout → Feature disabled
Enable for 5% users
Monitor metrics
Gradually increase rollout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If problems appear, the feature can be &lt;strong&gt;disabled instantly&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 Types of Feature Flags
&lt;/h1&gt;

&lt;p&gt;Not all feature flags are used for the same purpose.&lt;/p&gt;

&lt;p&gt;Understanding their types helps design systems properly.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣ Release Flags
&lt;/h1&gt;

&lt;p&gt;Used to &lt;strong&gt;gradually release new features&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new_checkout_enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Control feature rollout&lt;/li&gt;
&lt;li&gt;Reduce release risk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Release flags are usually &lt;strong&gt;temporary&lt;/strong&gt; and removed once the feature is stable.&lt;/p&gt;




&lt;h1&gt;
  
  
  2️⃣ Experiment Flags (A/B Testing)
&lt;/h1&gt;

&lt;p&gt;Used for &lt;strong&gt;product experiments&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checkout_variant_A
checkout_variant_B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users may see different versions of a feature.&lt;/p&gt;

&lt;p&gt;Metrics measured include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📈 Conversion rate&lt;/li&gt;
&lt;li&gt;📊 Engagement&lt;/li&gt;
&lt;li&gt;🔁 Retention&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  3️⃣ Operational Flags
&lt;/h1&gt;

&lt;p&gt;Used to &lt;strong&gt;control system behavior during incidents&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;disable_recommendation_engine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a system starts failing, the feature can be &lt;strong&gt;disabled instantly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Operational flags are useful during &lt;strong&gt;production outages&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  4️⃣ Permission Flags
&lt;/h1&gt;

&lt;p&gt;Used to &lt;strong&gt;control access based on user roles&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;admin_dashboard_enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only certain users or roles see the feature.&lt;/p&gt;

&lt;p&gt;This is commonly used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;internal tools&lt;/li&gt;
&lt;li&gt;beta programs&lt;/li&gt;
&lt;li&gt;admin dashboards&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚙️ Feature Flags vs Configuration Flags
&lt;/h1&gt;

&lt;p&gt;These concepts are often confused.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature Flags
&lt;/h3&gt;

&lt;p&gt;Used to control &lt;strong&gt;product functionality&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temporary&lt;/li&gt;
&lt;li&gt;Used for rollouts&lt;/li&gt;
&lt;li&gt;Tied to releases&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;enable_new_upload_ui&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Configuration Flags
&lt;/h3&gt;

&lt;p&gt;Used to control &lt;strong&gt;system configuration&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usually permanent&lt;/li&gt;
&lt;li&gt;Not tied to releases&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;max_upload_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;20MB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding this difference prevents &lt;strong&gt;misuse of feature flags&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧪 Simple Implementation Example (Go)
&lt;/h1&gt;

&lt;p&gt;Here is a simple feature flag example in Go:&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;FeatureFlags&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;NewCheckout&lt;/span&gt; &lt;span class="kt"&gt;bool&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;Checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="n"&gt;FeatureFlags&lt;/span&gt;&lt;span class="p"&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;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCheckout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;newCheckoutFlow&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;oldCheckoutFlow&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;Feature flag values may come from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;configuration files&lt;/li&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;remote config services&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🌐 Remote Feature Flag Systems
&lt;/h1&gt;

&lt;p&gt;In production, feature flags are often managed &lt;strong&gt;remotely&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Popular platforms include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LaunchDarkly&lt;/li&gt;
&lt;li&gt;Split&lt;/li&gt;
&lt;li&gt;Flagsmith&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These systems allow teams to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;toggle features instantly ⚡&lt;/li&gt;
&lt;li&gt;target specific users 🎯&lt;/li&gt;
&lt;li&gt;monitor rollout metrics 📊&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No redeployment required.&lt;/p&gt;




&lt;h1&gt;
  
  
  📈 Gradual Rollouts
&lt;/h1&gt;

&lt;p&gt;One of the most powerful capabilities of feature flags is &lt;strong&gt;progressive rollout&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example rollout strategy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1% users → monitor
10% users → monitor
50% users → monitor
100% users → full release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This dramatically &lt;strong&gt;reduces release risk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Problems can be detected &lt;strong&gt;before the feature reaches everyone&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%2Fsiqdsjwleonnrr8uzsp2.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%2Fsiqdsjwleonnrr8uzsp2.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Targeted Rollouts
&lt;/h1&gt;

&lt;p&gt;Feature flags can also target &lt;strong&gt;specific user segments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;internal employees&lt;/li&gt;
&lt;li&gt;beta testers&lt;/li&gt;
&lt;li&gt;specific countries&lt;/li&gt;
&lt;li&gt;premium users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example logic:&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;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;enable_feature&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables &lt;strong&gt;testing directly in production environments&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🐤 Canary Releases
&lt;/h1&gt;

&lt;p&gt;Feature flags are commonly used with &lt;strong&gt;canary releases&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A canary release exposes a feature to a &lt;strong&gt;small subset of users first&lt;/strong&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;performance issues&lt;/li&gt;
&lt;li&gt;unexpected errors&lt;/li&gt;
&lt;li&gt;unusual user behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;before rolling it out globally.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌑 Dark Launching
&lt;/h1&gt;

&lt;p&gt;Another advanced technique is &lt;strong&gt;Dark Launching&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The feature is deployed but &lt;strong&gt;hidden from users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The system still runs the feature &lt;strong&gt;in the background&lt;/strong&gt; to test performance.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;recommendation_engine_running&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;recommendation_visible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps test infrastructure safely before exposing the feature.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ The Hidden Problem: Feature Flag Debt
&lt;/h1&gt;

&lt;p&gt;Feature flags are powerful, but they introduce a new problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature Flag Debt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Over time, many flags remain in the codebase long after the feature is released.&lt;/p&gt;

&lt;p&gt;Example:&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;if&lt;/span&gt; &lt;span class="n"&gt;old_feature_flag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the feature is already permanent.&lt;/p&gt;

&lt;p&gt;This leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;messy code&lt;/li&gt;
&lt;li&gt;confusion&lt;/li&gt;
&lt;li&gt;technical debt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flags should be &lt;strong&gt;removed once they are no longer needed&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚨 Common Mistakes With Feature Flags
&lt;/h1&gt;

&lt;p&gt;Many teams misuse feature flags.&lt;/p&gt;

&lt;p&gt;Here are common pitfalls.&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Flag Explosion
&lt;/h3&gt;

&lt;p&gt;Too many flags make systems difficult to understand.&lt;/p&gt;

&lt;p&gt;Every flag increases &lt;strong&gt;system complexity&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Flags in Performance-Critical Paths
&lt;/h3&gt;

&lt;p&gt;Checking flags in very hot paths may affect performance.&lt;/p&gt;

&lt;p&gt;Flag evaluation should be &lt;strong&gt;fast and lightweight&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3️⃣ Long-Lived Release Flags
&lt;/h3&gt;

&lt;p&gt;Release flags should be temporary.&lt;/p&gt;

&lt;p&gt;Once rollout finishes, remove them.&lt;/p&gt;

&lt;h3&gt;
  
  
  4️⃣ Mixing Flags With Business Logic
&lt;/h3&gt;

&lt;p&gt;Feature flags should control &lt;strong&gt;behavior&lt;/strong&gt;, not implement complex logic.&lt;/p&gt;

&lt;p&gt;Avoid deeply nested conditions like:&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;if&lt;/span&gt; &lt;span class="n"&gt;flagA&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;flagB&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;flagC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ✅ Best Practices
&lt;/h1&gt;

&lt;p&gt;Successful teams follow several important practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Treat Flags as Temporary
&lt;/h3&gt;

&lt;p&gt;Every release flag should have an &lt;strong&gt;expiration plan&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Track Flag Ownership
&lt;/h3&gt;

&lt;p&gt;Each flag should have an &lt;strong&gt;owner responsible for cleanup&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3️⃣ Monitor Feature Rollouts
&lt;/h3&gt;

&lt;p&gt;Always observe metrics when enabling a feature.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;error rate&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;user behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4️⃣ Use Clear Naming
&lt;/h3&gt;

&lt;p&gt;Bad naming:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flag123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better naming:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checkout_v2_release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clear names improve maintainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  5️⃣ Remove Flags After Release
&lt;/h3&gt;

&lt;p&gt;Cleaning up unused flags keeps the &lt;strong&gt;codebase healthy&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚡ Feature Flags Enable Modern DevOps
&lt;/h1&gt;

&lt;p&gt;Feature flags are a key component of &lt;strong&gt;modern engineering practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They enable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 Continuous deployment&lt;/li&gt;
&lt;li&gt;🧪 Safe experimentation&lt;/li&gt;
&lt;li&gt;🔄 Instant rollbacks&lt;/li&gt;
&lt;li&gt;🎯 Controlled feature releases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of fearing deployments, teams can &lt;strong&gt;release features with confidence&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏁 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Feature flags fundamentally change how software is delivered.&lt;/p&gt;

&lt;p&gt;They transform deployments from &lt;strong&gt;risky events into controlled experiments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But like any powerful tool, they must be used carefully.&lt;/p&gt;

&lt;p&gt;Without discipline, feature flags can create complexity and technical debt.&lt;/p&gt;

&lt;p&gt;When implemented correctly, they become &lt;strong&gt;one of the most powerful tools in a developer’s toolbox&lt;/strong&gt;.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
