Pangram verdict · v3.3
We believe that this document is a mix of AI-generated, and human-written content
AI likelihood · overall
MixedArticle text · 1,731 words · 5 segments analyzed
Telegram Serverless lets you run backend code for your bot and Mini App directly on Telegram's infrastructure — no servers to provision, no containers to keep alive, no scaling to think about. You write plain JavaScript modules, deploy them with a single command, and Telegram runs them in a fast, isolated V8 sandbox that sits right next to the Bot API and a built‑in database. If you have ever wired a bot to a VPS, a cloud function, or a hosting panel just to answer a /start, this is the part you no longer have to do. On this page Why serverless Getting started Building with AI On the go with BotFather Projects & modules The database The SDK CLI reference Why serverless A Telegram bot is, at heart, a program that reacts to updates. Traditionally you had to host that program somewhere that is always on, reachable, and secure — and then keep it that way. Telegram Serverless removes that layer entirely: No infrastructure. There is no machine to rent, patch, or monitor. Your code runs on demand and scales with your bot automatically. Batteries included. The Telegram Bot API, an SQLite‑backed database, and outbound HTTP are available to every module out of the box — nothing to install, no credentials to wire up. Fast, isolated execution. Each invocation runs in a lightweight V8 isolate, close to Telegram's own systems, so calls to the Bot API and your database are quick and reliable. A real developer workflow. A project lives in a folder on your machine under version control. You edit files, see exactly what changed, deploy atomically, and roll your database schema forward with reviewed migrations — the way you already work with everything else. The mental model You work in three places, and they map cleanly onto each other: Where What lives there Your project folder JavaScript modules — schema, shared code, update handlers The cloud The deployed copy of those modules, plus your bot's database The tgcloud CLI The bridge — it shows you differences and syncs them You never SSH into anything. You edit files locally, run npx tgcloud push, and the platform takes it from there. Your bot's traffic is handled by the deployed modules; your database persists between invocations.
A project has just three kinds of code: handlers/ # entry points — one file per Telegram update type lib/ # shared code you import from anywhere schema.js # your database tables When an update arrives — a message, a button press, an inline query — Telegram routes it to the matching handler (handlers/message.js, handlers/callback_query.js, …) and calls its default export. That function talks to the Bot API and the database through the SDK, and returns. That is the whole loop. An update with no matching handler is simply ignored, so you add only the handlers you need. Quick demo Here is a complete, working demo bot. It replies to every message and remembers how many it has seen from each chat. schema.js import { table, integer } from 'sdk/db'; export const counters = table('counters', { chatId: integer('chat_id').primaryKey(), seen: integer('seen').notNull().default(0), }); handlers/message.js import { api, db } from 'sdk'; import { counters } from 'schema'; import { sql } from 'sdk/db'; export default async function (message) { const chatId = message.chat.id; // Insert the counter, or bump it if this chat already has one — and get the // resulting row back in the same statement via .returning(). const [row] = await db.insert(counters) .values({ chatId, seen: 1 }) .onConflictDoUpdate({ target: counters.chatId, set: { seen: sql`${counters.seen} + 1` }, }) .returning() .run(); await api.sendMessage({ chat_id: chatId, text: `Hello! I've seen ${row.seen} message(s) from you.`, }); } Deploy it: npx tgcloud push # upload the modules npx tgcloud migrate # create the `counters` table That's a live bot with persistent state and no server. Everything in it — api, db, the table() DSL — is described in the sections below. Serverless is a general backend for Telegram bots and Mini Apps, not a template for one kind of app. It is ideal for: Conversational AI Bots that need to store per‑user state in a database. Mini App Backends that store user data and serve dynamic content. Games and Tools — including leaderboards, quizzes and more.
Automations and Integrations that call third‑party HTTP APIs and push results into chats. Getting started This walkthrough takes you from an empty folder to a live bot that answers messages and stores data. It assumes you have Node.js 18 or newer installed and a bot registered with @BotFather. By the end you will have used every command you need day to day: push, migrate, run, and status. Before anything else, switch Serverless on. In @BotFather, open your bot → Serverless and turn it on. That turns the feature on for this bot and unlocks its CLI access token, handlers, library, and database. 1. Create a project The fastest way to start is the project creator, which scaffolds a project and installs the CLI into it: npm create @tgcloud/bot example_bot cd example_bot The argument is the target folder: pass . to scaffold into the current folder, or any path. It works in an existing folder too and never overwrites files you already have. This gives you a ready‑to‑edit project: example_bot/ ├─ docs/ │ └─ tgcloud-sdk.md # SDK reference (for you and your AI tools) ├─ handlers/ │ └─ message.js # a starter message handler (echoes text back) ├─ lib/ # your shared modules go here (empty to start) ├─ AGENTS.md # orientation for AI coding assistants ├─ package.json └─ schema.js # your database tables The scaffolded files are self‑documenting — each one contains commented examples of what you can do next. The CLI installs into the project as a local dev‑dependency, so you run it with npx tgcloud <command> (npx finds the copy in your project's node_modules), or through the npm run shortcuts the scaffold adds to package.json (npm run deploy, npm run status). By default there is no global tgcloud on your PATH. You can also install it globally — npm install -g @tgcloud/cli — if you'd rather type a bare tgcloud from anywhere. That's handy for running tgcloud init in any empty folder, and it's what shell tab‑completion needs. Either way you get the same project. 2. Link your bot Every project is tied to one bot.
Connect them with login, which asks for your CLI access token (@BotFather → your bot → Serverless → CLI Access → Access token — a separate token from your bot's API token) and stores it locally: npx tgcloud login The token has the form app<id>:<secret>. The CLI keeps it in .tgcloud/, which is git‑ignored, and never prints the secret part. Login is the only time you are asked for it — see Authentication for how tokens are resolved in CI. 3. Look around Two commands tell you where things stand at any moment, both fully offline: npx tgcloud status # what has changed locally vs. the deployed copy npx tgcloud diff # the line‑by‑line changes Right after init everything is new and nothing is deployed yet. status shows the starter files waiting to go up. 4. Deploy Send your modules to the cloud: npx tgcloud push push uploads every changed module in one atomic batch and updates your local record of what the cloud now holds. Your bot is live: open it in Telegram and send it a message — the starter handler echoes it back. Deploying never touches your database. Pushing code and changing your database schema are deliberately separate steps, so a code deploy can never surprise you with a data migration. That is what the next step is for. 5. Add a database table Let's make the bot remember something. Open schema.js and declare a table: import { table, integer, text, sql } from 'sdk/db'; export const messages = table('messages', { id: integer('id').primaryKey({ autoIncrement: true }), chatId: integer('chat_id').notNull(), text: text('text'), created: integer('created_at', { mode: 'timestamp' }).default(sql`(unixepoch())`), }); Deploy the schema, then apply it to the database: npx tgcloud push # uploads the new schema.js npx tgcloud migrate # creates the `messages` table push reports that the schema is out of sync and shows you the pending change, but applies nothing. migrate walks you through the change and, on your confirmation, creates the table. This two‑step model — and what happens with riskier changes like drops — is covered in Migrations. 6. Store and read data Now use the table from your handler.
Edit handlers/message.js: import { api, db } from 'sdk'; import { messages } from 'schema'; import { eq } from 'sdk/db'; export default async function (message) { // Save this message. await db.insert(messages) .values({ chatId: message.chat.id, text: message.text }) .run(); // Count how many we've stored for this chat. const count = await db.$count(messages, eq(messages.chatId, message.chat.id)); await api.sendMessage({ chat_id: message.chat.id, text: `Saved. That's ${count} message(s) from this chat so far.`, }); } Deploy the updated handler with npx tgcloud push, then send your bot a few messages and watch the count climb. The database persists between invocations — that's your bot's memory. 7. Test without deploying You don't have to deploy to try a change. npx tgcloud run executes a handler on the platform using your local files, without publishing them: npx tgcloud run handlers/message '{ chat: { id: 1 }, text: "hello" }' The argument is the payload your handler receives — for handlers/message, a Message — written in JSON5 (so you can skip quoting keys). The command prints anything the handler logged with console.*, the return value, and how long it took. This is the tightest loop for iterating on logic — no deploy, no waiting for a real message. 8. Keep in sync As you work, a handful of commands keep your local project and the cloud aligned: npx tgcloud status shows what changed, npx tgcloud push deploys, npx tgcloud pull brings your local project in line with the cloud, npx tgcloud fetch refreshes the reference copy without touching your files, and npx tgcloud reset discards local changes. If two people (or two machines) deploy to the same bot, the platform detects the conflict and push stops to let you pull first — you can never silently overwrite someone else's work. See Staying in sync. Building with AI Prefer to build with an AI assistant — or is the only coder on your team an AI?