Skip to content
back to the cosmos

Realtime voice, under 200ms

VoiceOps AI

A real-time voice-streaming backend holding sub-200ms latency across 100+ concurrent sessions — WebSocket ingest, Kafka consumer groups, and Kubernetes HPA that autoscales on consumer lag.

A live voice stream never pauses — audio keeps arriving whether the backend is ready or not. VoiceOps had to run streaming inference on that audio and return results inside a conversational budget (sub-200ms), and hold it not for one stream but for 100+ at once, where any backpressure at the source is a dropped call, not a queued job.

end-to-end latency
<200ms
per session
concurrent sessions
100+
autoscaling
consumer-lag
Kubernetes HPA
transport
WebSockets
Kafka fanout

the bar it had to clear

how it actually works

consumelagscaleWebSocketper sessionKafkaconsumer groupsStreaming inferenceworker poolK8s HPAscale on lagDatastoresPostgres · Mongo · RedisObservabilitylag · P95WS out100+ sessions

hover or tab a step to see how it works — or trace a route above.

  1. 01

    Ingress that never waits

    Live audio streams in over WebSockets, one connection per session. Backpressure here is a dropped call — the pipeline absorbs or sheds, it never blocks the source.

  2. 02

    Decouple ingest from inference

    Each session’s frames are published to Kafka; consumer groups fan the work out to a pool of inference workers, so a slow worker creates lag — not a dropped call.

  3. 03

    Output before input ends

    Inference runs in a streaming fashion — results begin flowing before a session’s audio ends. That overlap is where the sub-200ms budget is won.

  4. 04

    The sub-200ms promise<200ms

    Results stream back per session at sub-200ms end-to-end, 100+ sessions at a time.

watch it listen

Realtime speech opens a voice-activity gate, then streams. Hit speak — it detects the voice and transcribes token-by-token.

idle

Illustrative — the transcript streams token-by-token, the way the realtime pipeline works. The real budget lives in the numbers above: sub-200ms end-to-end across 100+ concurrent sessions.

the problem

Live audio is relentless — a voice stream never stops to let the backend catch up. VoiceOps had to run streaming inference on that audio and deliver results at conversational latency across 100+ simultaneous sessions, where a naive synchronous pipeline either falls behind under load or drops frames at the source.

the approach

  • Audio streams in over WebSockets; each session’s frames are published to Kafka, whose consumer groups fan the work out to a pool of inference workers.
  • Inference runs in a streaming fashion — results begin flowing before a session’s audio ends, which is where the latency budget is won.
  • Kubernetes HPA autoscales the worker pool on Kafka consumer lag — the most honest backlog signal — so capacity tracks real demand, not CPU guesses.
  • State and results land in PostgreSQL, MongoDB, and Redis; consumer lag and P95 latency are tracked across the pipeline so regressions surface before users feel them.

the calls that mattered

Every architecture is a set of trade-offs taken on purpose. These are the load-bearing ones.

Fan out over Kafka consumer groups, not a synchronous call.

A voice stream can’t wait on a busy worker. Publishing frames to Kafka and consuming them in groups decouples ingest from inference, so a slow worker creates lag — a number you can scale on — instead of a dropped call.

the trade-offA broker in the hot path and delivery semantics to reason about — accepted because it turns backpressure into an observable, scalable signal.

Autoscale on consumer lag, not CPU/GPU utilization.

Utilization lies under bursty streaming load; Kafka consumer-group lag measures work actually waiting — which is what latency is made of. Kubernetes HPA scales the worker pool on lag.

the trade-offNeeds lag-based HPA tuning and a broker to watch — more moving parts, for autoscaling that tracks the latency users actually feel.

Stream results — emit before the session ends.

Waiting for a full utterance blows the sub-200ms budget by construction. Streaming inference overlaps “still listening” with “already responding” — the overlap IS the latency win.

the trade-offDownstream consumers must handle incremental, revisable output instead of one final blob — a harder contract for a far lower latency.

what shipped

VoiceOps holds sub-200ms latency across 100+ concurrent voice sessions — WebSocket ingest, Kafka consumer groups, and Kubernetes HPA autoscaling on consumer lag, backed by PostgreSQL, MongoDB, and Redis. Consumer lag and P95 latency are tracked across the distributed pipeline, so the tail budget holds through traffic bursts.

what’s next

  • Speaker diarization on the stream so multi-party sessions are attributed per-voice.
  • Adaptive batching under load — trade a few ms of latency for throughput only when lag rises.
  • Per-session backpressure policies so a slow consumer degrades gracefully instead of dropping.

built with

KafkaWebSocketsKubernetesFastAPIPostgreSQLMongoDBRedis