Forum Discussion
Migrating Teams Calling Bot (EchoBot) from VMSS to Windows Containers / ACI?
Hi everyone,
I have built a Microsoft Teams Calling Bot using Application-Hosted Media based on the official C# EchoBot sample:
https://github.com/microsoftgraph/microsoft-graph-comms-samples/tree/master/Samples/PublicSamples/EchoBot
Currently, our signaling logic is fully serverless and runs efficiently on Azure Functions. However, the actual media processing (using the C# Calling SDK which relies on native Windows media binaries) is deployed on VMSS with Windows Server, just like the repository's default deployment guide suggests.
Running these Windows VMs continuously is becoming extremely expensive, and we are looking for a cheaper, modern, or "on-demand" alternative to handle the media pipeline.
Since raw audio processing strictly requires these native Windows-based Media binaries, I would like to ask the community:
1. Windows Containers (ACI / AKS): Has anyone successfully run this C# EchoBot/Media SDK inside Windows Containers (such as Azure Container Instances or AKS)? If so, how do you handle the public IP and port-binding requirements for the media sockets (since the platform needs direct public connectivity for UDP/TCP traffic)?
2. On-Demand Provisioning: Are there any known architectures or best practices for spinning up the media processor only when a call starts (e.g., triggering an ACI instance via the Azure Function signaling bot) and tearing it down afterwards to keep costs near zero when idle?
3. Alternative Approaches: If you have solved this high-infrastructure cost problem for a real-time raw audio bot in production, what architecture did you end up using?
Any documentation, GitHub references, or architectural advice would be highly appreciated!
Thanks!
2 Replies
- Ashlesha-msft
Microsoft
Hi, Building on what Jamony shared — here's a more detailed breakdown for each of your questions.
1. Windows Containers (ACI / AKS)
ACI is not viable for Application-Hosted Media bots. Three hard blockers:
- No per-instance public IP — each media worker needs its own reachable IP; ACI shares IPs behind NAT in most configurations
- Dynamic port binding (UDP/TCP ranges like 8445, 10000–20000) doesn't map cleanly to ACI's port model
- ACI is simply not in the supported host list — AKS and VMSS are
AKS with a Windows node pool is supported, but you must ensure each pod/node has a unique public IP. A standard Kubernetes LoadBalancer VIP (single shared IP) won't work. Use HostNetwork mode with node-level public IPs as the most practical setup.
2. On-Demand / Spin-up-on-call-start
Do not provision ACI or new VMSS instances after the call arrives. Windows container/VM cold start takes 2–10 minutes; Teams call setup negotiation closes in seconds — the call will fail before the worker is ready.
The practical cost-optimized pattern is: keep 1 warm worker always running, scale out on active call count or incoming call signal metrics, and use scale-in protection (VMSS instance protection or AKS PodDisruptionBudget) to prevent active calls from being terminated during scale-in. You won't reach zero idle cost, but you'll pay for one small instance instead of a full VMSS fleet.
3. Alternative Approaches
The biggest cost reduction by far is switching to service-hosted media — if your bot only needs audio prompts, DTMF, or short recordings, Microsoft hosts the media processing and your compute cost is essentially zero. Your Azure Functions signaling code is already compatible with this model.
If you genuinely need raw audio access (custom DSP, mixing, echo processing), stay on AKS Windows node pools and combine 1 on-demand node as your baseline with Spot node pools for burst capacity — Spot Windows nodes are roughly 60–80% cheaper than on-demand.
AKS is the only container option I would treat as supported here. The current Teams documentation lists AKS, but the application-hosted media requirements still apply: Windows Server, a ready instance, direct internet reachability with an instance-level public IP and public-facing port, and calls pinned to the instance that accepted them. ACI is not in the supported-host list, and its networking/lifecycle model does not map cleanly to that per-instance requirement.
I would not start an ACI container only after the call arrives. Provisioning and image-pull time make call setup unreliable, and stopping the worker ends any active call. A practical cost-optimized design is a Windows AKS node pool or VMSS with one warm worker, scale out on call/concurrency metrics, and drain calls before scale-in. It will not reach zero idle cost, but it preserves the supported media path.
If you only need prompts, DTMF, or short recordings rather than continuous raw audio, check whether service-hosted media can replace the local Media SDK—that is the real near-zero-infrastructure option.
https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/requirements-considerations-application-hosted-media-bots