The service makes requests to an external API that has started responding in 10 seconds. Goroutines are piling up, memory is growing, and the service crashes due to OOM. How to protect?
sobes.tech AI
Answer from AI
The problem is that goroutines are blocked on long requests to external APIs, leading to an accumulation of goroutines and increased memory consumption.
How to protect the service:
-
Limit the number of concurrently executing requests — use a semaphore or a worker pool to avoid creating too many goroutines.
-
Set timeouts on HTTP requests — use a context with a timeout (
context.WithTimeout) or configure timeouts in the HTTP client so that requests do not hang indefinitely. -
Handle errors and cancel requests on timeout — so goroutines do not block.
-
Use context for request cancellation — pass
context.Contextto functions to be able to cancel requests if necessary.
Example with timeout and concurrency limit:
var semaphore = make(chan struct{}, 10) // maximum 10 concurrent requests
func callExternalAPI(ctx context.Context, url string) error {
semaphore <- struct{}{} // acquire slot
defer func() { <-semaphore }() // release slot
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// process response
return nil
}
This approach prevents goroutine accumulation and OOM crashes.