Talk stream for each live conversation and keeps that stream attached to one backend replica until the conversation ends.
Use a stable load-balanced endpoint as your AgentKit URL, such as agent.your-domain.com:50051. Scale the backend replicas behind that endpoint.
Active conversations are distributed when new streams are created. An active stream is not moved between replicas during the conversation.
Capacity benchmark per instance
There is no universal conversations-per-pod number. Capacity depends on your runtime, LLM latency, tool latency, memory use, streaming behavior, and how much state you keep in the process. Benchmark each AgentKit backend shape before setting production autoscaling limits. Track these metrics during a load test:
Use the highest stable conversation count that keeps latency and error rate inside your SLO, then add headroom.
safe_conversations_per_pod with your measured benchmark.
Text-only EC2 benchmark
Use this benchmark only for a text-only AgentKit backend. In this benchmark:- One active conversation means one open AgentKit
Talkstream. - Rapida handles telephony, audio, STT, and TTS.
- Your AgentKit backend receives text and returns text.
- The benchmark backend does not call an LLM, database, workflow engine, or external tool.
- Each message is small, usually under
4 KB. - Each active conversation sends one user message every
10to15seconds. - A passing test keeps CPU under
60%, memory under70%, and stream errors under0.1%.
The numbers below are safe starting targets for capacity planning. They are not hard limits. Measure your own backend before using these numbers for a production commitment.
SDK concurrency knobs
AgentKit SDKs expose concurrency differently.
Use
max_workers guidance only for the Python SDK. For Node.js, use process and pod counts as the concurrency unit.
If you use Node.js, Go, or async Python, start with these targets:
Read the table like this:
max_workers. Each open stream can occupy a worker thread, so the safe active conversation count is close to the worker count.
Use this process to find your real number:
- Start at the target in the table.
- Keep all streams open for at least
30minutes. - Send one user message per conversation every
10to15seconds. - Increase active conversations by
25%. - Stop when CPU exceeds
60%, memory exceeds70%, p95 response latency increases sharply, or stream errors exceed0.1%. - Use the last passing value as your measured capacity.
- Plan production at
70%of measured capacity so you have headroom.
10,000 active streams on one host:
- raise
ulimit -nfor the AgentKit process - confirm proxy and server HTTP/2 max stream settings
- tune keepalive and idle timeouts across the load balancer, proxy, and server
- use connection draining before deploys
- track per-stream memory with production logging enabled
Horizontal scaling
Run multiple AgentKit backend replicas behind one gRPC-aware load balancer. Recommended production shape:- Run AgentKit on Kubernetes, ECS, Nomad, or another orchestrator that supports health checks and rolling deploys.
- Put a gRPC-capable load balancer or service mesh in front of the replicas.
- Configure the Rapida AgentKit endpoint to the load-balanced address.
- Keep per-conversation state either stream-local or in an external store such as Redis or Postgres.
- Drain replicas before deployment so existing streams can finish.
max_workers based on your benchmark and blocking behavior:
max_workers setting. Run more Node.js processes, pods, or instances when you need more concurrency. Expose health checks for Kubernetes or the load balancer:
Traffic distribution by tenant or dynamic value
You can route AgentKit traffic dynamically with metadata and a gRPC-aware L7 proxy. Rapida sends saved AgentKit metadata on theTalk stream. For outbound calls, you can override or add metadata for one conversation with agentkit.metadata.
- Rapida dials one stable AgentKit endpoint.
- The gRPC proxy inspects request metadata.
- The proxy routes the new
Talkstream to the matching backend pool. - The stream stays on that backend replica until the conversation ends.
- tenant-specific backend pools
- regional routing
- premium or regulated customer isolation
- model-tier routing
- canary releases by tenant or percentage
tenant, region, or tier. If metadata can be influenced by customer input, validate or sign it before using it for authorization or isolation.
NGINX metadata routing
Use NGINX as an L7 gRPC proxy when you want one public AgentKit endpoint and multiple backend pools. This example routes by the AgentKit metadata keytenant:
Kubernetes NGINX router
A KubernetesService can load balance between pods, but it cannot inspect AgentKit metadata. To route by metadata, run a gRPC-aware proxy such as NGINX in front of tenant-specific AgentKit services.
This example creates one public router service and two internal tenant backend services:
agentkit-acmeagentkit-globex
Deployment and Service. The router selects the service based on metadata; the selected service then load-balances across that tenant’s pods.
Service and Deployment for each pool you reference in the NGINX map.
External references:
Retries, failover, and draining
Retries are safe only before a stream is established. Once a conversation is active, retrying on another replica can duplicate tool calls or lose in-memory conversation state unless your backend is designed for resumability. Recommended retry policy:
Production recommendations:
- Set
connectTimeoutMslow enough to fail over quickly during startup, but high enough for your private network. - Keep
keepaliveTimeMsandkeepaliveTimeoutMsaligned with your proxy and firewall timeouts. - Use readiness checks that fail before shutdown so new streams stop landing on draining pods.
- Set a termination grace period long enough for normal conversations to finish.
- Make tool calls idempotent with a stable
tool_idwhere possible. - Store critical conversation state outside the process if the business requires recovery from pod failure.
Customer checklist
- Benchmark safe active conversations per pod before production traffic.
- Configure Rapida with a load-balanced
agentKitUrl. - Use TLS and metadata-based auth for production.
- Route by metadata only through a gRPC-aware L7 proxy.
- Scale on active streams, latency, CPU, memory, and downstream provider limits.
- Drain pods before deploys.
- Treat active-stream failover as an application-level feature, not a load-balancer feature.