Education10 min read

Meeting Bot Architecture at Scale: What Nobody Tells You

A deep look at the engineering decisions behind production meeting bots — concurrency, bot lifecycle, error recovery, state machines, and scaling to thousands of simultaneous sessions.

Gregnote Team

25 August 2026

The deceptively simple premise

At first glance, a meeting bot is just a program that joins a call, records audio, and sends a webhook when the meeting ends. Spin it up on a VPS, ship in a weekend. And that's true — for the demo.

What breaks at scale is everything you didn't design. Meeting bots are long-running, stateful, external-dependency-heavy processes. They connect to third-party video infrastructure you don't control, stay connected for 30–90 minutes, and need to produce reliable output even when the meeting host loses their internet, the platform drops the bot, or your own infrastructure hiccups.

This post walks through the architecture decisions that matter, drawn from running thousands of simultaneous meeting sessions.

Bot lifecycle: it's a state machine

The most important mental model for meeting bots is that each bot instance is a finite state machine with defined transitions. Not understanding this causes the majority of production bugs.

A bot's lifecycle looks like:

CREATED → JOINING → JOINED → RECORDING → COMPLETED
                  ↓
              FAILED (any stage)

Each transition has conditions, timeouts, and retry semantics. For example:

  • JOINING → JOINED: The platform admitted the bot and the audio stream started. If this doesn't happen within 60 seconds, you should transition to FAILED and alert. Don't leave bots stuck in JOINING indefinitely.
  • RECORDING → COMPLETED: The meeting ended (all participants left, or the host ended it), and the full audio was sent for transcription. If audio delivery fails, you should NOT mark the bot as COMPLETED — you need to retry or surface the error.

Every state should be persisted in your database, not just in memory. A process crash mid-recording should be recoverable.

Why bots get stuck

The most common issue you'll hit in production is bots that never transition out of JOINING. This happens for three reasons:

  1. The meeting URL is invalid or the meeting hasn't started yet. Your API should validate the URL format at request time, but you can't know if the meeting exists until the bot tries to join.
  2. The platform rejected the bot. Google Meet and Teams both have anti-bot detection. The more your bot looks like a real browser (correct user agent, proper WebRTC negotiation, realistic join timing), the more reliably it gets admitted.
  3. A network partition between your bot infrastructure and the platform. This is rarer but happens. Your infrastructure should be in a region with low latency to Google/Microsoft's video infrastructure — typically us-east or eu-west.

The fix is a timeout watchdog: if a bot hasn't transitioned out of JOINING within N seconds, mark it failed and fire a failure event. With Gregnote, you can see the bot's current state on the dashboard and replay the join attempt without needing to look at server logs.

Concurrency and isolation

Each bot is a separate process, not a thread. Video processing is CPU-heavy — audio decoding, resampling, VAD (voice activity detection) — and you do not want one bot's overloaded event loop delaying transcript delivery for another.

At low concurrency (< 20 simultaneous bots), you can get away with running them on a single multi-core machine. Above that, you need horizontal scaling — each bot instance on its own VM or container, orchestrated by a job queue.

The queue handles admission control: if your capacity is 100 concurrent bots, a 101st request should queue rather than fail. Gregnote handles this for you; if you're building your own infrastructure, Redis with BullMQ or SQS are common choices.

Audio pipeline: the two failure modes

The audio capture and transcription pipeline has two distinct failure modes:

Silent corruption: the audio is captured but damaged — a network dropout caused packet loss, the resampling step introduced artifacts, or the audio was truncated at the start or end. The transcription succeeds but the output is wrong. These are hard to detect without listening to the audio, so the best mitigation is redundant capture (record the raw WebRTC packets before decoding, so you have a fallback).

Hard failure: the transcription service returned an error, the audio file never arrived, or the webhook failed to deliver. These are detectable with status codes and should trigger automatic retries with exponential backoff.

Gregnote's transcription pipeline is built around the assumption that hard failures happen, and every step has retries. You get a webhook retry at 1m, 5m, 30m, and 2h after the initial attempt — so even if your server is down for 25 minutes after a meeting ends, you don't lose the event.

Webhook delivery as a first-class concern

Your webhook endpoint is the integration point between Gregnote and your product. Treat it with the same reliability standards as your critical API endpoints.

Two things matter most:

Idempotency: Gregnote may deliver the same event more than once (on retry). Your handler should be idempotent — processing the same meeting.completed event twice should produce the same result as processing it once. Store a processed_event_ids set and skip events you've already handled.

Fast acknowledgement: Respond with a 2xx status code as fast as possible — ideally before you do any real processing. Queue the work. If your handler does synchronous LLM calls, database writes, and Slack notifications before responding, it will time out on longer meetings, and Gregnote will retry a webhook you've already partially processed.

app.post("/hooks/gregnote", async (req, res) => {
  // Verify signature first
  verifySignature(req);
  // Acknowledge immediately
  res.sendStatus(200);
  // Then process async
  await queue.add("process-meeting", req.body);
});

Platform-specific quirks

Google Meet: Bots need a real email address to "knock" on a meeting. Meet treats bots more like guests — the host needs to admit them unless the meeting is set to admit all. Build UX that tells your users to set meetings to "admit all" or to expect a knock.

Microsoft Teams: Teams bots are first-class API citizens — Teams has an official bot framework. The join experience is smoother, but setup is more involved (Azure app registration, manifest, permissions). Once set up, reliability is excellent.

Zoom: Zoom's API policy has historically been more restrictive for third-party bots. Check the current terms before building.

Monitoring: what to watch

Three signals tell you your meeting bot infrastructure is healthy:

  1. Time-to-join (P50/P95): How long from API call to bot appearing in the meeting. Spikes here indicate platform admission issues or network problems.
  2. Transcript delivery rate: What fraction of completed meetings successfully delivered a transcript. Anything below 99% is worth investigating.
  3. Webhook delivery success rate: What fraction of webhook attempts got a 2xx response. If this drops, your customers aren't receiving meeting data.

Build dashboards for these three before anything else.

See also

If you're just getting started, read our guide to adding a meeting bot to Google Meet first — this post assumes you've already integrated the basic API. For understanding the webhook format in detail, see handling Gregnote webhooks in production.

Try it yourself

API key in 30 seconds. Free credit on sign-up. No card required.