context deadline exceeded means an operation didnβt complete within the timeout set by context.WithTimeout or context.WithDeadline.
Why this happens
Goβs context package enforces deadlines to prevent operations from hanging indefinitely. When a network call, database query, or any blocking operation takes longer than the configured timeout, the context is cancelled and this error is returned. The timeout may be set explicitly in your code or inherited from a parent context higher in the call chain.
What causes this error
- HTTP request to slow server β the external API didnβt respond in time
- Database query too slow β complex query exceeds the context timeout
- Timeout too short β the default or configured timeout is too aggressive
Fix 1: Increase the timeout
// β 1 second might be too short
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
// β
Give it more time
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
Fix 2: Add timeout to HTTP clients
client := &http.Client{
Timeout: 30 * time.Second,
}
resp, err := client.Get("https://slow-api.com/data")
Fix 3: Optimize the slow operation
If a database query is timing out, add indexes or simplify the query. If an API is slow, add caching or use a circuit breaker.
Alternative solutions
Retry with backoff: Use an exponential backoff strategy to retry failed requests rather than just increasing the timeout:
for i := 0; i < 3; i++ {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
resp, err := client.Do(req.WithContext(ctx))
cancel()
if err == nil { break }
time.Sleep(time.Duration(i+1) * 2 * time.Second)
}
Use context.WithCancel for long-running operations and cancel manually when you detect the operation is no longer needed.
Prevention
- Set realistic timeouts based on observed p99 latencies, not arbitrary values.
- Always pass contexts through your call chain and always call
defer cancel()to clean up resources.
Related: Go: Nil Pointer Dereference fix Β· Broken Pipe fix