Reliability
zyn integrates with pipz for production-grade reliability patterns.
Available Options
synapse, _ := zyn.Binary("question", provider,
zyn.WithRetry(3), // Retry on failure
zyn.WithBackoff(3, 100*time.Millisecond), // Retry with backoff
zyn.WithTimeout(10*time.Second), // Timeout protection
zyn.WithCircuitBreaker(5, 30*time.Second), // Circuit breaker
zyn.WithRateLimit(10, 100), // Rate limiting
zyn.WithFallback(backupSynapse), // Fallback synapse
zyn.WithErrorHandler(errorPipeline), // Custom error handling
)
Retry
Automatically retry failed calls:
// Simple retry (up to 3 attempts)
zyn.WithRetry(3)
// With exponential backoff
// Attempts with delays: 100ms, 200ms, 400ms, ...
zyn.WithBackoff(3, 100*time.Millisecond)
When to use:
- Transient failures (network blips)
- Rate limit errors (429)
- Provider temporary errors (503)
Best practices:
- Keep attempts low (2-3) to avoid cost explosion
- Use backoff for rate limits
- Combine with timeout to bound total duration
Timeout
Bound maximum execution time:
zyn.WithTimeout(10 * time.Second)
When to use:
- Always. LLM calls can hang indefinitely
- User-facing requests with latency requirements
- Background jobs with resource constraints
Guidelines:
- Simple queries: 5-10 seconds
- Complex reasoning: 30-60 seconds
- Batch processing: longer, but always bounded
Circuit Breaker
Stop calling a failing provider:
// Open after 5 failures, try again after 30 seconds
zyn.WithCircuitBreaker(5, 30*time.Second)
States:
- Closed - Normal operation, failures counted
- Open - Fails immediately, no provider calls
- Half-Open - After recovery time, tries one request
When to use:
- Provider outages
- Protecting downstream systems
- Cost control during failures
Rate Limiting
Control request throughput:
// 10 requests per second, burst of 100
zyn.WithRateLimit(10, 100)
When to use:
- Respecting provider rate limits
- Controlling costs
- Fair resource sharing
Note: Rate limiters are per-synapse. For global limits, share a rate limiter instance.
Fallback
Use a backup synapse on failure:
// Create backup synapse (different provider)
backupSynapse, _ := zyn.Binary("question", backupProvider)
// Primary with fallback
synapse, _ := zyn.Binary("question", primaryProvider,
zyn.WithFallback(backupSynapse),
)
Use cases:
- Multi-provider redundancy
- Graceful degradation (fall back to simpler model)
- A/B testing with fallback
Error Handling
Custom error processing:
import "github.com/zoobz-io/pipz"
// Define identity for the error handler
var logErrorsID = pipz.NewIdentity("log-errors", "Logs synapse errors")
errorHandler := pipz.Apply(logErrorsID,
func(ctx context.Context, e *pipz.Error[*zyn.SynapseRequest]) (*pipz.Error[*zyn.SynapseRequest], error) {
log.Printf("Synapse error: %v", e.Err)
metrics.Increment("synapse_errors")
return e, nil
},
)
synapse, _ := zyn.Binary("question", provider,
zyn.WithErrorHandler(errorHandler),
)
Combining Options
Options compose naturally:
synapse, _ := zyn.Classification("classify", categories, provider,
// Retry with backoff for transient failures
zyn.WithBackoff(3, 100*time.Millisecond),
// Timeout to bound total duration
zyn.WithTimeout(30*time.Second),
// Circuit breaker for provider outages
zyn.WithCircuitBreaker(5, 60*time.Second),
// Rate limit to stay within quotas
zyn.WithRateLimit(10, 50),
// Fallback to backup provider
zyn.WithFallback(backupSynapse),
)
Execution order:
Request → RateLimit → CircuitBreaker → Timeout → Retry → Provider
Recommended Configurations
User-Facing API
zyn.WithRetry(2),
zyn.WithTimeout(10*time.Second),
zyn.WithCircuitBreaker(3, 30*time.Second),
Background Processing
zyn.WithBackoff(5, 500*time.Millisecond),
zyn.WithTimeout(60*time.Second),
zyn.WithRateLimit(5, 20),
High-Availability
zyn.WithRetry(2),
zyn.WithTimeout(15*time.Second),
zyn.WithCircuitBreaker(5, 30*time.Second),
zyn.WithFallback(backupSynapse),
Session Behavior
Sessions are transactional with reliability options:
session := zyn.NewSession()
// Even with 3 retries, session only updates once on success
synapse, _ := zyn.Binary("q", provider, zyn.WithRetry(3))
synapse.Fire(ctx, session, "input")
// If all retries fail, session is unchanged
// If any retry succeeds, session has exactly 2 messages
Next Steps
- Observability Guide - Monitor reliability behavior
- Testing Guide - Test reliability patterns
- pipz Documentation - Full pipeline reference