If you have read any of my previous posts, you are probably thinking:"Wait, aren't all of your Telegram bots already serverless?"

Yes—I usually run everything on Cloudflare Workers and D1. When I say "Telegram Serverless" here, I am not talking about putting a bot on AWS Lambda or Cloudflare. I am talking about Telegram’s own native serverless platform (tgcloud), where your bot code, embedded SQLite database, and Mini App all live inside V8 isolates directly on Telegram's own infrastructure.

I recently built a full Telegram Business assistant and companion Mini App on tgcloud—complete with a streaming voice transcription pipeline—to see how it compares to my usual Cloudflare stack. Here is what actually feels like magic, the weird UI traps I hit along the way, and the one missing feature that still forces you back to an external cloud.

The Superpower: Zero-Webhook Architecture & Pre-Verified Auth

Even when you build a serverless bot on Cloudflare Workers, there is still an annoying pile of plumbing you have to wire up on day one: configuring a public HTTPS route, calling setWebhook, validating theX-Telegram-Bot-Api-Secret-Token header on every inbound payload, and spinning up ngrok or Cloudflare tunnels whenever you want to test locally.

On tgcloud, webhooks don't exist.

Because your V8 isolate runs inside Telegram's internal network perimeter, Telegram dispatches updates internally based on your directory layout:

  • File-Based Update Routing: If you drop a business_message.jsfile into your handlers directory, it automatically receives business messages. Running npx tgcloud run on your laptop mocks the isolate locally without tunnels or public URLs.
  • Embedded SQLite (schema.js): You don't have to provision an external database. You define your schema in code, runnpx tgcloud migrate, and query it via their built-in async query builder (sdk/db).
  • Zero-Boilerplate Mini App RPC (endpoints/):Normally, when a Telegram Mini App talks to your backend, you must passwindow.Telegram.WebApp.initData in a header and write crypto boilerplate on the server to verify the HMAC-SHA256 signature against your bot token. On tgcloud, you simply call Telegram.WebApp.Serverless.call('getProfile', payload). The runtime cryptographically verifies user identity before your endpoint code wakes up, handing you a trusted ctx.initData object.
  • Built-in SPA Hosting (dist/): Your compiled Mini App frontend is uploaded alongside your bot code and served directly from https://app<id>.tgcloud.ai/.

Streaming Voice Notes to Groq Whisper with Zero Disk

To stress-test the runtime, I built a Bring-Your-Own-Key (BYOK) voice transcription pipeline for Telegram Business users. Whenever a client sends a voice note or a circular video message, the bot transcribes it via Groq'swhisper-large-v3.

The catch: tgcloud runs in a locked-down V8 isolate. You get roughly 128MB of RAM, zero local filesystem access, and no arbitrary node_modules. You cannot download an .ogg file to /tmp, read it back, and upload it to an external AI inference endpoint.

Everything had to be wired as a zero-buffer memory stream:

  1. When a voice or video note lands, the handler extracts the audio metadata (extractAudioInfo).
  2. Instead of buffering the audio payload into memory, I pull a raw readable stream directly from Telegram's internal CDN using api.getFileStream(fileId).
  3. Those raw bytes are piped directly into a multipart/form-dataoutbound fetch() request to Groq Cloud's Whisper API.
// Zero-buffer memory stream: Telegram CDN -> V8 Isolate -> Groq Cloud Whisper
const fileStream = await api.getFileStream(voiceFileId);

const formData = new FormData();
formData.append("file", fileStream, "audio.ogg");
formData.append("model", "whisper-large-v3");

const res = await fetch("https://api.groq.com/openai/v1/audio/transcriptions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${userApiKey}`,
  },
  body: formData,
});

const { text } = await res.json();

Because the audio bytes flow straight from Telegram's internal CDN through the isolate network socket to Groq without touching persistent storage, end-to-end transcription takes between 400ms and 700ms.

Bot API 8.0 Fullscreen Traps

While building the companion Mini App using Telegram's newer Bot API 8.0 Fullscreen mode, I ran into two client rendering quirks that aren't obvious from the official documentation:

1. The Android Safe-Area Lie

When you launch a Mini App in fullscreen mode on mobile, the webview stretches edge-to-edge behind the OS status bar and the front camera punch-hole.

In normal mobile web development, you pad your header using standard CSSenv(safe-area-inset-top). In Android WebViews inside Telegram, that CSS environment variable frequently evaluates to 0px—shoving your app's navigation bar right underneath the phone's clock and physical camera cutout.

// Workaround: Android Telegram WebViews evaluate env(safe-area-inset-top) to 0px
function syncSafeArea() {
  const tg = window.Telegram?.WebApp;
  const rawTop = tg?.safeAreaInset?.top || 0;
  // Enforce a hard 58px minimum headroom fallback for punch-hole cameras
  const safeTop = Math.max(rawTop, 58);
  document.documentElement.style.setProperty("--tg-safe-top", `${safeTop}px`);
}

window.Telegram?.WebApp?.onEvent("safeAreaChanged", syncSafeArea);
window.Telegram?.WebApp?.onEvent("contentSafeAreaChanged", syncSafeArea);
syncSafeArea();

To fix it, I had to ignore CSS environment variables, dynamically readTelegram.WebApp.safeAreaInset and contentSafeAreaInsetin JavaScript, attach runtime listeners to safeAreaChanged, and enforce a hard 58px–64px minimum top headroom fallback.

2. Telegram Desktop Modal Clipping

On Telegram Desktop, the Mini App window spawns anchored to the exact screen coordinates of the button the user clicked. When I used standard Flexbox centering on modal dialogs, narrow window positions caused the top of the modal to clip into negative coordinates above the viewport. Switching to standard block auto-margins (margin: auto) resolved the clipping consistently across desktop and mobile.

The Biggest Blindspot: No Cron or Scheduled Triggers

For all the convenience of native co-location, tgcloud has one glaring limitation that you must account for before committing: it is strictly reactive.

An isolate only wakes up when one of two things happens:

  • A user triggers a Telegram update (message, business_message, callback_query).
  • A user has your Mini App open and triggers a serverless RPC call (POST /api/<name>).

There are no native cron triggers, no delayed queues, and no background timers.

If you are building a business assistant that needs to send a follow-up message 24 hours after a lead goes cold, fire an 8:00 AM daily schedule digest, or run a nightly SQLite cleanup job, tgcloud cannot wake itself up to do it.

To run scheduled tasks on a "serverless" Telegram bot, you still have to spin up an external cron—like a free Cloudflare Worker with a Cron Trigger—just to ping an authorized endpoint on your tgcloud app to wake the isolate up.

How It Stacks Up: tgcloud vs. Cloudflare Workers

FeatureTelegram Serverless (tgcloud)Traditional Edge (Cloudflare Workers)
Webhook SetupNone (internal file-based dispatch)Public HTTPS domain + secret token verification
Bot API CallsBuilt-in internal proxy (api.sendMessage)Outbound HTTPS requests with Bot Token
DatabaseEmbedded SQLite (npx tgcloud migrate)Cloudflare D1 / Turso / external DB
Mini App AuthPre-verified ctx.initData out of the boxManual Web Crypto HMAC-SHA256 verification
Scheduled Tasks (Cron)None (100% reactive to updates/RPC)Native Cron Triggers & Queues
Runtime ConstraintsV8 isolate, ~128MB RAM, 5–10s execution capConfigurable CPU limits, deep npm compatibility

Verdict

If your bot and Mini App are purely reactive—responding to user messages, transcribing voice notes on the fly, and serving an interactive UI when opened—tgcloud is the fastest way to ship a full-stack Telegram app with zero infrastructure ceremony.

Just remember that the second your product roadmap requires a background timer or a morning cron job, you're going to need an external trigger to wake it up.