
A traffic spike hits your self-hosted text-to-speech (TTS) endpoint, and requests start queueing. Latency climbs past your service level objective (SLO) right when the most callers are listening. The auto scaling policy behind that endpoint was supposed to prevent this, but the target value it scales on was a guess, and guesses like that fail silently until real traffic proves them wrong.
Get that number wrong, and it’s paid for in one of two ways, and neither shows up as an alarm. Guess too conservative, and the fleet runs GPU instances that sit mostly idle. That cost lands on every invoice but never trips an incident report. Guess too aggressive, and the fleet carries a risk nobody sees. Each instance holds more concurrent requests than it can serve inside its latency promise. Nothing looks wrong until a real traffic spike pushes queueing time past the SLO. That happens right when the most callers are listening. That’s the hidden gap. A policy that looks fine on the console can already be failing the people it’s supposed to serve.
In this post, we deploy Kokoro-82M , an 82-million-parameter TTS model, as a custom container on an Amazon SageMaker AI real-time endpoint. AWS Cloud Development Kit (AWS CDK) stacks handle the deployment. We replace guesswork with two measurements taken against the live endpoint. Q_max is the highest concurrency one instance sustains before breaching the SLO, and T_total is how long a scale-out takes end to end. We derive the scale-out threshold, scale-in threshold, and both cooldowns from those two numbers by arithmetic. Every number in this post comes from an actual deployment and measurement run of the aws-samples repository referenced in this post.
The endpoint deploys through three AWS CDK stacks, applied in order: SpeechFoundationStack creates the IAM roles and the Amazon S3 bucket that caches model weights, SpeechModelCacheStack syncs a model’s Hugging Face weights into that bucket once, and SpeechEndpointStack builds the container image, pushes it to Amazon ECR, and creates the Amazon SageMaker AI model, endpoint configuration, and endpoint.
SpeechModelCacheStack runs an AWS CodeBuild project that syncs the model’s Hugging Face weights into the cached Amazon S3 bucket once. A cold endpoint start doesn’t need to pull them from the internet. Gated by the preceding scaling_enabled check, SpeechEndpointStack builds the container image, pushes it to Amazon ECR, and creates the Amazon SageMaker AI model, endpoint configuration, and endpoint.
Most public guidance on Amazon SageMaker AI auto scaling targets short synchronous request/response calls, or large language model (LLM) serving, where the natural metric is tokens generated per second. TTS synthesis fits neither pattern: a single request holds a connection open for several seconds with no token-generation loop to attach a metric to. Kokoro-82M is non-autoregressive, a StyleTTS2 derivative with an ISTFTNet decoder, trained adversarially rather than by autoregressive next-token prediction or iterative denoising. It produces a full utterance from one duration-aligned pass. There’s no generation loop to instrument with a per-token metric in the first place. What determines whether a TTS instance is overloaded is simpler than it sounds: how many requests are queued and executing on it right now.
The deployed policy scales on ConcurrentRequestsPerModel , a native metric Amazon SageMaker AI publishes itself rather than one this project’s own container code has to emit. Scaling on a metric Amazon SageMaker AI publishes removes an entire class of failure where a custom metric configuration looks correct on paper but nothing is actually publishing to it.
ConcurrentRequestsPerModel publishes a Maximum statistic over a 10-second window, a different quantity from the mean in-flight count a benchmarking client measures directly. The tooling accounts for this. At every rung of the concurrency ladder it measures both quantities against the same load and records the ratio between them. It then uses that ratio to convert the client-measured threshold into Amazon CloudWatch units before writing it into the deployable configuration. For the Kokoro-82M run in this post, the measured ratio came out to exactly 1.0 at every rung, so the client-measured and Amazon CloudWatch-reported thresholds match directly.
A traffic spike hits your self-hosted text-to-speech (TTS) endpoint, and requests start queueing Reported by AWS Machine Learning on October 22, 2026.