Telegram Bot Builder
Build production-grade Telegram bots. This skill covers the full lifecycle:
architecture selection, framework choice, database integration, deployment,
monetization, and security.
Minimal Hello World
Python (aiogram 3.x):
import asyncio
from aiogram import Bot, Dispatcher, Router, F
from aiogram.types import Message
router = Router()
@router.message(F.text == "/start")
async def start(message: Message) -> None:
await message.answer("Hello! I'm alive.")
async def main() -> None:
bot = Bot(token="BOT_TOKEN")
dp = Dispatcher()
dp.include_router(router)
await dp.start_polling(bot)
asyncio.run(main())
TypeScript (grammY):
import { Bot } from "grammy";
const bot = new Bot(process.env.BOT_TOKEN!);
bot.command("start", (ctx) => ctx.reply("Hello! I'm alive."));
bot.start();
Quick Start: Choose Your Stack
Decision Tree
Q1: Language?
├── Python → Q2
└── TypeScript/JS → grammY (see references/typescript-grammy.md)
Q2: Complexity?
├── Simple script / notification bot → python-telegram-bot v21
└── Multi-user, async, FSM, production → aiogram 3.x
Q3: Database?
├── Prototype / single instance → SQLite + WAL
├── Production / multi-instance → PostgreSQL (asyncpg or Supabase)
├── Serverless → Supabase Edge Functions + PostgREST
└── Russia (152-FZ) → Yandex Cloud (Managed PG + Cloud Functions)
Q4: Hosting?
├── Full control → VPS + systemd/PM2
├── Containers → Docker + compose
├── Serverless → Cloudflare Workers / Supabase Edge / Yandex CF
└── PaaS → Railway / Fly.io / Render
Framework Comparison
| Factor |
aiogram 3.x |
python-telegram-bot v21 |
grammY |
| Language |
Python 3.10+ |
Python 3.9+ |
TypeScript/JS |
| Async |
Native asyncio |
Optional (v20+) |
Native |
| FSM |
StatesGroup, 5 scoping strategies |
ConversationHandler |
Conversations plugin (replay engine) |
| Bot API |
10.0 (May 2026) |
Latest |
Latest |
| Middleware |
BaseMiddleware chain |
Handler groups |
Koa-style stack |
| Best for |
Production, high-load, Russian community |
Simple bots, scripts, beginners |
TypeScript projects, serverless |
| Maintained |
Active (3.28.2) |
Active (v21.11.1) |
Active |
Telegraf v4 is in maintenance mode (no v5 shipped). New projects should use grammY.
Architecture Patterns
1. Monolith (single process)
Best for: early stage, <1000 DAU, simple logic.
Bot process → handles updates → DB (SQLite/Postgres)
Stack: aiogram + MemoryStorage + PM2/systemd.
2. Queue-based (webhook → queue → worker)
Best for: AI bots (LLM response >5s), high volume.
Telegram → webhook endpoint (200 OK immediately)
→ SQS/RabbitMQ (MessageGroupId=user_id)
→ worker process → Telegram API
Prevents webhook timeouts. Per-user ordering without cross-user blocking.
3. Serverless (cloud function per webhook)
Best for: low traffic, pay-per-use, no ops.
Telegram → Cloud Function → response
Requires: fast cold start (<1s), external state (Redis/KV/DB).
grammY has first-class serverless support: bot.handleUpdate(req.body).
4. Microservice (separate handlers)
Best for: >100k DAU, large teams, complex domains.
Overkill for most bots. Consider queue-based first.
Webhook vs Polling
| Scenario |
Use |
| Local development |
Polling -- no domain/SSL needed |
| Production VPS |
Either; webhook has lower latency |
| Serverless |
Webhook only -- polling needs persistent process |
| High-volume |
Webhook -- 3x lower median latency |
| Behind firewall |
Polling -- outbound only |
Webhook security (mandatory):
- Secret token:
setWebhook(secret_token=...) → validate X-Telegram-Bot-Api-Secret-Token header
- IP whitelist (optional):
149.154.160.0/20, 91.108.4.0/22
References (load on demand)
Load only the reference needed for the current task:
| File |
When to load |
| references/python-aiogram.md |
Building with aiogram 3.x (FSM, routers, middleware, handlers) |
| references/typescript-grammy.md |
Building with grammY (sessions, conversations, plugins) |
| references/databases.md |
Choosing/configuring database (SQLite, Supabase, PostgreSQL, Yandex Cloud) |
| references/deployment.md |
Deploying bot (VPS, Docker, serverless, PaaS, reverse proxy) |
| references/ai-integration.md |
Adding AI/LLM (streaming, context, token management) |
| references/payments.md |
Telegram Stars, Stripe, CloudPayments, subscriptions |
| references/security.md |
Webhook validation, rate limiting, anti-spam, WebApp auth |
Project Structure (aiogram 3.x)
bot/
├── bot.py # Entry point, Dispatcher setup
├── config.py # Settings from env (pydantic-settings)
├── handlers/
│ ├── __init__.py # Router registration
│ ├── start.py # /start, /help
│ ├── admin.py # Admin commands
│ └── payments.py # Payment handlers
├── middlewares/
│ ├── throttling.py # Rate limiting
│ ├── auth.py # Access control
│ └── i18n.py # Internationalization
├── keyboards/
│ ├── inline.py # InlineKeyboardMarkup builders
│ └── reply.py # ReplyKeyboardMarkup builders
├── states/
│ └── forms.py # StatesGroup definitions
├── services/
│ ├── db.py # Database layer
│ └── ai.py # AI/LLM integration
├── filters/
│ └── admin.py # Custom filters
├── .env
├── Dockerfile
└── requirements.txt
Project Structure (grammY)
bot/
├── src/
│ ├── bot.ts # Bot instance, middleware registration
│ ├── config.ts # Environment config
│ ├── handlers/
│ │ ├── start.ts
│ │ ├── admin.ts
│ │ └── payments.ts
│ ├── conversations/
│ │ └── registration.ts
│ ├── middleware/
│ │ ├── auth.ts
│ │ └── session.ts
│ ├── keyboards/
│ │ └── menus.ts
│ └── services/
│ ├── db.ts
│ └── ai.ts
├── .env
├── Dockerfile
├── package.json
└── tsconfig.json
Validation Checklist
Before shipping, verify:
1---2name: telegram-bot-builder3description: Build production-grade Telegram bots from scratch -- architecture, code, database, deployment, monetization. Supports Python (aiogram 3.x, python-telegram-bot v21) and TypeScript (grammY). Database flexibility: SQLite local, Supabase (PostgREST + Edge Functions + RLS), PostgreSQL (asyncpg, Prisma, Drizzle), Yandex Cloud, Redis. Covers webhook/polling, FSM, middleware, AI integration (OpenAI/Claude streaming), Telegram Stars payments, Mini Apps, Business API. Use when: (1) creating a new Telegram bot, (2) adding features to existing bot, (3) choosing stack/database for a bot, (4) deploying a bot to production, (5) integrating AI/LLM into a bot, (6) adding payments/Stars, (7) scaling a bot, (8) securing webhook endpoints. Triggers: telegram bot, tg bot, aiogram, grammy, bot api, telegram payments, telegram stars, bot webhook, bot polling, bot fsm, bot deployment, inline keyboard, conversation handler, mini app bot.4---56# Telegram Bot Builder78Build production-grade Telegram bots. This skill covers the full lifecycle:9architecture selection, framework choice, database integration, deployment,10monetization, and security.1112## Minimal Hello World1314**Python (aiogram 3.x):**15```python16import asyncio17from aiogram import Bot, Dispatcher, Router, F18from aiogram.types import Message1920router = Router()2122@router.message(F.text == "/start")23async def start(message: Message) -> None:24 await message.answer("Hello! I'm alive.")2526async def main() -> None:27 bot = Bot(token="BOT_TOKEN")28 dp = Dispatcher()29 dp.include_router(router)30 await dp.start_polling(bot)3132asyncio.run(main())33```3435**TypeScript (grammY):**36```typescript37import { Bot } from "grammy";3839const bot = new Bot(process.env.BOT_TOKEN!);4041bot.command("start", (ctx) => ctx.reply("Hello! I'm alive."));4243bot.start();44```4546## Quick Start: Choose Your Stack4748### Decision Tree4950```51Q1: Language?52├── Python → Q253└── TypeScript/JS → grammY (see references/typescript-grammy.md)5455Q2: Complexity?56├── Simple script / notification bot → python-telegram-bot v2157└── Multi-user, async, FSM, production → aiogram 3.x5859Q3: Database?60├── Prototype / single instance → SQLite + WAL61├── Production / multi-instance → PostgreSQL (asyncpg or Supabase)62├── Serverless → Supabase Edge Functions + PostgREST63└── Russia (152-FZ) → Yandex Cloud (Managed PG + Cloud Functions)6465Q4: Hosting?66├── Full control → VPS + systemd/PM267├── Containers → Docker + compose68├── Serverless → Cloudflare Workers / Supabase Edge / Yandex CF69└── PaaS → Railway / Fly.io / Render70```7172### Framework Comparison7374| Factor | aiogram 3.x | python-telegram-bot v21 | grammY |75|--------|------------|------------------------|--------|76| Language | Python 3.10+ | Python 3.9+ | TypeScript/JS |77| Async | Native asyncio | Optional (v20+) | Native |78| FSM | StatesGroup, 5 scoping strategies | ConversationHandler | Conversations plugin (replay engine) |79| Bot API | 10.0 (May 2026) | Latest | Latest |80| Middleware | BaseMiddleware chain | Handler groups | Koa-style stack |81| Best for | Production, high-load, Russian community | Simple bots, scripts, beginners | TypeScript projects, serverless |82| Maintained | Active (3.28.2) | Active (v21.11.1) | Active |8384> **Telegraf v4** is in maintenance mode (no v5 shipped). New projects should use grammY.8586## Architecture Patterns8788### 1. Monolith (single process)89Best for: early stage, <1000 DAU, simple logic.90```91Bot process → handles updates → DB (SQLite/Postgres)92```93Stack: aiogram + MemoryStorage + PM2/systemd.9495### 2. Queue-based (webhook → queue → worker)96Best for: AI bots (LLM response >5s), high volume.97```98Telegram → webhook endpoint (200 OK immediately)99 → SQS/RabbitMQ (MessageGroupId=user_id)100 → worker process → Telegram API101```102Prevents webhook timeouts. Per-user ordering without cross-user blocking.103104### 3. Serverless (cloud function per webhook)105Best for: low traffic, pay-per-use, no ops.106```107Telegram → Cloud Function → response108```109Requires: fast cold start (<1s), external state (Redis/KV/DB).110grammY has first-class serverless support: `bot.handleUpdate(req.body)`.111112### 4. Microservice (separate handlers)113Best for: >100k DAU, large teams, complex domains.114Overkill for most bots. Consider queue-based first.115116## Webhook vs Polling117118| Scenario | Use |119|----------|-----|120| Local development | Polling -- no domain/SSL needed |121| Production VPS | Either; webhook has lower latency |122| Serverless | Webhook only -- polling needs persistent process |123| High-volume | Webhook -- 3x lower median latency |124| Behind firewall | Polling -- outbound only |125126Webhook security (mandatory):1271. **Secret token**: `setWebhook(secret_token=...)` → validate `X-Telegram-Bot-Api-Secret-Token` header1282. **IP whitelist** (optional): `149.154.160.0/20`, `91.108.4.0/22`129130## References (load on demand)131132Load only the reference needed for the current task:133134| File | When to load |135|------|-------------|136| [references/python-aiogram.md](references/python-aiogram.md) | Building with aiogram 3.x (FSM, routers, middleware, handlers) |137| [references/typescript-grammy.md](references/typescript-grammy.md) | Building with grammY (sessions, conversations, plugins) |138| [references/databases.md](references/databases.md) | Choosing/configuring database (SQLite, Supabase, PostgreSQL, Yandex Cloud) |139| [references/deployment.md](references/deployment.md) | Deploying bot (VPS, Docker, serverless, PaaS, reverse proxy) |140| [references/ai-integration.md](references/ai-integration.md) | Adding AI/LLM (streaming, context, token management) |141| [references/payments.md](references/payments.md) | Telegram Stars, Stripe, CloudPayments, subscriptions |142| [references/security.md](references/security.md) | Webhook validation, rate limiting, anti-spam, WebApp auth |143144## Project Structure (aiogram 3.x)145146```147bot/148├── bot.py # Entry point, Dispatcher setup149├── config.py # Settings from env (pydantic-settings)150├── handlers/151│ ├── __init__.py # Router registration152│ ├── start.py # /start, /help153│ ├── admin.py # Admin commands154│ └── payments.py # Payment handlers155├── middlewares/156│ ├── throttling.py # Rate limiting157│ ├── auth.py # Access control158│ └── i18n.py # Internationalization159├── keyboards/160│ ├── inline.py # InlineKeyboardMarkup builders161│ └── reply.py # ReplyKeyboardMarkup builders162├── states/163│ └── forms.py # StatesGroup definitions164├── services/165│ ├── db.py # Database layer166│ └── ai.py # AI/LLM integration167├── filters/168│ └── admin.py # Custom filters169├── .env170├── Dockerfile171└── requirements.txt172```173174## Project Structure (grammY)175176```177bot/178├── src/179│ ├── bot.ts # Bot instance, middleware registration180│ ├── config.ts # Environment config181│ ├── handlers/182│ │ ├── start.ts183│ │ ├── admin.ts184│ │ └── payments.ts185│ ├── conversations/186│ │ └── registration.ts187│ ├── middleware/188│ │ ├── auth.ts189│ │ └── session.ts190│ ├── keyboards/191│ │ └── menus.ts192│ └── services/193│ ├── db.ts194│ └── ai.ts195├── .env196├── Dockerfile197├── package.json198└── tsconfig.json199```200201## Validation Checklist202203Before shipping, verify:204205- [ ] Bot token in env var, never hardcoded206- [ ] `bot.catch()` or `@dp.errors()` global error handler207- [ ] Webhook: secret token validation enabled208- [ ] Rate limiting per user (Redis counter or middleware)209- [ ] Input length validation (`len(text) > MAX` → reject)210- [ ] HTML escape user input before `parse_mode="HTML"`211- [ ] FSM storage: NOT MemoryStorage in production212- [ ] Graceful shutdown: SIGINT/SIGTERM handlers213- [ ] Typing indicator (`sendChatAction("typing")`) before slow ops214- [ ] Message length: split at 4096 chars