AI System Design

Design a Text-to-Speech Service

Step 1 / 9

Learn AI system design by building a text-to-speech / voice synthesis service like ElevenLabs, Play.ht or a hosted TTS step by step.

The numbers to beatbatchwhole file (URL)streamingfirst-audio fastSSML / voicecontrol inputs

In the interview room

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

Functional requirements

What it must do — agree on these before drawing a single box.

  • Synthesize: turn text (with a chosen voice + SSML) into natural-sounding speech.
  • Stream or batch: return a whole audio file, or stream first-audio-fast for a live voice agent.
  • Normalize + pronounce: expand numbers/dates/abbreviations to words and resolve pronunciation.
  • Voices & control: offer multiple voices, voice cloning, and prosody control via SSML.
  • Cache + deliver: serve repeated phrases from cache and static audio via CDN.

Non-functional requirements

The qualities that shape the whole design — each one names the mechanism that buys it.

Serve two SLAs from one pipeline
A gateway routes batch (whole file/URL) and streaming (first-audio-fast over a persistent connection) onto the same synthesis pipeline and GPU fleet.
A voice agent starts speaking instantly
Stream chunked synthesis — synthesize the first clause/sentence fast and play it while later chunks generate, collapsing time-to-first-audio to one small chunk.
Say the right words, not the letters
A text front-end normalizes numbers/dates/abbreviations to spoken words and resolves pronunciation (incl. homographs from context) before the acoustic model — the top TTS error source.
Cloning can’t enable impersonation
Gate voice cloning behind consent/verification of the voice owner and watermark synthetic audio so misuse is detectable — voice is a safety surface, not just a product.
Repeated phrases never touch the GPU
Cache synthesized audio keyed by (text + voice + params) so common IVR/notification phrases are cache hits; deliver immutable audio via CDN.
Run GPUs economically under a latency budget
Batch synthesis for throughput but keep streaming batches small, autoscale on load, keep models warm, and lean on the cache so most traffic never reaches a GPU.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

A multi-stage pipeline (normalize → pronounce → prosody)over a flat letter-to-sound mapping

“$5 on 3/4” must become “five dollars on March fourth”, homographs need context, and the voice needs natural rhythm and emotion. A flat phoneme map is robotic and mispronounces real text — TTS is a pipeline, not a lookup.

Chunked streaming synthesisover synthesizing the whole reply before playing any of it

Synthesizing everything first adds latency proportional to reply length — dead air that breaks conversational flow. Synthesize the first chunk fast and stream it while the rest generates, so first-audio latency is one small chunk.

Split acoustic model and vocoderover one fused end-to-end model

Splitting text→mel from mel→waveform lets each stage be optimized and swapped independently and localizes concerns — the vocoder is often the latency/quality bottleneck you tune without retraining the acoustic model.

Verify consent before a clone is usableover treating possession of an audio sample as permission

Having a recording of someone’s voice — a speech, a voicemail, a clip — is not consent to clone it; that gap enables impersonation and fraud. Gate the voice behind verification and watermark its output rather than labeling after the damage.

Cache audio by text+voice+paramsover re-synthesizing every request on a GPU

Huge fractions of TTS traffic are identical — IVR prompts, notifications, stock phrases synthesized millions of times. Serving repeats from cache skips the GPU entirely; only genuinely novel text pays for synthesis.

What this teaches

Learn AI system design by building a text-to-speech / voice synthesis service like ElevenLabs, Play.ht or a hosted TTS step by step. An interactive guide covering the synthesis pipeline (text normalization, acoustic model, vocoder), batch vs streaming synthesis, first-audio latency for voice agents, voices and prosody control, caching common phrases + CDN, GPU scaling, voice cloning safety, and the unhappy paths.

Key takeaways

  • Natural TTS is a pipeline, not a lookup: normalize text, resolve pronunciation, render human prosody.
  • A gateway serves batch (whole file) and streaming (first-audio-fast) over the same synthesis pipeline.
  • Streaming synthesizes in chunks and plays the first audio immediately — first-audio latency is the metric.
  • The pipeline is text front-end → acoustic model (mel) → vocoder (waveform), often split for optimization.
  • Voices are conditioning inputs; cloning is powerful and must be gated by consent + watermarking.
  • Cache synthesized audio by text+voice+params so repeated phrases skip the GPU; deliver via CDN.
  • Scale GPUs with batching (small for streaming) + autoscaling + warm weights; harden the front-end.

Concepts covered

  • What makes text-to-speech hard?
  • More than reading letters
  • A gateway for batch and streaming
  • Streaming synthesis
  • Normalize → acoustic → vocoder
  • Voices, cloning & prosody control
  • Caching & delivery
  • GPU scaling
  • Pronunciation, latency & abuse

Design a Text-to-Speech Service — read the full walkthrough as text

the same steps, decisions & trade-offs, for reading, reference & search

The big idea

What makes text-to-speech hard?

Turning text into a natural voice has two faces. Batch: narrate a whole article or audiobook — quality matters, latency doesn't. Streaming: a voice agent that must start speaking within ~200ms of deciding what to say, or the conversation feels broken. And "natural" hides real complexity: pronouncing "Dr.", "$5", and "2024" correctly, with human-like rhythm and emotion.

A text-to-speech (TTS) service synthesizes speech through a pipeline — text normalization → acoustic model → vocoder — served in batch or streaming mode. The hard parts: getting the front-end (pronunciation) right, hitting the first-audio latency budget for interactive agents, and controlling GPU cost with caching.

How to read this: Each step opens with a real design decision — make the call before I show you what ships. Watch the pipeline grow, and at the end break text normalization and drop the phrase cache to see the fluent-but-wrong failure and the cost lever. Hit Begin.

Step 1 · "Natural" is the hard part

More than reading letters

It's tempting to think TTS is "map each letter to a sound." Why is producing a convincing voice actually much harder than that?

Design decision: Why is natural TTS much harder than mapping letters to sounds?

The call: Because audio files are large. — File size is trivial. The difficulty is linguistic and acoustic: correctly interpreting text into spoken words and rendering natural, expressive prosody — a flat phoneme mapping sounds robotic and mispronounces real text.

Natural speech is a multi-stage problem. You must normalize text ($5 → "five dollars", Dr. → "Doctor", 3/4 → "March fourth"), resolve pronunciation including homographs from context ("read" past vs present), and render human-like prosody — rhythm, stress, intonation, emotion. A flat letter-to-sound map is robotic and wrong. This is why TTS is a pipeline, not a lookup.

Front-end + back-end: TTS has a linguistic front-end (text → normalized words → phonemes, with prosody) and an acoustic back-end (phonemes/text → sound). Most embarrassing failures ("dollar sign five") come from the front-end; most quality wins come from the back-end. Both matter.

Step 2 · The front door

A gateway for batch and streaming

Like ASR, TTS serves two modes with different SLAs. What does the entry point do when a synthesis request arrives?

A gateway accepts the text, chosen voice, and optional SSML/prosody controls, checks the cache, and routes by mode. Batch: synthesize the whole text and return an audio file (URL). Streaming: begin emitting audio as soon as the first chunk is ready and stream it out over a persistent connection — essential for voice agents where first-audio latency is the metric that matters. Both drive the same synthesis pipeline and GPU fleet.

One pipeline, two SLAs: Batch optimizes total quality/throughput; streaming optimizes time-to-first-audio. The gateway exposes both and multiplexes onto shared GPUs. For interactive voice, starting to speak fast (then continuing to generate) beats waiting to synthesize the whole utterance.

Step 3 · Speak before it's all written

Streaming synthesis

A voice agent has decided to say a two-sentence reply. Waiting to synthesize the entire thing before playing any of it adds seconds of dead air. How do you make it feel instant?

Design decision: A voice agent must reply fast. How do you avoid seconds of silence before it speaks?

The call: Synthesize in chunks and stream the first audio out immediately, generating the rest as it plays. — Chunk the text (by clause/sentence), synthesize the first chunk fast, and start streaming audio while later chunks are still being generated. First-audio latency drops to the time for one small chunk, and playback stays ahead of generation, so the reply begins almost instantly and continues seamlessly.

Stream the synthesis. Chunk the text (by clause/sentence), synthesize the first chunk fast, and begin streaming its audio immediately while later chunks are generated in the background — playback stays just ahead of generation. First-audio latency collapses from "synthesize the whole reply" down to "synthesize one small chunk", so a voice agent starts speaking almost instantly and continues seamlessly.

Time-to-first-audio: For conversational voice, the key metric isn't total synthesis time — it's how fast the first audio plays. Streaming chunked synthesis (and a low-latency model) minimizes it, so the agent responds like a person instead of pausing awkwardly before every sentence.

Step 4 · Inside the pipeline

Normalize → acoustic → vocoder

Concretely, how does normalized text become a waveform? What are the stages and why are they usually split?

Three stages. (1) Text front-end: normalize (numbers/dates/abbreviations → words) and convert to phonemes (grapheme-to-phoneme), with prosody from SSML/context. (2) Acoustic model: turn the phonemes + target voice + prosody into a mel spectrogram (how it should sound over time). (3) Vocoder: convert the mel spectrogram into an actual waveform. Splitting acoustic model from vocoder lets each be optimized (and swapped) independently; some modern systems fuse them end-to-end.

Two-stage synthesis: The classic split — acoustic model (text → mel) then vocoder (mel → audio) — mirrors "decide the sound, then render it". The vocoder is often the latency/quality bottleneck. End-to-end neural models exist, but the staged view maps cleanly to where errors and costs live: front-end for pronunciation, back-end for audio quality.

Step 5 · Voices & expression

Voices, cloning & prosody control

Users want a specific voice, sometimes their own, and control over how it sounds — emphasis, pauses, emotion, speed. How does the service offer that?

Design decision: A user uploads a 10-second audio clip and asks to clone that voice. What should the service require before generating anything in it?

The call: Verification that the uploader is the voice's owner (or has explicit authorization) before the clone is usable. — Consent has to be structural, not assumed: verify the person cloning a voice is authorized to, gate the resulting voice behind that check, and watermark its output so misuse is detectable downstream.

Support multiple voices as speaker embeddings/models the acoustic stage conditions on, plus voice cloning (derive a new voice embedding from a short sample). Give control via SSML or parameters — emphasis, pauses, rate, pitch, emotion/style — so callers shape the prosody. Because cloning is powerful and abusable, gate it behind consent and verification, and add audio watermarking so synthetic speech is detectable. Voice is both the product and a safety surface.

Conditioning + control: A voice is a conditioning input to the acoustic model; cloning creates that conditioning from a sample. SSML exposes prosody knobs. The power to mimic any voice makes consent, verification and watermarking non-negotiable — impersonation and fraud are the obvious abuses.

Step 6 · Don't re-synthesize the world

Caching & delivery

Enormous fractions of TTS traffic are identical — the same IVR prompts, notifications, and stock phrases synthesized millions of times in the same voice. Re-running the GPU for each is pure waste. And finished audio needs fast delivery. How?

Cache synthesized audio keyed by (text + voice + params): a repeated phrase is served from the cache and never touches the GPU — a massive cost and latency win for the common, static content that dominates many workloads. Store generated audio in object storage and deliver via CDN (audio is immutable and often re-played, ideal edge content). The result is a URL; only genuinely novel text pays for synthesis.

Cache the repeats, CDN the rest: TTS traffic is heavily repetitive, so caching by exact text+voice+params turns most requests into cache hits that skip the GPU entirely. A CDN then fans out the static audio. You only spend GPU on new, unique utterances — the biggest cost lever in a TTS service.

Step 7 · Feed the fleet

GPU scaling

Novel synthesis is GPU-bound (the vocoder especially), demand varies, and streaming has a tight latency budget. How do you run the fleet economically without breaking real-time?

Same GPU-economics as other inference services: batch synthesis requests for throughput on the batch path, but keep streaming batches small so first-audio latency stays low. Autoscale on load, keep models warm (avoid cold starts loading multi-GB weights), and use faster/lighter models or vocoders for the streaming path where latency dominates. Combined with the cache (most traffic never reaches a GPU), this keeps cost in check while protecting the interactive SLA.

Batch vs latency, again: Batching helps throughput but hurts latency, so big batches for batch synthesis and tiny ones for streaming. The cache removes most load entirely; autoscaling and warm weights handle the rest. The vocoder is often where you spend the most GPU, so it's the prime target for optimization/quantization.

Step 8 · The sharp edges

Pronunciation, latency & abuse

TTS fails in fluent, confident ways: the front-end mispronounces text, homographs go wrong, streaming latency slips, and voice cloning invites impersonation and fraud.

Harden the front-end — robust normalization for numbers/dates/currency/units, a pronunciation lexicon for names and jargon, and context-aware homograph resolution — since these errors are fluent and confident, not crashes. Protect the latency budget with chunked streaming, low-latency models, and caching. Combat abuse: consent/verification for cloning, watermark synthetic audio, rate-limit, and moderate text (don't voice disallowed content). Fail gracefully — fall back to a simpler voice/model rather than silence.

Design for the unhappy path: Mispronunciation → normalization + lexicon + homograph context. Latency → chunk + fast models + cache. Cloning abuse → consent, watermark, moderate. The scariest TTS failure is the one that sounds perfect while being wrong or misused — so the guards target fluency-masked errors and voice safety.

You did it

You just designed a text-to-speech service.

  • Natural TTS is a pipeline, not a lookup: normalize text, resolve pronunciation, render human prosody.
  • A gateway serves batch (whole file) and streaming (first-audio-fast) over the same synthesis pipeline.
  • Streaming synthesizes in chunks and plays the first audio immediately — first-audio latency is the metric.
  • The pipeline is text front-end → acoustic model (mel) → vocoder (waveform), often split for optimization.
  • Voices are conditioning inputs; cloning is powerful and must be gated by consent + watermarking.
  • Cache synthesized audio by text+voice+params so repeated phrases skip the GPU; deliver via CDN.
  • Scale GPUs with batching (small for streaming) + autoscaling + warm weights; harden the front-end.
built to turn words into a voice before the sentence finishes — make the calls, break the front-end, run the gauntlet.
Finished this one? 0 / 61 AI System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More AI System Designs