Singleflight is one of my favorite optimization techniques for backend systems. It ensures that a task is executed only once, even if multiple concurrent requests are made for the same data.

For example: Imagine you have a backend endpoint that requests data. If multiple users hit that endpoint at once, instead of hitting the database or cache multiple times, just one request is made.

5 requests hit the endpoint → only 1 DB query is made → the result is shared with all 5 users

Singleflight Illustration

How to implement Singleflight

Most languages have packages to implement Singleflight, but I will be using the official Go package (golang.org/x/sync/singleflight) for this example.

var g singleflight.Group

func GetUser(userID string) (*User, error) {
   
    // Define the work to be done
    var fetchUserFromDB func() (interface{}, error)
    fetchUserFromDB = func() (interface{}, error) {
        fmt.Println("Fetching from database")
        return database.QueryUser(userID)
    }

    // Execute with Singleflight
    result, err, shared := g.Do(userID, fetchUserFromDB)
    if err != nil {
        return nil, err
    }

    if shared {
        fmt.Println("Shared result returned")
    }

    return result.(*User), nil
}

Understanding the code

result, err, shared := g.Do(userID, fetchUserFromDB): This is where the magic happens.

  • userID: This is the key. Singleflight uses it to group requests. Any other request with this same key will wait for the first one to finish instead of calling the function again.

  • fetchUserFromDB: This is the function that actually fetches the user from the database if no request is currently running.

When to use Singleflight

Fetching data that doesn’t change often

As shown in the example above.

Handling Redis Refreshes

You can use it to handle Redis cache refreshing. You don’t want to run 500 background jobs just to update the same Redis key at the same time.

Using 3rd Party APIs

If your application calls an external API (like Twilio, Stripe, or OpenAI) that has rate limits or costs, Singleflight is a lifesaver.

Scenario: You have a dashboard widget showing the Bitcoin price from an external API.

The Problem: If 1,000 users refresh at 9:00 AM, you might hit the API 1,000 times, getting rate-limited or charged extra.

With Singleflight: The first user triggers the call; the other 999 wait. You pay for 1 call but serve 1,000 users.


Personally, I use Singleflight mostly for read-only data.