<?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: Nguyễn Long</title>
    <description>The latest articles on DEV Community by Nguyễn Long (@2nguyenlong000k).</description>
    <link>https://dev.to/2nguyenlong000k</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1775762%2F6ae4e3c9-e493-4633-a77f-c83227ce2c1b.jpg</url>
      <title>DEV Community: Nguyễn Long</title>
      <link>https://dev.to/2nguyenlong000k</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/2nguyenlong000k"/>
    <language>en</language>
    <item>
      <title>From Polling to Partying: Writing Cooler Goroutines with sync.Cond</title>
      <dc:creator>Nguyễn Long</dc:creator>
      <pubDate>Thu, 26 Jun 2025 02:38:14 +0000</pubDate>
      <link>https://dev.to/2nguyenlong000k/from-polling-to-partying-writing-cooler-goroutines-with-synccond-1ld8</link>
      <guid>https://dev.to/2nguyenlong000k/from-polling-to-partying-writing-cooler-goroutines-with-synccond-1ld8</guid>
      <description>&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;Imagine a DJ show with hundreds of people waiting for their favorite track to drop. If everyone kept asking the DJ every millisecond:&lt;br&gt;
"Is it time to dance yet? Now?"&lt;br&gt;
You’d probably end up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sweaty DJ (over loaded)&lt;/li&gt;
&lt;li&gt;Burned speakers (crashing)&lt;/li&gt;
&lt;li&gt;And a power outage (aka a CPU meltdown)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s what &lt;strong&gt;polling&lt;/strong&gt; looks like in code.&lt;/p&gt;

&lt;p&gt;But what if the DJ had a mic and just said:&lt;br&gt;
"Hey! When the beat drops, I’ll tell you!"&lt;/p&gt;

&lt;p&gt;That’s &lt;strong&gt;&lt;code&gt;sync.Cond&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  So, What is &lt;code&gt;sync.Cond&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;Go’s &lt;code&gt;sync.Cond&lt;/code&gt; is a condition variable&lt;br&gt;
a concurrency primitive that lets goroutines sleep &lt;strong&gt;efficiently&lt;/strong&gt; while waiting for a condition to become true. It’s based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A shared &lt;strong&gt;mutex&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A condition-checking &lt;strong&gt;loop&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;And the ability to &lt;strong&gt;wait&lt;/strong&gt;, &lt;strong&gt;signal&lt;/strong&gt;, or &lt;strong&gt;broadcast&lt;/strong&gt; to other goroutines.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  You use it when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;There’s a &lt;strong&gt;shared resource&lt;/strong&gt; (like a connection pool or ticket list)&lt;/li&gt;
&lt;li&gt;Goroutines must &lt;strong&gt;wait&lt;/strong&gt; for that resource to become available&lt;/li&gt;
&lt;li&gt;You want to avoid &lt;strong&gt;polling&lt;/strong&gt; or wasting CPU&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take the example when you use Polling:&lt;/p&gt;

&lt;p&gt;Imagine you’re running a party where guests (goroutines) can only enter the dance floor when there’s space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for {
    if showReady {
        fmt.Println("💃 Fan starts dancing!")
        break
    }
    time.Sleep(100 * time.Millisecond)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They keep &lt;strong&gt;checking and sleeping&lt;/strong&gt;... That’s like asking the DJ every 100ms:&lt;/p&gt;

&lt;p&gt;"Hey, can I dance yet? What about now? How about now?!"&lt;br&gt;
That’s called &lt;strong&gt;polling&lt;/strong&gt;, and it’s inefficient and annoying (for both CPU and DJ).&lt;/p&gt;

&lt;p&gt;Enter: &lt;strong&gt;&lt;code&gt;sync.Cond&lt;/code&gt;&lt;/strong&gt; – a way to &lt;strong&gt;wait without burning CPU&lt;/strong&gt; until you're signaled to proceed.&lt;/p&gt;

&lt;p&gt;So let's take a look at this example first, then we will dig deeply into the mechanism:&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;var&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="n"&gt;cond&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCond&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;mu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;showReady&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="c"&gt;// Fan goroutine&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;showReady&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🧍 Fan waiting..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// unlocks, sleeps, then relocks&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"💃 Fan starts dancing!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="c"&gt;// DJ goroutine&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="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;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="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;showReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🎧 DJ: The beat drops!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// wakes up one fan&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example illutrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let fans "wait" until the event is ready -&amp;gt; stimulate for 3 seconds&lt;/li&gt;
&lt;li&gt;Notify waiting fans as soon as the DJ starts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Business Analogy
&lt;/h3&gt;

&lt;p&gt;This pattern models real business use cases like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Worker thread pools&lt;/strong&gt; waiting for jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order processors&lt;/strong&gt; waiting for payment confirmation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumers&lt;/strong&gt; waiting for items to appear in a queue&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background tasks&lt;/strong&gt; triggered by external events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our case:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The dance floor = the shared resource.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fan = goroutine that waits.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The DJ = the event trigger.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Now let's talk about the correct way to use this mechanism:
&lt;/h3&gt;

&lt;p&gt;This is the simple flow:&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;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;doWork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;like :&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;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;showReady&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🧍 Fan waiting..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// unlocks, sleeps, then relocks&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"💃 Fan starts dancing!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the flow will be depicted as bellow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[🔒 LOCKED]        G1 enters critical section
[❓ CHECK ]       Check condition Is showReady true? --&amp;gt;No.
[😴 WAIT ]        G1 goes to sleep → cond.Wait() waiting for other GR to wake it up! (meaning waiting for the beat drops)
[🔓 UNLOCKED]     Lock is released while waiting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another goroutine will signals:&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;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// or cond.Broadcast()&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's mean when the DJ drops the beat, game on...&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;go&lt;/span&gt; &lt;span class="k"&gt;func&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;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="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;showReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🎧 DJ: The beat drops!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// wakes up one fan&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[🔒 LOCKED]       G2 changes condition to true (start the show) 
[📣 SIGNAL]       G2 calls cond.Signal() (notify to the FAN)
[🔓 UNLOCKED]     Lock released 
&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 plaintext"&gt;&lt;code&gt;[👂 WOKEN UP]     G1 is notified, wakes up 
[🔒 LOCK AGAIN]   Tries to reacquire the mutex
[✅ RECHECK ]     Sees condition is now true
[🏃 PROCEED ]     Does work and exits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyivkchviqytvq5a19m5d.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%2Fyivkchviqytvq5a19m5d.png" alt="Image description" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The output looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;🧍 Fan waiting...
🎧 DJ: The beat drops!
💃 Fan starts dancing!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why not just &lt;code&gt;time.Sleep()&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;You could say: &lt;em&gt;"Why not just let the fan sleep for 3 seconds too?"&lt;/em&gt;&lt;br&gt;
Because in a real app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The DJ doesn’t follow a fixed schedule.&lt;/li&gt;
&lt;li&gt;There might be &lt;strong&gt;many fans&lt;/strong&gt;, not just one.&lt;/li&gt;
&lt;li&gt;The fan may give up waiting or be notified &lt;strong&gt;instantly&lt;/strong&gt; the moment music starts.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How Does &lt;code&gt;Wait()&lt;/code&gt; Actually Work?
&lt;/h2&gt;
&lt;h4&gt;
  
  
  Here’s the implementation under the hood:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Cond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                             &lt;span class="c"&gt;// panic if copied&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;runtime_notifyListAdd&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c"&gt;// get a wait ticket&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                                  &lt;span class="c"&gt;// release the mutex&lt;/span&gt;
    &lt;span class="n"&gt;runtime_notifyListWait&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c"&gt;// suspend goroutine&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                                    &lt;span class="c"&gt;// re-acquire lock on wake&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;

&lt;h3&gt;
  
  
  Key Takeaways:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;There’s a checker to prevent copying the &lt;code&gt;Cond&lt;/code&gt; instance, it would be panic if you do so -&amp;gt; anyway, we don't care abt it's detail&lt;/li&gt;
&lt;li&gt;Calling &lt;code&gt;cond.Wait()&lt;/code&gt; immediately unlocks the mutex -&amp;gt; mutex &lt;strong&gt;must be locked before we call cond.Wait()&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;After being notified, this method will lock the mutex again -&amp;gt; you need to unlock it after you done with shared data &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Signal vs Broadcast
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Signal()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wakes up &lt;strong&gt;1&lt;/strong&gt; goroutine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Broadcast()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wakes up &lt;strong&gt;all&lt;/strong&gt; waiting goroutines&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Polling based flow:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────┐       ┌────────────────────┐
│  Goroutine A │────→  │ tryGetConnection() │
└──────────────┘       └────────────────────┘
       │                         │
       ▼                         ▼
  [Not Available]         →   Sleep(100ms)
       │                         │
       └───── loop ──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Fan keeps knocking: “DJ, can I dance now? … How about now? … Still no?”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loop repeats wastefully&lt;/li&gt;
&lt;li&gt;Sleep is either too short (CPU burn) or too long (latency)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;code&gt;sync.Cond&lt;/code&gt; Flow (Efficient + Coordinated)
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   [ DJ thread ]
┌──────────────┐     time.Sleep
│ Goroutine B  │────────────────────┐
└──────────────┘                    │
        │                           ▼
        │                    ┌──────────────┐
        │                    │  showReady = true
        │                    │  cond.Signal()
        │                    └──────┬───────┘
        ▼                           │
┌────────────────────────────────┐  ▼
│   Goroutine A (waiting fan)    │◄─┘
│  mu.Lock()                     │
│  while !showReady {           ◄──────────────┐
│      cond.Wait() (sleep)                  │
│  }                                        │
│  // Proceed to dance 💃                   │
└────────────────────────────────┘

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

&lt;/div&gt;


&lt;p&gt;Fan enters the club, sits quietly. DJ announces:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“🎧 The beat drops!”&lt;br&gt;&lt;br&gt;
Fan wakes up instantly:&lt;br&gt;&lt;br&gt;
“💃 I’m dancing!”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Sleeps peacefully while waiting&lt;/li&gt;
&lt;li&gt; Wakes up only when ready&lt;/li&gt;
&lt;li&gt; CPU usage remains near-zero&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Don’t burn out your CPU (or your DJ). If you’re managing shared resources in Go and you’re still writing polling loops, it’s time to level up with &lt;code&gt;sync.Cond&lt;/code&gt;.&lt;br&gt;
This pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scales beautifully&lt;/li&gt;
&lt;li&gt;Imprves latency&lt;/li&gt;
&lt;li&gt;Gives you precise coordination&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  When Should You Reach for &lt;code&gt;sync.Cond&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Use it when&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a &lt;strong&gt;shared condition&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;And multiple goroutines &lt;strong&gt;wait&lt;/strong&gt; on it&lt;/li&gt;
&lt;li&gt;And that condition &lt;strong&gt;is protected by a mutex&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;And &lt;strong&gt;polling is not acceptable&lt;/strong&gt;
Don’t use it if:&lt;/li&gt;
&lt;li&gt;A simple &lt;code&gt;chan&lt;/code&gt; will do&lt;/li&gt;
&lt;li&gt;You don’t already hold a mutex around the state&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Bonus: real-world use case: connection pool
&lt;/h1&gt;
&lt;h5&gt;
  
  
  The Problem With Polling:
&lt;/h5&gt;

&lt;p&gt;Time a go I already have a nice tcp server implementation setup in golang.&lt;br&gt;
To implement this kind of custom tcp server, we need st called connection pool for maximize the power of machines, allow more concurrency operation.&lt;/p&gt;

&lt;p&gt;So the first implementation look like this: &lt;strong&gt;bad pattern&lt;/strong&gt; (but a common one):&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;for&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;conn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tryGetConnection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;conn&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;conn&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;100&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;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 👎 try polling&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happened next?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;CPU burned&lt;/strong&gt; — even when no connection was available&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Latency grew&lt;/strong&gt; — increase sleep = slower reaction, decrease sleep = higher CPU&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;1,000 goroutines polling = chaos&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Edge cases everywhere&lt;/strong&gt; — race conditions like being woken just before state changed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to &lt;code&gt;sync.Cond&lt;/code&gt; which perfectly resolve this problem:&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;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;hasFreeConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&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;acquireConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  What changed?
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;No more busy loops&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;CPU usage drops to near zero while waiting&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Only woken when it matters&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;No weird races or wasted wakeups&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Someone will ask me st like this:&lt;/p&gt;

&lt;h5&gt;
  
  
  Why not use channels instead?
&lt;/h5&gt;

&lt;p&gt;Well, to be honest, my 2nd try consider buffered channel of &lt;code&gt;net.Conn&lt;/code&gt; and it can resolve the problem.&lt;/p&gt;

&lt;h6&gt;
  
  
  and that works… until it doesn't.
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Channels are great for &lt;strong&gt;linear producers/consumers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;But don’t scale well to:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;broadcast wakeups&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shared state protected by mutex&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;non-linear wake patterns&lt;/strong&gt;
Channels are &lt;strong&gt;data pipes&lt;/strong&gt;.
&lt;code&gt;sync.Cond&lt;/code&gt; is a &lt;strong&gt;condition watcher&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of channels as a delivery guy.&lt;br&gt;&lt;br&gt;
Think of &lt;code&gt;sync.Cond&lt;/code&gt; as a waiter with a bell: &lt;em&gt;“Your table is ready!”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You have a &lt;code&gt;[]*ConnWrapper&lt;/code&gt;, and you want to hand out a free one. If none are free, you wait — &lt;em&gt;but you don’t burn the CPU&lt;/em&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;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;hasFreeConn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&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;grabFreeConn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;conn&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 connection is returned:&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;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;markConnFree&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;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could be scaling up to &lt;strong&gt;thousands of goroutines&lt;/strong&gt;, and CPU usage would still be flatlined at.&lt;/p&gt;

&lt;p&gt;Here's the full 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;type&lt;/span&gt; &lt;span class="n"&gt;ConnWrapper&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;conn&lt;/span&gt;  &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;
    &lt;span class="n"&gt;inUse&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;type&lt;/span&gt; &lt;span class="n"&gt;ConnectionPool&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;connections&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ConnWrapper&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;          &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
    &lt;span class="n"&gt;cond&lt;/span&gt;        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cond&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;NewConnectionPool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ConnectionPool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pool&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;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCond&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;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Initialize dummy connections (you can replace with real dials)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&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;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connections&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;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connections&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;ConnWrapper&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;conn&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;inUse&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pool&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;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;hasFreeConnection&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="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;cw&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;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connections&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;cw&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="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;acquireConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cw&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;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connections&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;cw&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;cw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inUse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cw&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="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="c"&gt;// GetConnection blocks until one is available&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetConnection&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&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;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFreeConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;waitCh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&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;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waitCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;

        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&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="o"&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;ctx&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="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;waitCh&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="c"&gt;// recheck in next loop&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&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;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;acquireConnection&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;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ReleaseConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cw&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;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connections&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;cw&lt;/span&gt;&lt;span class="o"&gt;.&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;conn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inUse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&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="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Wake up one goroutine waiting&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go Official Documentation – &lt;code&gt;sync.Cond&lt;/code&gt;&lt;/strong&gt;
&lt;a href="https://pkg.go.dev/sync#Cond" rel="noopener noreferrer"&gt;https://pkg.go.dev/sync#Cond&lt;/a&gt;
&lt;em&gt;The authoritative source explaining how &lt;code&gt;Cond&lt;/code&gt; works and how to use it properly.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Blog – Share Memory by Communicating&lt;/strong&gt;
&lt;a href="https://go.dev/blog/share-memory-by-communicating" rel="noopener noreferrer"&gt;https://go.dev/blog/share-memory-by-communicating&lt;/a&gt;
&lt;em&gt;Go’s philosophy on concurrency. Although &lt;code&gt;sync.Cond&lt;/code&gt; is a shared-memory primitive, this blog explains when it’s okay to step outside channels.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Practical Go Concurrency Patterns" – Google I/O talk&lt;/strong&gt;
&lt;a href="https://www.youtube.com/watch?v=QDDwwePbDtw" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=QDDwwePbDtw&lt;/a&gt;
&lt;em&gt;Great visual explanation of channels, mutexes, &lt;code&gt;sync.Cond&lt;/code&gt;, and when to use what.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Forum: Why &lt;code&gt;sync.Cond&lt;/code&gt; Over Channels&lt;/strong&gt;
&lt;a href="https://forum.golangbridge.org/t/what-is-the-difference-between-channel-and-sync-cond/13125" rel="noopener noreferrer"&gt;https://forum.golangbridge.org/t/what-is-the-difference-between-channel-and-sync-cond/13125&lt;/a&gt;
&lt;em&gt;A useful community thread with insights into differences, tradeoffs, and when &lt;code&gt;Cond&lt;/code&gt; is a better fit than channels.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source code for &lt;code&gt;sync.Cond.Wait()&lt;/code&gt; (Go standard library)&lt;/strong&gt;
&lt;a href="https://github.com/golang/go/blob/master/src/sync/cond.go" rel="noopener noreferrer"&gt;https://github.com/golang/go/blob/master/src/sync/cond.go&lt;/a&gt;
&lt;em&gt;For those who want to go under the hood and see how &lt;code&gt;Wait()&lt;/code&gt; really works internally (with &lt;code&gt;runtime_notifyListWait&lt;/code&gt;).&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Go Concurrency Patterns – Francesc Campoy&lt;/strong&gt;
&lt;a href="https://www.youtube.com/watch?v=QDDwwePbDtw" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=QDDwwePbDtw&lt;/a&gt;
&lt;em&gt;Covers deep concurrency primitives including real-world use cases of &lt;code&gt;sync.Cond&lt;/code&gt;.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>[GCP] Resource vs Billing management</title>
      <dc:creator>Nguyễn Long</dc:creator>
      <pubDate>Sun, 06 Oct 2024 16:11:02 +0000</pubDate>
      <link>https://dev.to/2nguyenlong000k/gcp-resource-vs-billing-management-36nf</link>
      <guid>https://dev.to/2nguyenlong000k/gcp-resource-vs-billing-management-36nf</guid>
      <description>&lt;h1&gt;
  
  
  Resource hirarchy
&lt;/h1&gt;

&lt;p&gt;5 levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain&lt;/li&gt;
&lt;li&gt;Organiztion&lt;/li&gt;
&lt;li&gt;Folders&lt;/li&gt;
&lt;li&gt;Projects&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To create resource, must create project level first&lt;br&gt;
1 resource could be in only one project&lt;br&gt;
Not be able to be in multiple projects at the same time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;Including Service resource of gg cloud example: VMs, Storage....etc&lt;/p&gt;

&lt;p&gt;Labels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Help categorize resources by key value pair&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Billing Account:
&lt;/h1&gt;

&lt;p&gt;Role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Billing account creator

&lt;ul&gt;
&lt;li&gt;Permissions: Can create new billing accounts.&lt;/li&gt;
&lt;li&gt;Use Case: Typically assigned to individuals responsible for setting up billing for a project or organization.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Billing account user

&lt;ul&gt;
&lt;li&gt;Permissions: Allows a user to associate projects with a billing account and view basic billing information.&lt;/li&gt;
&lt;li&gt;Use Case: Useful for team members who need to link projects to the billing account but don’t require full management permissions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Billing Account Viewer

&lt;ul&gt;
&lt;li&gt;Permissions: Can view billing information, such as reports and transaction details, but cannot make changes or associate projects with billing accounts.&lt;/li&gt;
&lt;li&gt;Use Case: Best for stakeholders who need visibility into billing without the ability to modify settings (e.g., financial auditors).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Project Billing Manager

&lt;ul&gt;
&lt;li&gt;Permissions: Can link or unlink billing accounts to/from specific projects but cannot view billing details or manage the billing account itself.&lt;/li&gt;
&lt;li&gt;Use Case: Ideal for project managers who need control over which billing account is linked to their projects but do not need access to overall billing data.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Billing account Administrator:

&lt;ul&gt;
&lt;li&gt;Permissions: Has full control over the billing account, including managing payment methods, viewing reports, associating projects, and assigning roles.&lt;/li&gt;
&lt;li&gt;Use Case: Best suited for individuals or teams responsible for overseeing all billing-related activities for an organization.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Cost Management and Budget Alerts
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Commited Use Discounts (CUD's)
&lt;/h2&gt;

&lt;p&gt;Discount prices when you commit to using a &lt;em&gt;minimum level of resources for a specified term&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 or 3 years commitment&lt;/strong&gt;&lt;br&gt;
2 types commitment &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spend based&lt;/li&gt;
&lt;li&gt;Resource based&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Spend based commitment
&lt;/h2&gt;

&lt;p&gt;Discount for a commitment to spend a minimum amount for a service (hours) in a particular region&lt;/p&gt;

&lt;p&gt;If you commit to spending $100,000 on Compute Engine over a one-year period, Google Cloud may offer you a discounted rate on that service. You can use the Compute Engine resources freely within that spend, benefiting from the lower costs.&lt;/p&gt;

&lt;p&gt;Spend-based commitments are ideal for organizations with predictable cloud usage that want to optimize their costs while maintaining flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you do not use the entire $100,000 commitment over the one-year period?
&lt;/h3&gt;

&lt;p&gt;you will still be required to pay the full committed amount. Spend-based commitments in Google Cloud are binding, meaning that you are obligated to pay for the amount you committed to, even if your actual usage falls short of that amount.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full Payment Obligation: You will still be charged the full $100,000, regardless of your actual consumption.&lt;/li&gt;
&lt;li&gt;No Refunds: Google Cloud does not refund or reduce your payment if you do not fully utilize the committed spend.&lt;/li&gt;
&lt;li&gt;Planning Considerations: To avoid this, it’s essential to carefully estimate your anticipated cloud usage before entering into a spend-based commitment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What Happens If You Use More Than $100,000 ?
&lt;/h3&gt;

&lt;p&gt;If you use more than the committed amount (in this case, over $100,000) during the one-year period, the excess usage will be billed at the standard pay-as-you-go rates without any additional discounts from the spend-based commitment. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discount Applies Only Up to the Committed Amount: You receive discounted pricing only for the committed $100,000. Once you exceed this amount, any further usage is charged at the regular on-demand rates.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No Penalties for Over-Usage: You are free to use more than your commitment, but the discounts do not apply beyond the committed spend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Regular Billing for Excess Usage: Any usage beyond your commitment will be billed monthly, just like regular Google Cloud billing, but without the discounted rates.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Benefit?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;25% discount&lt;/strong&gt; for 1 year - &lt;strong&gt;52% discount&lt;/strong&gt; for 3 year&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Cloud SQL instacnes:&lt;/li&gt;
&lt;li&gt;BigQuery Reservations&lt;/li&gt;
&lt;li&gt;GG VMWare Engine:

&lt;ul&gt;
&lt;li&gt;Google Kubernetes Engine (GKE)&lt;/li&gt;
&lt;li&gt;Google Cloud Compute Engine&lt;/li&gt;
&lt;li&gt;Cloud Run&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Applies only to &lt;strong&gt;CPU&lt;/strong&gt; and &lt;strong&gt;memory usage&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resource based commitment
&lt;/h2&gt;

&lt;p&gt;Discount for a commitment to spend &lt;strong&gt;a minimum amount&lt;/strong&gt; for &lt;strong&gt;compute Engine resources&lt;/strong&gt; in a &lt;strong&gt;particular region&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, you might commit to using 64 vCPUs and 256 GB of memory for a one-year term.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;vCPU, Memory, GPU and Local SSD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Discounted Pricing: In exchange for committing to these resources, you receive a substantial discount (often up to 50-70% off) compared to the regular, on-demand rates.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;57% discount for most resource&lt;/li&gt;
&lt;li&gt;70% for memory-optimized machine types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For use across Projects&lt;/p&gt;

&lt;h3&gt;
  
  
  Use case:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Predictable Workloads: This option is ideal for workloads that are predictable and steady, as it helps reduce costs significantly over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Applicable to Specific Services: Resource-based commitments are most commonly used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compute Engine: Virtual machine (VM) instances, CPU, RAM, GPUs.&lt;/li&gt;
&lt;li&gt;Google Kubernetes Engine (GKE): Resources used by Kubernetes - clusters.&lt;/li&gt;
&lt;li&gt;Cloud SQL: For database resource allocations (vCPUs and RAM).&lt;/li&gt;
&lt;li&gt;Cloud Spanner: For specific database instances and resources.
### Example:
If you commit to using 100 vCPUs and 512 GB of RAM for a one-year period for Compute Engine, you’ll receive a discounted price for this specific resource allocation. If you use more than this, the additional resources will be charged at the regular rate, but if you use less, you’ll still be charged for the committed resources.
## Sustained-use discounts
Automatic discounts for running Compute Engine resources a significant portion of the billing month
Applies to vCPUs and memory for most Compute Engine instance types&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Does not apply for App Engine flexible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dataflow&lt;/li&gt;
&lt;li&gt;E2 machine types&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Feature
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automatic Discounts:

&lt;ul&gt;
&lt;li&gt;SUDs are automatically applied when you use a Compute Engine VM for more than 25% of a month. The longer you run the VM, the larger the discount becomes, reaching up to 30% off the standard price when the VM is used for nearly the entire month.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;No Commitment Required:

&lt;ul&gt;
&lt;li&gt;Unlike committed-use contracts, there’s no need to pre-purchase or commit to a specific amount of resources. The discount is automatically applied based on how long you use the VM each month.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Proportional Discounts:

&lt;ul&gt;
&lt;li&gt;The discount grows as your usage increases. Here’s a breakdown:

&lt;ul&gt;
&lt;li&gt;For the first 25% of the month, you pay the full price.&lt;/li&gt;
&lt;li&gt;For 25% to 50% usage, you get a small discount.&lt;/li&gt;
&lt;li&gt;For 50% to 75% usage, the discount increases further.&lt;/li&gt;
&lt;li&gt;For usage above 75%, you get the maximum discount (up to 30%).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Cloud Billing Budgets
&lt;/h1&gt;

&lt;p&gt;Enable you to &lt;em&gt;track your actual Google Cloud spend&lt;/em&gt; against your planned spend&lt;/p&gt;

&lt;p&gt;Budget alert threshold rules that are used to &lt;strong&gt;trigger email&lt;/strong&gt; notifications to help you stay informed about your spend&lt;/p&gt;

&lt;h1&gt;
  
  
  Feature:
&lt;/h1&gt;

&lt;p&gt;Define the scope of the budget&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spen of billing account or more granular&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Budget amount can be set to a specified total, or based on previous month's spend&lt;/p&gt;

&lt;p&gt;Alert emails are sent to billing account admins and specific users when &lt;strong&gt;costs exceed a percentage&lt;/strong&gt; of the budget&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Handling Transactions Without Breaking Service-Adapter Decoupling in Hexagonal Architecture with Golang</title>
      <dc:creator>Nguyễn Long</dc:creator>
      <pubDate>Tue, 01 Oct 2024 00:17:31 +0000</pubDate>
      <link>https://dev.to/2nguyenlong000k/handling-transactions-without-breaking-service-adapter-decoupling-in-hexagonal-architecture-with-golang-5ce1</link>
      <guid>https://dev.to/2nguyenlong000k/handling-transactions-without-breaking-service-adapter-decoupling-in-hexagonal-architecture-with-golang-5ce1</guid>
      <description>&lt;h1&gt;
  
  
  Handling Transactions Without Breaking Service-Adapter Decoupling in Hexagonal Architecture with Golang
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When building applications in Go using hexagonal architecture (also known as Ports and Adapters), maintaining a clear separation between the service layer and the adapter layer is essential.&lt;/p&gt;

&lt;p&gt;One challenge that developers often face is managing database transactions within this architecture without violating service-adapter decoupling.&lt;br&gt;
I will walk you through a common problem of transaction handling and how to refactor your Go code to solve it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Problem: Transactions and Decoupling
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In hexagonal architecture, the service (business logic) should not be aware of infrastructure details such as transaction management. &lt;/li&gt;
&lt;li&gt;The service layer should focus purely on business rules and defer infrastructure operations like database interactions to the adapter layer. &lt;/li&gt;
&lt;li&gt;Transaction handling, like db.Begin(), often ends up being tightly coupled to the service layer, leading to design that violates the principle of separation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider the following example, where transaction logic leaks into the service layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// UserService (Service Layer)
type UserService struct {
    userRepo port.UserRepo
    logRepo  port.LogRepo
}

func (u *UserService) CreateUser(ctx context.Context, user domain.User) error {
    // Transaction begins in the adapter
    tx := u.userRepo.BeginTransaction(ctx)

    // Create user
    createdUser, err := u.userRepo.CreateUser(ctx, user)
    if err != nil {
        tx.Rollback()
        return err
    }

    // Create task for the user
    task, err := u.userRepo.CreateTask(ctx, createdUser)
    if err != nil {
        tx.Rollback()
        return err
    }

    // Log the task
    err = u.logRepo.LogTask(ctx, task)
    if err != nil {
        tx.Rollback()
        return err
    }

    // Commit transaction if all steps succeed
    return tx.Commit()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is a basic operation for for User and Task Management System. Here is the break down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, user will be created&lt;/li&gt;
&lt;li&gt;After user created, some Task instances will create for that user&lt;/li&gt;
&lt;li&gt;After task creation, the system will log the task for the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point we may noticed that if any of this task fail, then it should be rollback, otherwise, the actions will be commited.&lt;/p&gt;

&lt;h3&gt;
  
  
  But, What's Wrong with This Approach?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;At first glance while this might seem functional, the &lt;code&gt;CreateUser&lt;/code&gt; method in the service layer is managing the transaction (BeginTransaction, Rollback, Commit), &lt;strong&gt;which should be the responsibility of the adapter layer.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Handling transactions directly in the service? -&amp;gt; violate the decoupling principle. -&amp;gt; harder to maintain and scale your code, as the service layer now knows too much about the infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Better Solution: Apply Unit of work pattern
&lt;/h2&gt;

&lt;p&gt;The Unit of Work pattern groups multiple operations into a single transaction and ensures that all changes are committed or rolled back as a unit. The Unit of Work itself can manage the transaction across repositories. It acts as a coordinator for all database changes that happen during a business operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type UnitOfWork struct {
    db *sql.DB
}

func (uow *UnitOfWork) Begin(ctx context.Context) (context.Context, error) {
    tx, err := uow.db.Begin()
    if err != nil {
        return ctx, err
    }
    uow.tx = tx
    return context.WithValue(ctx, TransactionKey, tx), nil
}

func (uow *UnitOfWork) Commit() error {
    return uow.tx.Commit()
}

func (uow *UnitOfWork) Rollback() error {
    return uow.tx.Rollback()
}

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

&lt;/div&gt;



&lt;p&gt;In this case, the &lt;code&gt;UnitOfWork&lt;/code&gt; is passed around to each repository, ensuring all operations within a transaction are coordinated. The service layer simply calls the Unit of Work to start and complete transactions.&lt;/p&gt;

&lt;p&gt;UserService now will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (u *UserService) CreateUser(ctx context.Context, user domain.User) error {
    uow := UnitOfWork{}
    ctx, err := uow.Begin(ctx, u.db)
    if err != nil {
        return err
    }

    createdUser, err := u.userRepo.CreateUser(ctx, user)
    if err != nil {
        uow.Rollback()
        return err
    }

    task, err := u.userRepo.CreateTask(ctx, createdUser)
    if err != nil {
        uow.Rollback()
        return err
    }

    err = u.logRepo.LogTask(ctx, task)
    if err != nil {
        uow.Rollback()
        return err
    }

    return uow.Commit()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo Layer: It will get the transaction from the context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// UserRepoImpl (Adapter Layer)
type UserRepoImpl struct {
    db *sql.DB
}

func (u *UserRepoImpl) CreateUser(ctx context.Context, user domain.User) (domain.User, error) {
    // Use the transaction from context
    tx := ctx.Value(TransactionKey).(*sql.Tx)
    // Execute user creation within the transaction
    result, err := tx.Exec("INSERT INTO users ...")
    if err != nil {
        return domain.User{}, err
    }
    // Logic to create and return the new user
    return createdUser, nil
}

func (u *UserRepoImpl) CreateTask(ctx context.Context, user domain.User) (domain.Task, error) {
    tx := ctx.Value(TransactionKey).(*sql.Tx)
    // Execute task creation within the transaction
    result, err := tx.Exec("INSERT INTO tasks ...")
    if err != nil {
        return domain.Task{}, err
    }
    return task, nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By making use of callback and pass transaction via context, We can get the benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service layer no longer handles transaction management. It simply focuses on business logic.&lt;/li&gt;
&lt;li&gt;All transaction-related concerns are handled in the repository (adapter) layer, making it easier to change or extend the infrastructure layer without affecting the service.&lt;/li&gt;
&lt;li&gt; The &lt;strong&gt;Unit Of Work&lt;/strong&gt; method can be reused across different service methods that require transaction handling, reducing code duplication.&lt;/li&gt;
&lt;li&gt; Easier to test because it’s not tied to the database context.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Decoupling transaction management from the service layer and moving it to the adapter layer helps you adhere to the principles of hexagonal architecture. This refactor not only keeps the layers clean and independent but also improves the maintainability and scalability of your application. In Golang, this approach can be easily implemented using contexts to pass transactions and callback functions to execute business logic within the transaction scope.&lt;/p&gt;

&lt;p&gt;Ref:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/gretro/unit-of-work-pattern-in-go-i6l"&gt;https://dev.to/gretro/unit-of-work-pattern-in-go-i6l&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sesaquecruz/go-unit-of-work" rel="noopener noreferrer"&gt;https://github.com/sesaquecruz/go-unit-of-work&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>GCP compute options</title>
      <dc:creator>Nguyễn Long</dc:creator>
      <pubDate>Mon, 30 Sep 2024 22:18:19 +0000</pubDate>
      <link>https://dev.to/2nguyenlong000k/gcp-compute-options-1j5n</link>
      <guid>https://dev.to/2nguyenlong000k/gcp-compute-options-1j5n</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fheam4wy7ibrarieitg8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fheam4wy7ibrarieitg8m.png" alt="Image description" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Deep Dive into GCP Compute Options

&lt;ol&gt;
&lt;li&gt;
Google Compute Engine (GCE) – Virtual Machines

&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Use Cases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Google Kubernetes Engine (GKE) – Container Orchestration

&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Use Cases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
App Engine – Platform-as-a-Service (PaaS)

&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Cloud Functions

&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Use Cases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Comparison Table&lt;/li&gt;

&lt;/ol&gt;

&lt;h1&gt;
  
  
  Introduction:
&lt;/h1&gt;

&lt;p&gt;💡 So, you’re building something cool on GCP, and now you need to pick the right compute option. It's like standing in front of a vending machine of cloud services: “Do I want a classic virtual machine? Or should I get some fancy containers? Maybe I'll go serverless and just have it magically work.”&lt;/p&gt;

&lt;p&gt;In Google Cloud Platform, you’ve got choices—and lots of them. But don’t worry, it’s not as confusing as picking the perfect avocado. Let’s break it down, step by step, with a little fun along the way. Think of each compute option like different modes of transportation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💻 Virtual Machines (VMs): You’re driving your own car. Full control, but hey, you’ve got to maintain it &lt;/li&gt;
&lt;li&gt;☸️/🐳 Containers (GKE/Cloud Run): Hop on a public bus. You are sharing, but it's efficent and flexible.&lt;/li&gt;
&lt;li&gt;🌍 Serverless (App Engine/Cloud Funcion): Teleportation... You dont know how, but you're there when you need to be.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Deep Dive into GCP Compute Options
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Google Compute Engine (GCE) – Virtual Machines
&lt;/h2&gt;

&lt;p&gt;VMs💻 are called instance andd need to choose region and zone to deploy.&lt;br&gt;
You choose the OS and specify the application you put on it.&lt;/p&gt;

&lt;p&gt;GCE provides traditional virtual machines that give you complete control over the operating system and infrastructure. You manage everything: scaling, patching, and maintaining the VMs. This is ideal for legacy applications, specialized workloads that need specific OS configurations, or high-compute tasks that demand fine-grained control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Full control over OS &lt;/li&gt;
&lt;li&gt;Custom VM type ot predefined ones&lt;/li&gt;
&lt;li&gt;Suitable for workloads that require specific lib or frameworks&lt;/li&gt;
&lt;li&gt;Manging multiple instances using &lt;strong&gt;instance groups&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add/remove capacity using autoscaling with &lt;strong&gt;instance groups&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Attach/detach disks as needed.&lt;/li&gt;
&lt;li&gt;Can SSH directly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hosting legacy applications that aren’t easily containerized.&lt;/li&gt;
&lt;li&gt;Running high-performance computing (HPC) tasks or workloads that need fine-tuning&lt;/li&gt;
&lt;li&gt;Applications that require stateful operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s say you’re running a finance application that needs specific security patches and configurations to meet regulatory compliance. VMs are perfect because you control every layer, including the OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. ☸ Google Kubernetes Engine (GKE) – Container Orchestration
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Is container-oschestration system for automating deploying,scaling and managing containers&lt;/li&gt;
&lt;li&gt;Built in* open-source Kubernetes*&lt;/li&gt;
&lt;li&gt;Flexibility to &lt;em&gt;inegrate&lt;/em&gt; with on-premise Kubernetes.&lt;/li&gt;
&lt;li&gt;Uses compute engine instances as nodes in a clusters ☸&lt;/li&gt;
&lt;li&gt;Cluster is group of nodes or compute engine instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automatic scaling and self-healing containers.&lt;/li&gt;
&lt;li&gt;Runs across multiple zones for redundancy.&lt;/li&gt;
&lt;li&gt;Integrates with Google’s stack, like Cloud Monitoring and Logging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Running microservices architectures, where each service can scale independently.&lt;/li&gt;
&lt;li&gt;Applications that need high availability across zones.&lt;/li&gt;
&lt;li&gt;Workloads requiring container orchestration with easy management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧠 Think of an ecommerce app that needs independent scaling for different services (checkout, inventory, recommendations). With GKE, you deploy each service in a container, ensuring that traffic spikes on one service don’t affect the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.🚀 App Engine – Platform-as-a-Service (PaaS)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fuly managed, serverless platform for developing and hosting web applications at scale (PaaS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Provisions servers and scales your app instances &lt;em&gt;based on demand&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Build your app by favourite lanaguage&lt;/li&gt;
&lt;li&gt;Connect with GG services seamlessly like Firestore, Cloud SQL, and Pub/Sub.&lt;/li&gt;
&lt;li&gt;Integrates with Web sec scanner to identify threats.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 App Engine is a fully managed platform that abstracts away infrastructure management. You focus on writing your code while App Engine handles everything from scaling to monitoring. It’s great for developers who want to focus on code, not infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Cloud Function (λ)
&lt;/h2&gt;

&lt;p&gt;Serverless Execution env for building &amp;amp; connecting cloud service&lt;/p&gt;

&lt;h3&gt;
  
  
  Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simple, single-purpose functions that are attached to events&lt;/li&gt;
&lt;li&gt;Triggerd when an event being watched is fired&lt;/li&gt;
&lt;li&gt;Your code executes in a fully managed env&lt;/li&gt;
&lt;li&gt;No need to provision any infrastructure&lt;/li&gt;
&lt;li&gt;Event-driven: Automatically executes in response to triggers.&lt;/li&gt;
&lt;li&gt;Scales automatically with traffic.&lt;/li&gt;
&lt;li&gt;Perfect for lightweight, short-duration tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use case:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ETC&lt;/li&gt;
&lt;li&gt;hook&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;Mobile backend functions&lt;/li&gt;
&lt;li&gt;FaaS&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Comparison Table:
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Service&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Management Level&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Scaling&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Cost Model&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compute Engine&lt;/td&gt;
&lt;td&gt;VMs&lt;/td&gt;
&lt;td&gt;Full control&lt;/td&gt;
&lt;td&gt;Manual or autoscaling&lt;/td&gt;
&lt;td&gt;Pay for uptime&lt;/td&gt;
&lt;td&gt;Legacy apps, specialized OS control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes Engine (GKE)&lt;/td&gt;
&lt;td&gt;Container orchestration&lt;/td&gt;
&lt;td&gt;Managed&lt;/td&gt;
&lt;td&gt;Automatic, multi-zone availability&lt;/td&gt;
&lt;td&gt;Pay for instance uptime&lt;/td&gt;
&lt;td&gt;Microservices, high availability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Run&lt;/td&gt;
&lt;td&gt;Serverless containers&lt;/td&gt;
&lt;td&gt;Fully managed&lt;/td&gt;
&lt;td&gt;Scales to zero&lt;/td&gt;
&lt;td&gt;Pay per request&lt;/td&gt;
&lt;td&gt;Stateless apps, event-driven microservices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App Engine&lt;/td&gt;
&lt;td&gt;PaaS&lt;/td&gt;
&lt;td&gt;Fully managed&lt;/td&gt;
&lt;td&gt;Automatic, scales based on traffic&lt;/td&gt;
&lt;td&gt;Pay per instance uptime&lt;/td&gt;
&lt;td&gt;Web apps, mobile backends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Functions&lt;/td&gt;
&lt;td&gt;Serverless functions&lt;/td&gt;
&lt;td&gt;Fully managed&lt;/td&gt;
&lt;td&gt;Automatic, scales to zero&lt;/td&gt;
&lt;td&gt;Pay per execution&lt;/td&gt;
&lt;td&gt;Event-driven, lightweight tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
    </item>
    <item>
      <title>GCP Global Infrastructure</title>
      <dc:creator>Nguyễn Long</dc:creator>
      <pubDate>Mon, 30 Sep 2024 21:36:47 +0000</pubDate>
      <link>https://dev.to/2nguyenlong000k/gcp-global-infrastructure-44k6</link>
      <guid>https://dev.to/2nguyenlong000k/gcp-global-infrastructure-44k6</guid>
      <description>&lt;p&gt;Google Cloud had been designed to serve all users worldwide by designing the infrastructure with redundant regions connected with high bandwidth connecting different continents.&lt;br&gt;
Invested 13 Subsea Cables Connecting these continents(100,000 miles of fiber cable)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;24 Regions&lt;/li&gt;
&lt;li&gt;73 Zone&lt;/li&gt;
&lt;li&gt;144 Network edges location&lt;/li&gt;
&lt;li&gt;200+ countries and territory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F7kt76l3gog68abuxk1zn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7kt76l3gog68abuxk1zn.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwfglazj7p17u2gs4bf43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwfglazj7p17u2gs4bf43.png" alt="Image description" width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In cloud computing, the terms zone, region, and multi-region are used to describe the geographical organization of cloud resources, which impacts performance, availability, and redundancy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zone:
&lt;/h2&gt;

&lt;p&gt;A zone is a specific, isolated data center within a region. Each region contains multiple zones (usually 3 or more). Zones are independent of one another to ensure high availability.&lt;br&gt;
Resources (like VMs, databases) within a zone can communicate with very low latency.&lt;br&gt;
If a zone goes down (due to a failure or maintenance), other zones in the same region continue to operate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key Points:

&lt;ul&gt;
&lt;li&gt;Zone = Individual data center within a region.&lt;/li&gt;
&lt;li&gt;Isolated: Redundant setup ensures &lt;strong&gt;high availability.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Low latency communication &lt;strong&gt;between resources in the same zone&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Region:
&lt;/h2&gt;

&lt;p&gt;A region is a geographical location that contains multiple zones (typically 3 or more). For example, &lt;code&gt;us-central1&lt;/code&gt; is a region.&lt;br&gt;
A region ensures redundancy by spreading resources across multiple zones, reducing the risk of downtime due to failures in one zone.&lt;br&gt;
Each region is designed to be independent of other regions to ensure &lt;em&gt;fault tolerance and minimize latency for users in that geographical area&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key Points:

&lt;ul&gt;
&lt;li&gt;Region = Group of zones in a specific geographical area.&lt;/li&gt;
&lt;li&gt;Ensures redundancy and low latency for local traffic.&lt;/li&gt;
&lt;li&gt;Independent of other regions for fault tolerance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Multi-region:
&lt;/h2&gt;

&lt;p&gt;Multi-region refers to deploying resources across multiple regions. This approach is used to improve disaster recovery, global availability, and latency reduction for users in different parts of the world.&lt;br&gt;
Services that need global reach or highly available systems may use multi-region setups to ensure that even if one region goes down, others can take over without downtime.&lt;br&gt;
Examples include Google Cloud Storage or databases set up in a multi-region configuration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key Points:

&lt;ul&gt;
&lt;li&gt;Multi-region = Resources spread across several regions.&lt;/li&gt;
&lt;li&gt;Improves global availability and disaster recovery.&lt;/li&gt;
&lt;li&gt;Reduces latency for users in different geographical areas.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>gcp</category>
    </item>
  </channel>
</rss>
