Go Academy · Lesson

Throttling Goroutines

Control concurrency.

Lesson 3 of 413 steps

Throttling Goroutines is a free Go Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, and your progress syncs across the web and the CoddyKit app. The Go Academy course includes 4 lessons in total.

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
Free to start

Learn Go with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
51
Lessons
203

Frequently Asked Questions

Is the “Throttling Goroutines” lesson free?

Yes — any 3 lessons of the Go Academy learning path, including “Throttling Goroutines”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Go Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

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