← Back to Building Elle

Capacity & cost study LetsTalk / Elle · 27 Aug 2026

Elle at Call-Center Scale

What it takes to go from 43 calls a month to a quarter of a million, what a full-duplex interaction model changes, and what each option costs per minute with every fee counted.

01 The short answer

Cost is not what stops this system from handling call-center volume. State is. The arithmetic below matters, but it is the second problem.

  1. A duplex model deletes two thirds of the per-minute bill. In the current stack, speech-out and the language model are 68% of the compute cost. A speech-to-speech model has neither line: one model hears audio and emits audio. Cascade with Opus 5 is $0.0446 a call-minute; Gemini Live is $0.0228.1

  2. Self-hosting PersonaPlex is not a cost play. On an H100 at eight concurrent streams it costs $0.0355 per stream-minute in GPU time alone, more than the entire managed duplex stack. It becomes cheaper only past roughly twelve streams per GPU, or on small GPUs that scale to zero. The case for it is control, not price.2

  3. One unmeasured number decides the whole question. Concurrent streams per GPU. Every published figure I could find for a Moshi-class model is second-hand. Measure it before committing to hardware; the answer moves the monthly bill by 8×.

02 What breaks first

Elle today takes about 43 calls a month and never sees two at once. The ceilings below are ordered by when they bite, and the first three are in our own code rather than in anyone's pricing page.

CeilingBites atWhyFix
Per-instance state 2 instances SQLite lives on the container's own disk. Two Cloud Run instances hold two different databases: caller history, consent, and the architecture override disagree depending on which one answers. Move to Cloud SQL or Firestore. The GCS archive made history durable; it did not make it shared.
Double-booking ~5 concurrent Booking reads free/busy, then writes. Two callers offered the same slot both pass the check before either writes. A short-lived hold row with a unique constraint on the slot, taken before the calendar write.
No overflow path capacity When capacity runs out the caller gets silence. There is no queue, no callback offer, no "we are busy" branch. A TwiML fallback that offers a callback and captures the number.
Vendor concurrency ~10–50 Twilio caps concurrent calls per account, Deepgram caps concurrent streams, and Anthropic rate limits are per-organisation. Raise all three by ticket before a launch, not during one.
Cold start under burst ~25 concurrent One min-instance. A burst above what one container holds starts new ones while callers are already on the line. Min-instances tracking the busy-hour floor, not one.

Ordered by the concurrency at which each becomes a live incident. Concurrency estimates assume 3.5-minute calls arriving over an eight-hour business day with a 2.5× busy-hour peak.3

Worth saying plainly

None of the first three cost money to fix. They are a week of work, and they are load-bearing for every number in the rest of this document, because a cheaper per-minute price on a system that loses bookings is not cheaper.

03 Three ways to answer a phone

The cascade, which is what runs today. Audio goes to Deepgram for transcription, the transcript goes to Claude, Claude's text goes back to Deepgram for speech. Three vendors, three network hops, and a turn cannot start until silence is detected. Our endpointing is set to 1000 ms, so every reply carries a full second of dead air before any model has been asked anything. Realistic turn latency is 1.2 to 2.0 seconds.

Managed duplex. Gemini Live on Vertex takes audio in and gives audio out from a single model that is listening and speaking at the same time. There is no endpointing parameter because there is no endpoint: interruption is a property of the model, not of a timer. We already run this; it is one of the three providers behind the runtime switch.

Self-hosted duplex. PersonaPlex is NVIDIA's full-duplex conversational speech model, built on the Moshi architecture, with role prompts for persona and audio conditioning for voice.4 Code is MIT; weights are under the NVIDIA Open Model License and gated behind accepting terms on Hugging Face. It runs on our hardware, which is the entire point: the voice can be cloned and fixed, the persona is a prompt we own, no audio leaves the project, and there is no per-minute meter.

04 What a call-minute costs

telephony speech in speech out model + bridge GPU
Cost per call-minute by architecture, split into telephony, speech in, speech out, model and GPU $0.00 $0.01 $0.02 $0.03 $0.04 $0.05 Cascade + Opus 5 Cascade + Opus 5 — telephony: $0.0085/min Cascade + Opus 5 — speech-in: $0.0058/min Cascade + Opus 5 — speech-out: $0.0135/min Cascade + Opus 5 — model: $0.0168/min $0.0446 Cascade + Haiku 4.5 Cascade + Haiku 4.5 — telephony: $0.0085/min Cascade + Haiku 4.5 — speech-in: $0.0058/min Cascade + Haiku 4.5 — speech-out: $0.0135/min Cascade + Haiku 4.5 — model: $0.0040/min $0.0318 Gemini Live duplex Gemini Live duplex — telephony: $0.0085/min Gemini Live duplex — model: $0.0143/min $0.0228 PersonaPlex on L4 PersonaPlex on L4 — telephony: $0.0085/min PersonaPlex on L4 — model: $0.0040/min PersonaPlex on L4 — gpu: $0.0086/min $0.0211 PersonaPlex on H100 PersonaPlex on H100 — telephony: $0.0085/min PersonaPlex on H100 — model: $0.0040/min PersonaPlex on H100 — gpu: $0.0355/min $0.0479

US dollars per call-minute, marginal cost only; the monthly floor is in §05. Assumes a 3.5-minute call, the assistant speaking half of it at 150 words per minute, and two model turns a minute.5 GPU figures assume eight concurrent streams per GPU at 65% utilisation.2

Two things fall out of this. Speech-out is the most expensive line in the cascade at $0.0135 a minute, more than double speech-in, because Aura-2 bills per character and the assistant does half the talking.6 And the model line swings 5× on model choice alone: Opus 5 costs $0.0168 a call-minute against Haiku 4.5's $0.0040.7

Which means the cheapest available change to the current system is not architectural. Moving the SMS and booking turns to Haiku 4.5 while leaving Opus 5 on the calls that need judgment takes 29% off the per-minute bill, today, with no new infrastructure.

05 The monthly bill

Architecture 1k min 10k min 100k min 1M min $/min at 1M
Cascade + Opus 5today's stack $151$553$4,572 $45,704$0.0457
Cascade + Haiku 4.5one config change $139$425$3,292 $32,904$0.0329
Gemini Livemanaged duplex, Vertex $130$335$2,392 $23,904$0.0239
PersonaPlex on L4Cloud Run GPU, scales to zero, 2 streams/GPU $128$319$2,224 $22,220$0.0222
PersonaPlex on H100GKE, autoscaled, 8 streams/GPU $8,354$8,786 $13,140$57,745$0.0577
PersonaPlex on H100GKE, reserved for peak, 3-year commit $3,861$3,974 $12,404$123,202$0.1232

All-in monthly cost. Every row includes telephony, the model, the Cloud Run bridge, and the fixed floor: a phone number,8 always-allocated min-instances,9 Secret Manager,10 logging,11 the GCS call archive,12 Artifact Registry,13 and egress to Twilio.14 GKE rows add the cluster fee, a load balancer, and node boot disks.15 What is deliberately not counted is at note 16.16

The last row is the trap, and it is the one a vendor will steer you toward. A three-year commitment discounts the hourly rate by 55%, but you must reserve for the busy-hour peak and then pay for all 730 hours in the month. With a 2.5× peak factor that is 2.5× the hardware you average, running idle most of the time. Committed pricing turns a utilisation problem into a contract.

Autoscaling inverts it: you pay for what you use, but the warm floor that keeps first callers off a cold GPU costs $8,074 a month on one H100 whether anyone calls or not. At 1,000 minutes a month that floor is the entire bill, which is why the H100 row starts at $8,354 and the managed row starts at $130.

06 Where the crossover is

three-layer cascade managed duplex self-hosted duplex dashed = second option in that family
All-in cost per call-minute against monthly call volume, both scales logarithmic $0.02 $0.05 $0.1 $0.25 $0.5 $1 $2.5 $5 $10 1k 10k 100k 1M PersonaPlex H100 Cascade + Opus 5 Cascade + Haiku Gemini Live PersonaPlex L4 call-minutes per month

All-in cost per call-minute against monthly volume, both axes logarithmic. The fixed floor dominates below 10k minutes, which is why every line falls steeply and then flattens. Above about 30k minutes the lines are flat and the ranking stops changing.

Below 10,000 minutes a month, architecture is nearly irrelevant: you are paying for a warm container and a phone number, and the difference between the best and worst option is $24 a month. Above 30,000 the marginal rate is all that matters and the order is fixed.

The H100 line never catches the others at these volumes. It is still falling at 1M minutes because the warm floor is still amortising; it would cross Gemini Live somewhere past 4M minutes a month, which is a 40-seat call center running flat out.

07 The number that decides it

Everything above rests on how many concurrent conversations one GPU holds while staying real-time. A Moshi-class model needs roughly 16–20 GB in fp16, which fits an L4's 24 GB with no room for KV cache growth, and fits an H100's 80 GB with room to batch. Published guidance suggests four to eight sessions on a 48–80 GB card, but that figure is second-hand and I could not reach the paper to confirm it.4 Treat the table below as the shape of the answer, not the answer.

Streams per GPU L4, Cloud Run A100 40 GB H100 on demand H100 3-yr commit vs. Gemini Live at $0.0135
2$0.0086$0.0471 $0.1418$0.0638 L4 only
4$0.0043$0.0235 $0.0709$0.0319 L4 only
8$0.0022$0.0118 $0.0354$0.0160 L4, A100
12$0.0014$0.0078 $0.0236$0.0106 everything but on-demand H100
16$0.0011$0.0059 $0.0177$0.0080 everything but on-demand H100

GPU cost per stream-minute at 65% utilisation.2 The rightmost column names the hardware that beats managed duplex on compute at that density.

Measuring this is two days of work and it is the highest-value two days in the whole plan: stand one GPU up, drive N synthetic conversations at it from recorded call audio, and find the N at which time-to-first-audio crosses 300 ms or the model starts falling behind real-time. The answer sets the hardware, the fleet size, and whether this is worth doing at all.

08 What integration actually costs us

The provider seam is already there. Realtime models sit behind one interface with three implementations, chosen per call, with a runtime override and a TTL. Adding a fourth is one file and one enum value.

src/realtime/
  factory.ts          VoiceProvider = "deepgram" | "openai" | "gemini" | "personaplex"
  personaPlex.ts      new: WebSocket to the inference service, PCM16 in and out
  audio/g711.ts       already converts mu-law 8 kHz to PCM16 and resamples 8k to 24k

The audio plumbing is done. Gemini Live already needs PCM16 in at 16 kHz and out at 24 kHz, so the stateful resampler with carries across chunk boundaries already exists and is already verified. PersonaPlex speaks the same shape.

The part that is genuinely new

A speech-to-speech model does not emit tool calls. Elle's job is booking: she checks a calendar, writes a hold, sends a confirmation. PersonaPlex will happily discuss a Thursday appointment and cannot make one.

The pattern that solves it is a supervisor. The duplex model owns the conversation; its transcript stream feeds a cheap text model that owns the tools and writes results back into the duplex model's context as it goes. That keeps the latency win, because the caller hears the duplex model immediately while the booking resolves behind it, and it costs one Haiku turn per exchange, which is the $0.0040 a minute already in the tables.

It also means the failure modes multiply. The supervisor can lag the conversation, and the caller can be told a slot is held a second before the write fails. That needs designing, not discovering.

09 What I would do

StageTriggerWorkCost impact
Fix the state Before any volume at all Shared database, a booking lock, an overflow branch. Nothing else on this list is safe without it. ~$40/mosmallest Cloud SQL instance
Split the models Now Haiku 4.5 on SMS and booking turns, Opus 5 on calls. One config change. −29%
Move calls to duplex Past 10k min/mo Flip the runtime switch to Gemini Live for voice, keep the cascade as the fallback provider. Both already exist. −46%
Benchmark PersonaPlex Past 50k min/mo, or any voice/persona requirement Gemini cannot meet One GPU, synthetic load, find streams-per-GPU. Two days. ~$500one-off
Self-host Only if the benchmark clears 12 streams per GPU, or control is worth the premium Supervisor pattern, GPU autoscaling, a real on-call rotation. This is where you start operating infrastructure rather than consuming it. see §05

Triggers are volumes, not dates. Nothing here needs doing before the volume that justifies it, except the first row, which needs doing regardless.

The honest summary

At today's volume, managed duplex is cheaper, lower-latency, and less work than anything we would host. Self-hosting PersonaPlex is worth doing when we need a voice and a persona that are ours, when audio cannot leave the project, or when a vendor's per-minute rate becomes a negotiating position we do not like. Those are good reasons. Saving money at 100,000 minutes a month is not one of them.

10 Rates, sources, assumptions

Every figure in this document derives from the constants below. All are US list prices in us-central1 as published in August 2026, before any negotiated discount. The model that produces the tables is in the repository at tools/scale-model.py, so a rate change is a one-line edit and a rerun.

  1. Cascade against duplex. Cascade + Opus 5 marginal cost is telephony $0.0085 + speech-in $0.0058 + speech-out $0.0135 + model and bridge $0.0168 = $0.0446. Gemini Live is telephony $0.0085 + model and bridge $0.0143 = $0.0228. Speech-out plus model is $0.0303 of $0.0446, or 68%.
  2. GPU cost per stream-minute. rate ÷ streams ÷ 60 ÷ utilisation. Rates: a3-highgpu-1g (1×H100 80 GB) $11.06/hr on demand; a2-highgpu-1g (1×A100 40 GB) ~$3.67/hr; Cloud Run L4 $0.0001867/GPU-second, or $0.672/hr, without zonal redundancy; 3-year committed use discount taken at 55% off. Utilisation is 65%, which allows for scale-up lag and partially filled GPUs. At eight streams on an on-demand H100 that is 11.06 / 8 / 60 / 0.65 = $0.0354. GCP GPU instance pricing, Cloud Run pricing.
  3. Concurrency. Business-hour wall clock is 8 h × 22 days = 10,560 minutes a month. Average concurrency is monthly minutes divided by that; peak is 2.5× average. At 100k minutes: 9.5 average, 24 peak. At 1M: 94.7 average, 237 peak. Average call length 3.5 minutes.
  4. PersonaPlex. NVIDIA, built on the Moshi architecture and weights, with role-prompt persona control and audio-conditioned voice. Code MIT, weights under the NVIDIA Open Model License with terms accepted on Hugging Face. Memory and concurrency figures for Moshi-class models are from secondary sources; arxiv.org was unreachable from this network, so the paper's own latency and throughput claims are not verified here. github.com/NVIDIA/personaplex.
  5. Conversation shape. 3.5-minute call; assistant speaks 50% of it; 150 words per minute, taken as 900 characters per spoken minute; two model turns per minute; per turn 6,000 cached input tokens, 400 fresh input tokens, 120 output tokens. Cached input billed at 0.1× input.
  6. Deepgram. Nova-3 multilingual streaming $0.0058/min (monolingual $0.0048). Aura-2 $0.030 per 1,000 characters, so 450 characters a call-minute is $0.0135. Aura-2.
  7. Language models. Claude Opus 5 $5.00 in / $25.00 out per million tokens; Claude Haiku 4.5 $1.00 / $5.00. Per call-minute at two turns: Opus 5 $0.0160, Haiku 4.5 $0.0032; the figures in §04 add the $0.0008 Cloud Run bridge. Gemini Live on Vertex is $3.00 per million audio input tokens and $12.00 per million audio output tokens at 25 tokens per second of audio, giving 60×25×3/1e6 + 30×25×12/1e6 = $0.0135 a call-minute. Vertex-hosted Claude is priced by Google and differs from the Anthropic list rates used here.
  8. Phone number. $1.15 per local number per month. Inbound voice $0.0085/min to a programmable-voice number. Elastic SIP trunking would cut inbound to $0.0034/min, worth $5,100 a month at 1M minutes, at the cost of running SIP. Twilio SIP pricing.
  9. Cloud Run min-instances. Always-allocated CPU at $0.000018/vCPU-second and $0.000002/GiB-second. One 2 vCPU / 2 GiB instance held for 730 hours is $105.12 a month. One instance per 25 concurrent calls, so the 1M-minute rows carry ten, at $1,051. Per-call compute on top is $0.0008 a minute at 0.5 vCPU and 0.5 GiB.
  10. Secret Manager. $0.06 per active secret version per month across seven secrets, plus $0.03 per 10,000 access operations: $0.42 at low volume, $1.28 at 1M minutes.
  11. Cloud Logging. $0.50 per GiB ingested beyond 50 GiB free. At roughly 2 KB per call-minute even 1M minutes is 1.9 GiB, so this is $0.00 at every volume modelled. It stops being free if you start logging audio.
  12. GCS call archive. Standard storage $0.020 per GB-month. One JSON snapshot per call at about 8 KB, retained twelve months: $0.05 a month at 100k minutes, $0.52 at 1M. The cheapest line in the document and the one that keeps the transcripts.
  13. Artifact Registry. $0.10 per GB-month beyond 0.5 GB free; a 2 GiB image is $0.15. Cloud Build stays inside its free 2,500 build-minutes at our deploy cadence.
  14. Egress. Mu-law 8 kHz is 8 KB/s, so about 480 KB per call-minute leaves Cloud Run for Twilio. At $0.12 per GB that is $5.49 a month at 100k minutes and $54.93 at 1M. Small, but it grows linearly and nobody budgets it.
  15. GKE rows only. Cluster management $0.10/hr = $73, one internal load balancer $18, and 100 GB SSD boot disk per GPU node at $0.17/GB = $17 per node. At 237 peak concurrent and eight streams per GPU that is 30 nodes, $510 in disk alone.
  16. Not counted. Engineering time, GCP support (Standard is $29/mo or 3% of spend, whichever is greater, which at 1M minutes is not $29), the A2P messaging campaign, a second region for failover, and any negotiated rate. Every figure here is list price for one region with no redundancy, which makes them a floor rather than a forecast.