0Pricing
Go Academy · Lesson

Throttling Goroutines

Control concurrency.

Throttling Goroutines is a free Go Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Throttling Concurrency

Sometimes you do not limit per second, you limit how many goroutines run at once. This caps simultaneous load on a resource regardless of timing.

  • Bounds parallelism
  • Protects connection pools
  • Prevents memory spikes

The Semaphore Channel

A buffered channel works as a counting semaphore. Its capacity equals the maximum concurrency. Acquiring sends a token; releasing receives one.

sem := make(chan struct{}, 3)

Acquire and Release

Before starting work, send into the channel to acquire a slot (blocks if full). When done, receive to release it, freeing the slot for another goroutine.

sem <- struct{}{}        // acquire
// do work
<-sem                    // release

Why struct{}

An empty struct struct{}{} occupies zero bytes. Using it as the channel element makes the semaphore a pure signal with no wasted memory.

Throttling a Loop

Launch a goroutine per task but gate each on the semaphore. At most cap goroutines do real work concurrently; the rest block at acquire.

for _, task := range tasks {
    sem <- struct{}{}
    go func(t Task) {
        defer func() { <-sem }()
        process(t)
    }(t)
}

Pairing with WaitGroup

The semaphore bounds concurrency but does not tell you when everything finishes. Combine it with a sync.WaitGroup to wait for all tasks.

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    defer func() { <-sem }()
    process(t)
}()

Release in defer

Always release in a defer so the slot frees even if the work panics or returns early. Forgetting to release leaks slots and eventually deadlocks new acquirers.

A Complete Throttled Run

This program runs eight tasks with at most two concurrent, printing start and end to show the cap in action.

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    sem := make(chan struct{}, 2)
    var wg sync.WaitGroup
    for i := 0; i < 8; i++ {
        wg.Add(1)
        sem <- struct{}{}
        go func(id int) {
            defer wg.Done()
            defer func() { <-sem }()
            fmt.Println("start", id)
            time.Sleep(20 * time.Millisecond)
            fmt.Println("end", id)
        }(i)
    }
    wg.Wait()
    fmt.Println("done")
}

errgroup with SetLimit

The golang.org/x/sync/errgroup package offers SetLimit to throttle a group and propagate the first error. It is a cleaner alternative for many cases, though it is an external package.

Throttling vs Worker Pool

A worker pool reuses a fixed set of goroutines pulling from a queue. Semaphore throttling spawns a goroutine per task but caps active ones. Pools are leaner for huge task counts; semaphores are simpler to bolt on.

Choosing the Limit

For database calls, set the limit at or below your connection pool size. For outbound HTTP, match the host connection limit. Too high causes resource exhaustion; too low wastes capacity.

Quick Check

Test your throttling knowledge.

Recap

You learned goroutine throttling:

  • A buffered channel acts as a counting semaphore
  • Acquire by send, release by receive in defer
  • struct{} elements cost zero bytes
  • Pair with WaitGroup to wait for completion
  • Size the limit to the protected resource

Frequently asked questions

Is the “Throttling Goroutines” lesson free?

Yes — the full text of “Throttling Goroutines” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.

What will I learn in “Throttling Goroutines”?

Control concurrency. You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Go Academy?

No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Throttling Goroutines” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Go Academy lesson?

Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Token Bucket Concept
  2. golang.org/x/time/rate
  3. Throttling Goroutines
  4. Backoff and Retry
← Back to Go Academy