Features Quick Start Examples Testing Compare GitHub
v1.2.2 — Production Hardened

Your Go HTTP client just got superpowers

Composable, idiomatic Go HTTP resilience. Retry, Circuit Breaker, FIFO Bulkhead, Lock-Free Rate Limiter, Timeout, Fallback, Body-Aware Singleflight, Hooks, Metrics, Health Check — one API, zero deps.

go get github.com/farhanturu/ambatukam-go
client := ambatukam.New(
    ambatukam.WithRetry(...),
    ambatukam.WithCircuitBreaker(...),
    ambatukam.WithBulkhead(...),
    ambatukam.WithRateLimit(...),
    ambatukam.WithFallback(...),
)
0
+
Resilience Patterns
0
External Dependencies
0
+
Goroutine Stress Tests
MIT
Open Source License
Features

Everything for production-grade HTTP

One library replaces 3-5 different packages. Zero dependencies, one consistent API, battle-tested.

🔄

Retry with Backoff

Exponential, constant, or linear backoff with automatic jitter. POST bodies are automatically buffered for safe retry. Supports Retry-After headers. Custom ShouldRetry hook.

Circuit Breaker

Three-state machine — closed, open, half-open. Race-safe with sync.RWMutex and generation counter for stale probe protection.

🚧

FIFO Bulkhead

Worker pool with proper FIFO ordering. MaxQueue=0 for fail-fast mode. Graceful shutdown via client.Close().

🚦

Lock-Free Rate Limiter

Channel-based token bucket — no mutex contention under high concurrency. Perfect for API quotas.

⏱️

Timeout Map

Different timeouts for different URL patterns. Supports * (single segment) and ** (multi segment) wildcards. Set 10s for payments, 5s for users, 1s for health checks.

🛟

Fallback

Return a cached response or friendly error when everything fails. Propagates attempt count from upstream retry errors.

🔗

Body-Aware Singleflight

Deduplicate concurrent requests. GET uses method+URL key. POST/PUT/PATCH includes sha256(body) — never merges different payloads.

📊

Prometheus

Full Prometheus integration with Counter, Gauge, Histogram vectors. All 9 metrics wired to policies.

🏥

Health Check

Built-in /health endpoint with policy status, memory stats, uptime. Background refresh, goroutine cleanup on Close().

📝

Custom Logger

WithCustomLogger(Logger) — implement 4 methods (Debug, Info, Warn, Error) for zerolog, zap, or any logging library.

🪝

Independent Hooks

BeforeRequest and AfterResponse fire on every request — even without WithRetry. OnRetry, OnStateChange, OnFallback are policy-specific.

Quick Start

Get started in 30 seconds

Install the package and you're ready to go.

01

Install the package

go get github.com/farhanturu/ambatukam-go
02

Create a resilient client

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    "github.com/farhanturu/ambatukam-go"
)

func main() {
    client := ambatukam.New(
        ambatukam.WithTimeout(ambatukam.TimeoutConfig{Timeout: 2 * time.Second}),
        ambatukam.WithRetry(ambatukam.RetryConfig{MaxRetries: 3}),
        ambatukam.WithCircuitBreaker(ambatukam.CircuitConfig{FailureThreshold: 5}),
        ambatukam.WithBulkhead(ambatukam.BulkheadConfig{MaxConcurrent: 10}),
        ambatukam.WithRateLimit(ambatukam.RateLimitConfig{Rate: 10, Burst: 5}),
    )
    defer client.Close()

    resp, err := client.Get(context.Background(), "https://api.example.com/users")
    if err != nil { log.Fatal(err) }
    defer resp.Body.Close()
    fmt.Println("status:", resp.StatusCode)
}
03

You're production-ready

Auto-retry with exponential backoff
Circuit opens when service is down
FIFO queue with concurrency limit
Lock-free rate limiting
Timeout per attempt
Examples

Real-world patterns

Common patterns for production applications.

package main

import (
    "context"
    "errors"
    "log"
    "strings"
    "time"
    "github.com/farhanturu/ambatukam-go"
)

func main() {
    client := ambatukam.New(
        ambatukam.WithTimeout(ambatukam.TimeoutConfig{Timeout: 10 * time.Second}),
        ambatukam.WithRetry(ambatukam.RetryConfig{
            MaxRetries: 3,
            Backoff:    ambatukam.ConstantBackoff(500 * time.Millisecond),
        }),
        ambatukam.WithCircuitBreaker(ambatukam.CircuitConfig{FailureThreshold: 5}),
        ambatukam.WithFallback(ambatukam.FallbackConfig{
            Handler: func(req *http.Request, err error) (*http.Response, error) {
                return nil, errors.New("payment service unavailable")
            },
        }),
        ambatukam.WithHooks(ambatukam.Hooks{
            BeforeRequest: func(req *http.Request) error {
                req.Header.Set("Authorization", "Bearer "+stripeKey)
                return nil
            },
        }),
    )
    defer client.Close()

    body := strings.NewReader("amount=2000¤cy=usd")
    resp, err := client.Post(ctx, "https://api.stripe.com/v1/charges", "application/x-www-form-urlencoded", body)
    if err != nil {
        log.Printf("Payment failed: %v", err)
        return
    }
    defer resp.Body.Close()
}
package main

import (
    "context"
    "fmt"
    "time"
    "github.com/farhanturu/ambatukam-go"
)

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    client := ambatukam.New(
        ambatukam.WithRequestID("X-Request-ID"),
        ambatukam.WithSingleflight(),
        ambatukam.WithTimeoutMap(map[string]time.Duration{
            "/api/users/*":  5 * time.Second,
            "/api/orders/*": 10 * time.Second,
        }),
        ambatukam.WithRetry(ambatukam.DefaultRetryConfig()),
        ambatukam.WithHooks(ambatukam.Hooks{
            BeforeRequest: func(req *http.Request) error {
                req.Header.Set("Authorization", "Bearer "+getToken())
                return nil
            },
        }),
    )
    defer client.Close()

    user, err := ambatukam.GetJSON[User](client, ctx, "http://user-service/api/users/123")
    if err != nil { log.Fatal(err) }
    fmt.Printf("User: %s (%s)\n", user.Name, user.Email)
}
package main

import (
    "context"
    "fmt"
    "time"
    "github.com/farhanturu/ambatukam-go"
)

type Weather struct {
    Temperature float64 `json:"temperature"`
    Description string  `json:"description"`
}

func main() {
    client := ambatukam.New(
        ambatukam.WithRateLimit(ambatukam.RateLimitConfig{
            Rate: 5, Burst: 10, WaitTimeout: 2 * time.Second,
        }),
        ambatukam.WithTimeout(ambatukam.TimeoutConfig{Timeout: 30 * time.Second}),
        ambatukam.WithFallback(ambatukam.FallbackConfig{
            Handler: func(req *http.Request, err error) (*http.Response, error) {
                return getCachedData(req.URL.String())
            },
        }),
    )
    defer client.Close()

    weather, err := ambatukam.GetJSON[Weather](client, ctx, "https://api.weather.com/v1/current")
    if err != nil { log.Fatal(err) }
    fmt.Printf("%.1f°C — %s\n", weather.Temperature, weather.Description)
}
package main

import (
    "net/http"
    "github.com/farhanturu/ambatukam-go"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
    requestsTotal := prometheus.NewCounterVec(
        prometheus.CounterOpts{Name: "http_requests_total"},
        []string{"method", "url", "status"},
    )
    circuitState := prometheus.NewGaugeVec(
        prometheus.GaugeOpts{Name: "circuit_breaker_state"},
        []string{"name"},
    )
    prometheus.MustRegister(requestsTotal, circuitState)

    recorder := ambatukam.NewPrometheusRecorder(ambatukam.PrometheusConfig{
        RequestsTotal: requestsTotal,
        CircuitState:  circuitState,
    })

    client := ambatukam.New(
        ambatukam.WithRetry(ambatukam.RetryConfig{MaxRetries: 3}),
        ambatukam.WithCircuitBreaker(ambatukam.CircuitConfig{FailureThreshold: 5}),
        ambatukam.WithMetrics(recorder),
    )
    defer client.Close()

    http.Handle("/health", client.HealthChecker().Handler())
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(":8080", nil))
}
package main

import (
    "context"
    "fmt"
    "time"
    "github.com/farhanturu/ambatukam-go"
)

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    client := ambatukam.New(
        ambatukam.WithTimeout(ambatukam.TimeoutConfig{Timeout: 5 * time.Second}),
        ambatukam.WithRetry(ambatukam.RetryConfig{MaxRetries: 3}),
    )
    defer client.Close()

    user, err := ambatukam.GetJSON[User](client, ctx, "https://api.example.com/users/1")
    if err != nil { log.Fatal(err) }
    fmt.Printf("User: %s (%s)\n", user.Name, user.Email)

    created, err := ambatukam.PostJSON[User](client, ctx, "https://api.example.com/users",
        User{Name: "John", Email: "john@example.com"})
    if err != nil { log.Fatal(err) }
    fmt.Printf("Created: %s (ID: %d)\n", created.Name, created.ID)
}
package main

import (
    "github.com/farhanturu/ambatukam-go"
)

func main() {
    // Production — balanced defaults
    prod := ambatukam.New(ambatukam.ProductionConfig()...)
    defer prod.Close()

    // Aggressive — fast-fail for fragile services
    aggressive := ambatukam.New(ambatukam.AggressiveConfig()...)
    defer aggressive.Close()

    // Conservative — generous for critical services
    conservative := ambatukam.New(ambatukam.ConservativeConfig()...)
    defer conservative.Close()
}
Battle-Tested

Stress tested with 1000 goroutines

20 stress tests covering DDoS-level concurrency, chaos servers, circuit breaker state transitions, and full-stack integration.

💥

DDoS Bulkhead

500 goroutines, 10 concurrent. Verifies FIFO ordering and fail-fast denial under extreme load.

🌊

DDoS Full Stack

1000 goroutines with chaos server (50% fail, random delay). All policies working together.

🔀

Circuit Breaker Cycles

5 cycles of open/close transitions with 20 concurrent goroutines each. Race-safe state machine.

🎯

Singleflight Dedup

20 goroutines, same URL. Verifies only 1 backend hit, 20 successful responses.

🪝

Hooks Verification

50 goroutines. Verifies BeforeRequest and AfterResponse fire exactly 50 times each.

🏥

Chaos Server

Flaky, slow, down, rate-limited, recovery servers. Tests every failure mode in production.

Comparison

Why choose Ambatukam Go?

One library replaces 3-5 different packages.

Feature Ambatukam Go failsafe-go go-retryablehttp sony/gobreaker
Retry
Circuit Breaker
FIFO Bulkhead
Lock-Free Rate Limiter
Timeout Map (wildcards)
Fallback
Body-Aware Singleflight
Health Check
Prometheus
Custom Logger
Independent Hooks
Stress Tested (1000 goroutines)
Zero Deps

Ready to supercharge
your HTTP client?

Start using Ambatukam Go today. Production-grade, battle-tested, zero dependencies.