Why Go microservices need circuit breakers for external APIs
When downstream third-party networks experience temporary degradation, unbounded goroutines trying to send emails can exhaust system file descriptors and crash your service.
Implementing the Circuit Breaker pattern with sony/gobreaker ensures your Go service fails fast during upstream outages without cascading failures.
Go Email Client with Circuit Breaker (email.go)
Here is the complete Go implementation with circuit breakers and custom JSON transport.
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/sony/gobreaker"
)
type EmailClient struct {
apiKey string
httpClient *http.Client
cb *gobreaker.CircuitBreaker
}
type SendRequest struct {
To string `json:"to"`
Subject string `json:"subject"`
Text string `json:"text"`
}
func NewEmailClient(apiKey string) *EmailClient {
st := gobreaker.Settings{
Name: "SadaSendCircuitBreaker",
MaxRequests: 5,
Interval: 30 * time.Second,
Timeout: 10 * time.Second,
}
return &EmailClient{
apiKey: apiKey,
httpClient: &http.Client{Timeout: 5 * time.Second},
cb: gobreaker.NewCircuitBreaker(st),
}
}
func (c *EmailClient) Send(ctx context.Context, req SendRequest) error {
_, err := c.cb.Execute(func() (interface{}, error) {
payload, _ := json.Marshal(req)
httpReq, _ := http.NewRequestWithContext(ctx, "POST", "https://api.sadasend.com/v1/emails", bytes.NewBuffer(payload))
httpReq.Header.Set("Authorization", "Bearer "+c.apiKey)
httpReq.Header.Set("Content-Type", "application/json")
resp, err := c.httpClient.Do(httpReq)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return nil, fmt.Errorf("server error: %d", resp.StatusCode)
}
return nil, nil
})
return err
}Core Advantages in Go Production Clusters
- Zero goroutine leakage on connection stalls.
- Fail-fast protection that recovers automatically when connectivity restores.
- Native context.Context cancellation support for graceful server shutdowns.
Building AI agents that send email?
Join the SadaSend early access waitlist to get scoped API keys, recipient allowlists, and Model Context Protocol (MCP) servers upon launch.