This content originally appeared on Level Up Coding - Medium and was authored by Dzaky Widya Putra
Introduction
There are many ways to optimize your code to achieve more efficiency, and reducing running processes is one of them. In this article, we are going to see how we can optimize a Go code by reducing duplicate processes using one of the Go packages, Singleflight.
Problem
Let’s say you have a web app, it has 10 requests per second (RPS). Based on the data you know some of those requests have the same pattern that can actually generate the same result, which means you actually have redundant processes.

From the illustration above, we know user 1 and user 2 want the same thing, but in the end, we (mostly) are processing both requests separately.
Solution
Singleflight is one of the Go packages that can solve that kind of problem, as described in the documentation, it provides a duplicate function call suppression mechanism.
Cool, so we can actually decrease the number of functions we process if we know that the functions we are going to call are duplicated, let’s see how we can use it in the real-world case.
Implementation
We are going to create two programs, server.go and client.go .
server.go — will act as the web service that can receive requests at the endpoint /api/v1/get_something with a parameter called name
// server.go
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/api/v1/get_something", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
response := processingRequest(name)
fmt.Fprint(w, response)
})
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println(err)
}
}
func processingRequest(name string) string {
fmt.Println("[DEBUG] processing request..")
return "Hi there! You requested " + name
}
client.go will act as a client that makes 5 concurrent requests to the web service (you can set the number in a variable totalRequests)
// client.go
package main
import (
"io/ioutil"
"log"
"net/http"
"sync"
)
func main() {
var wg sync.WaitGroup
endpoint := "http://localhost:8080/api/v1/get_something?name=something"
totalRequests := 5
for i := 0; i < totalRequests; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
makeAPICall(endpoint)
}(i)
}
wg.Wait()
}
func makeAPICall(endpoint string) {
resp, err := http.Get(endpoint)
if err != nil {
log.Fatalln(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
result := string(body)
log.Printf(result)
}
First, we can run the server.go then continue by client.go. We’ll see in the terminal of the server’s script something like this:
[DEBUG] processing request..
[DEBUG] processing request..
[DEBUG] processing request..
[DEBUG] processing request..
[DEBUG] processing request..
The terminal of the client’s script would be like this:
Hi there! You requested something
Hi there! You requested something
Hi there! You requested something
Hi there! You requested something
Hi there! You requested something
It makes sense, since we sent five requests from the clients, and processed those five requests in the server.
Now let’s implement Singleflight in our code so that it would be more efficient.
// server.go
package main
import (
"fmt"
"net/http"
"golang.org/x/sync/singleflight"
)
var g = singleflight.Group{}
func main() {
http.HandleFunc("/api/v1/get_something", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
response, _, _ := g.Do(name, func() (interface{}, error) {
result := processingRequest(name)
return result, nil
})
fmt.Fprint(w, response)
})
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println(err)
}
}
func processingRequest(name string) string {
fmt.Println("[DEBUG] processing request..")
return "Hi there! You requested " + name
}
After we restarted the server and run the client’s program again, the terminal in the server’s script shows this:
[DEBUG] processing request..
[DEBUG] processing request..
The terminal of the client’s script shows this:
Hi there! You requested something
Hi there! You requested something
Hi there! You requested something
Hi there! You requested something
Hi there! You requested something
That’s great! All the clients get the expected responses, but now our server only processed two requests. Imagine the size of efficiency you will bring if you are processing thousands of similar requests, it’s amazing!
Conclusion
In this article, we learned the power of Singleflight in optimizing our code. Not only in handling a web request, but you can also expand the use case of it to other things like getting the data from the database, etc.
There are also things that I didn’t cover in this article for example what if the process in Singleflight fails, and how we can mitigate it. That might be a topic I want to explore later in the next articles.
Lastly, thank you very much if you are still reading up to this point, please do share the article if you find it useful or might know someone who needs it.
Level Up Coding
Thanks for being a part of our community! Before you go:
- 👏 Clap for the story and follow the author 👉
- 📰 View more content in the Level Up Coding publication
- 🔔 Follow us: Twitter | LinkedIn | Newsletter
🚀👉 Join the Level Up talent collective and find an amazing job
Optimize your Go code using Singleflight was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Dzaky Widya Putra

Dzaky Widya Putra | Sciencx (2023-02-08T15:17:48+00:00) Optimize your Go code using Singleflight. Retrieved from https://www.scien.cx/2023/02/08/optimize-your-go-code-using-singleflight/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.