Enforcing a 5‑QPS Limit on Go Jobs with Rate Limiter and Semaphore

This article explains how to restrict a third‑party API to five requests per second in Go by combining a rate limiter to pace job starts and a semaphore to cap concurrent executions, complete with a full, runnable code example and detailed implementation notes.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Enforcing a 5‑QPS Limit on Go Jobs with Rate Limiter and Semaphore

Requirement: a third‑party API is limited to 5 QPS, so the number of jobs that access the interface must not exceed five per second, including both running and newly started tasks.

Solution: use a rate limiter to control the frequency of job starts and a semaphore to bound the number of jobs running concurrently. The limiter guarantees that no more than five jobs begin each second; the semaphore ensures that at most five jobs are executing at any moment.

Implementation

package main

import (
    "context"
    "fmt"
    "math/rand"
    "sync"
    "sync/atomic"
    "time"

    "golang.org/x/time/rate"
)

func RateLimit() {
    const maxJobsPerSecond = 5
    const numJobs = 22
    var wg sync.WaitGroup

    var runningJobs int32   // currently executing jobs
    var startedJobs int32   // jobs that have been started
    var finishedJobs int32  // jobs that have just finished

    limiter := rate.NewLimiter(rate.Every(time.Second/time.Duration(maxJobsPerSecond)), maxJobsPerSecond)
    semaphore := make(chan struct{}, maxJobsPerSecond)

    for i := 1; i <= numJobs; i++ {
        wg.Add(1)
        go func(jobID int) {
            defer wg.Done()
            limiter.Wait(context.Background()) // wait for limiter permission

            semaphore <- struct{}{}               // acquire semaphore
            atomic.AddInt32(&startedJobs, 1)
            atomic.AddInt32(&runningJobs, 1)

            executeJob(jobID) // perform the task

            atomic.AddInt32(&finishedJobs, 1)
            atomic.AddInt32(&runningJobs, -1)

            <-time.After(time.Second) // wait one second before releasing
            <-semaphore               // release semaphore

            printStatus(&runningJobs, &startedJobs, &finishedJobs)
        }(i)
    }

    wg.Wait()
    fmt.Println("All jobs completed")
}

Key Points

The rate.NewLimiter call controls the launch rate so that at most maxJobsPerSecond jobs start each second.

A semaphore channel limits the number of jobs that can run concurrently.

After a job finishes, the code waits one second before releasing the semaphore to prevent immediate new starts, ensuring the per‑second limit is respected even for fast‑completing tasks.

Atomic counters ( startedJobs, runningJobs, finishedJobs) safely track job states in a concurrent environment.

Supporting Functions

func executeJob(jobID int) {
    startTime := time.Now()
    fmt.Printf("%v Job %d started
", time.Now().Format("2006-01-02 15:04:05.000"), jobID)

    rand.Seed(time.Now().UnixNano())
    duration := time.Duration(rand.Intn(5000-1+1)+1) * time.Millisecond
    time.Sleep(duration)

    fmt.Printf("%v Job %d finished Cost:%v
", time.Now().Format("2006-01-02 15:04:05.000"), jobID, time.Since(startTime))
}

func printStatus(runningJobs, startedJobs, finishedJobs *int32) {
    fmt.Printf("Current status - Running: %d, Started: %d, Finished: %d
",
        atomic.LoadInt32(runningJobs),
        atomic.LoadInt32(startedJobs),
        atomic.LoadInt32(finishedJobs))
}

This implementation ensures that even if tasks complete quickly, no more than five new tasks are launched per second, while accurately tracking running, started, and finished jobs.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendGosemaphorerate limitingQPS
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.