# Go (Golang) Microservice for Email with Circuit Breakers & Retries

_By Tayyab Mughal, Founder & AI Chief · 31 July 2026 · 2 min read_

> Building an enterprise-grade Go email microservice featuring Sony GoBreaker circuit breakers, exponential backoff retries, and structured slog telemetry.

Learn how to write a production-grade Go service that dispatches millions of emails with resilient circuit breaking, retries, and zero memory leaks.

## 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.

```go
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.

---

_Tags: Go, Golang, Microservices, Resilience_
