Skip to main content

Overview

Bifrost provides three key performance configuration parameters that control throughput, memory usage, and request handling behavior:
These defaults are suitable for most production deployments handling up to ~5000 RPS. For higher throughput or constrained environments, tuning these parameters can significantly improve performance.

Understanding the Parameters

Concurrency (Per Provider)

What it does: Controls two aspects of provider performance:
  1. Worker Goroutines: The number of goroutines that process requests for each provider. Each worker pulls requests from the provider’s queue and executes them against the provider’s API.
  2. Provider Pool Pre-warming: Pre-allocates provider-specific response objects (e.g., AnthropicMessageResponse, OpenAIResponse) in sync pools to reduce allocations during request handling.
Impact:
  • Higher concurrency = More parallel requests to the provider, higher throughput, more pre-allocated response objects
  • Lower concurrency = Fewer parallel requests, lower resource usage, respects provider rate limits
Default: 1000 workers per provider

Buffer Size (Per Provider)

What it does: Sets the capacity of the buffered channel (queue) for each provider. Incoming requests are queued here before being picked up by workers. Impact:
  • Larger buffer = More requests can be queued during traffic spikes, handles burst traffic better
  • Smaller buffer = Lower memory footprint, faster backpressure signals to clients
Default: 5000 requests per provider queue Queue Full Behavior: Controlled by drop_excess_requests:
  • false (default): New requests block until queue space is available
  • true: New requests are immediately dropped with an error when queue is full
Constraint: Buffer size must be greater than or equal to concurrency. If concurrency > buffer_size, provider setup will fail.

Initial Pool Size (Global)

What it does: Controls the number of pre-allocated objects in Bifrost’s internal sync pools at startup. These pools recycle objects to reduce garbage collection overhead. Pooled Objects:
  • Channel messages (request wrappers)
  • Response channels
  • Error channels
  • Stream channels
  • Plugin pipelines
  • Request objects
Impact:
  • Higher initial pool = Less GC pressure during high traffic, more consistent latency, higher initial memory usage
  • Lower initial pool = Lower initial memory footprint, may cause more allocations under load
Default: 5000 objects per pool

Sizing Guidelines

Concurrency & Buffer Size (Per Provider)

Configure these settings per provider based on the expected RPS for that specific provider:
Example: If you expect 2000 RPS to OpenAI and 500 RPS to Anthropic, configure OpenAI with concurrency: 2000, buffer_size: 3000 and Anthropic with concurrency: 500, buffer_size: 750.
Formula:
This ratio ensures:
  • Enough queue capacity to absorb traffic bursts
  • Workers are never starved for work
  • Backpressure is applied before memory exhaustion

Initial Pool Size (Global)

Configure this setting based on total RPS across all providers combined:
Memory estimates are approximate and vary based on request/response sizes, number of providers, and plugins. Monitor actual memory usage in your environment.
Formula:
Additionally, ensure:
This ensures pools are pre-warmed to handle peak queue depths without runtime allocations.

Multi-Node Deployments

When running multiple Bifrost instances behind a load balancer, divide the per-node settings by the number of nodes based on your total expected RPS.

Formula

Example: 10,000 RPS Across 4 Nodes

Total capacity (aggregate across all 4 nodes):
  • Total RPS: 10,000 RPS
  • Per-node RPS: ~2,500 RPS per node
Single node settings for 10,000 RPS (if running on one node):
  • Concurrency: 10000
  • Buffer Size: 15000
  • Initial Pool Size: 15000
Per-node settings (4 nodes, 10,000 RPS total):
Kubernetes Horizontal Pod Autoscaling: When using HPA, configure settings for your minimum replica count. As pods scale up, each node handles a smaller portion of traffic. Consider using environment variables or ConfigMaps to dynamically adjust settings based on replica count.

Provider-Specific Tuning

Different providers have different rate limits and latency characteristics. Tune each provider independently:

Provider Rate Limit Considerations

Example: Mixed Provider Configuration


Queue Overflow Handling

When the provider queue reaches capacity, Bifrost’s behavior is controlled by drop_excess_requests:

Blocking Mode (Default)

  • New requests wait until queue space is available
  • Ensures no requests are lost
  • May increase latency during high load
  • Suitable for critical workloads where every request matters

Drop Mode

  • New requests are immediately rejected when queue is full
  • Returns error: "request dropped: queue is full"
  • Maintains consistent latency for accepted requests
  • Suitable for real-time applications where stale requests are useless
Best Practice: Use drop_excess_requests: true with buffer sizes at 1.5x concurrency for production workloads. This prevents memory exhaustion while still handling reasonable traffic bursts.

Monitoring and Diagnostics

Key Metrics to Monitor

Health Check Endpoint

The Gateway exposes health and metrics endpoints:

Best Practices Summary

Start Conservative

Begin with lower values and scale up based on observed performance. Over-provisioning wastes resources.

Monitor Continuously

Track queue depths, latencies, and error rates. Adjust settings based on real traffic patterns.

Match Provider Limits

Don’t set concurrency higher than provider rate limits allow. You’ll just get rate-limited.

Plan for Bursts

Set buffer_size to 1.5x concurrency to handle traffic spikes without dropping requests.

Quick Reference