
بات سرورلس تلگرام: راهنمای کامل پلتفرم رسمی Telegram Serverless و tgcloud
تعریف کوتاه: «Telegram Serverless» پلتفرم رسمی تلگرام برای اجرای کد بکاند باتها و Mini Appهاست، مستقیماً روی زیرساخت خود تلگرام: ماژولهای جاوااسکریپت شما در یک V8 sandbox ایزوله، کنار Bot API و یک پایگاهدادهی داخلی مبتنی بر SQLite اجرا میشوند و با دستور
npx tgcloud pushدیپلوی میشوند، بدون سرور، بدون container، بدون نگرانی از مقیاسپذیری. پیش از معرفی این پلتفرم رسمی، عبارت «بات سرورلس تلگرام» به الگوی اجرای بات روی پلتفرمهای شخصثالث مثل Cloudflare Workers گفته میشد، الگویی که همچنان معتبر و قابل استفاده است و در همین مقاله پوشش داده شده.
بهروزرسانی مهم (ژوئیه ۲۰۲۶ / تیر ۱۴۰۵): نسخهی اول این مقاله زمانی نوشته شد که تلگرام هیچ پلتفرم سرورلس رسمی نداشت و «بات سرورلس تلگرام» صرفاً یک الگوی معماری جامعهمحور بود، و مقاله همین را با صراحت گفته بود. از آن زمان، تلگرام مستندات رسمی Telegram Serverless را منتشر کرده است. این مقاله بهطور کامل بازبینی و بهروزرسانی شده: بخشهای جدید بر اساس مستندات رسمی و تست عملی خود ما نوشته شدهاند، و الگوی قبلی (سرورلس شخصثالث) هم بهعنوان گزینهی جایگزین حفظ شده است.
بهروزرسانی مهر ۱۴۰۵ (اکتبر ۲۰۲۶): منوی Serverless حالا در BotFather ظاهر میشود، اما فعالسازی آن با ثبت درخواست در لیست انتظار انجام میشود. مستندات رسمی هم از آن زمان پشتیبانی از آپلود و دانلود فایل را اضافه کردهاند. هر دو تغییر در متن اعمال شده و یافتههای تست تیر ۱۴۰۵ بهعنوان سابقه حفظ شدهاند.
مقدمه
اگر تا امروز یک بات تلگرام ساخته باشید، احتمالاً با این چرخه آشنا هستید: یک VPS اجاره میکنید، Node.js را روی آن نصب میکنید، یک دامنه یا سابدامنه برای Webhook تنظیم میکنید، گواهی SSL میگیرید (چون Telegram Bot API فقط HTTPS را قبول میکند)، یک پایگاه داده راهاندازی میکنید، فرآیند را با PM2 یا systemd بهصورت daemon اجرا میکنید، و بعد باید نگران آپدیت امنیتی سرور، مانیتورینگ Uptime، و مقیاسپذیری در زمان افزایش ناگهانی ترافیک هم باشید.
برای یک بات کوچک شخصی، این حجم از زیرساخت اغلب بیش از خودِ منطق بات وقت میگیرد. خیلی از توسعهدهندهها یک آخر هفته را صرف «راهاندازی سرور» میکنند، نه نوشتن منطق واقعی بات. همین نقطه درد دو مسیر ایجاد کرده است:
پلتفرم رسمی Telegram Serverless، که تلگرام اخیراً معرفی کرده و کد بات شما را روی زیرساخت خود تلگرام اجرا میکند؛
الگوی سرورلس شخصثالث: اجرای بات از طریق Webhook روی پلتفرمهایی مثل Cloudflare Workers، AWS Lambda یا Vercel، که سالهاست جامعهی توسعهدهندگان از آن استفاده میکند.
در این مقاله هر دو مسیر را کامل بررسی میکنیم: پلتفرم رسمی از داخل چطور کار میکند، ما در تست عملی به چه نتایجی رسیدیم، چه محدودیتهایی دارد، الگوی شخصثالث کجا هنوز انتخاب بهتری است، و چه زمانی مهاجرت واقعاً ارزش دارد.

تلگرام حالا رسماً پلتفرم سرورلس دارد
طبق مستندات رسمی، Telegram Serverless به شما اجازه میدهد کد بکاند بات یا Mini App خود را مستقیماً روی زیرساخت تلگرام اجرا کنید. اجزای اصلی آن اینهاست:
اجرای کد در V8 Isolate: هر فراخوانی در یک محیط ایزوله و سبک از موتور جاوااسکریپت اجرا میشود که (به گفتهی مستندات) نزدیک به سیستمهای خود تلگرام قرار دارد، بنابراین فراخوانی Bot API و پایگاهداده سریع است.
Bot API داخلی: کل Bot API بدون هیچ توکنکشی و پیکربندی، از طریق SDK در دسترس هر ماژول است، مثل
api.sendMessage(...)و تمام متدهای فعلی و آینده.پایگاهدادهی داخلی SQLite: هر بات پایگاهدادهی مخصوص به خودش را دارد که بین اجراها باقی میماند (persistent) و با یک DSL شبیه Drizzle ORM تعریف و کوئری میشود.
HTTP خروجی: یک کلاینت
fetchبرای فراخوانی APIهای بیرونی (از جمله APIهای هوش مصنوعی) در SDK وجود دارد.CLI به نام tgcloud: پل بین پوشهی پروژهی شما و کلود تلگرام، دیپلوی، دیف، مهاجرت پایگاهداده و تست، همه از خط فرمان.
مدیریت از داخل BotFather: طبق مستندات، کل پروژه (هندلرها، کتابخانه، دیتابیس و توکن CLI) از داخل خود BotFather هم قابل مدیریت است، حتی از موبایل.
معماری در سادهترین شکل خودش این است:
کاربر پیام میفرستد
│
▼
سرورهای تلگرام
│ (بدون Webhook دستی — پلتفرم خودش مدیریت میکند)
▼
Serverless Runtime تلگرام
(هندلر شما در V8 Isolate)
│
▼
پایگاهدادهی داخلی SQLite
│
▼
پاسخ از طریق Bot API داخلی
تفاوت کلیدی با الگوی شخصثالث: در اینجا حتی Webhook را هم خودتان مدیریت نمیکنید. پلتفرم Webhook را خودش تنظیم میکند و allowed_updates را بر اساس هندلرهایی که دیپلوی کردهاید میسازد؛ یعنی تلگرام فقط برای آپدیتهایی کد شما را اجرا میکند که واقعاً هندلر دارند. یک نکتهی عملی: طبق مستندات، اضافه یا حذف کردن یک هندلر میتواند Webhook را تا همگامسازی بعدی «out of sync» کند. اگر هندلر جدیدتان آپدیتی دریافت نمیکند، اول خروجی npx tgcloud status یا npx tgcloud webhook را ببینید و با npx tgcloud webhook sync آن را دوباره همگام کنید.
وضعیت عرضه: چه چیزی الان واقعاً در دسترس است؟
این مهمترین بخش این بهروزرسانی است و میخواهم کاملاً شفاف باشد، چون ترکیب «مستندات عمومی» و «دسترسی محدود» دقیقاً جایی است که توسعهدهندهها سردرگم میشوند.
خلاصهی وضعیت (مهر ۱۴۰۵): مستندات و CLI رسمی عمومی هستند و منوی Serverless حالا در BotFather ظاهر میشود، اما فعالسازی آن فعلاً با ثبت درخواست در لیست انتظار انجام میشود. تا وقتی درخواست شما تأیید نشده، توکن CLI در دسترس نیست. فرض نکنید همین امروز برای بات شما فعال است.
| جزء | وضعیت | منبع |
|---|---|---|
| مستندات رسمی (core.telegram.org) | ✅ منتشر شده و عمومی | مستندات رسمی |
CLI رسمی (پکیج @tgcloud/cli در npm) | ✅ قابل نصب؛ ما نسخهی 0.1.2 را تست کردیم و نسخهی 0.2.0 در مهر ۱۴۰۵ منتشر شد | تست عملی ما و npm |
فرمان tgcloud login | ✅ اجرا میشود و توکن CLI میخواهد | تست عملی ما |
| منوی Serverless در BotFather | ✅ ظاهر میشود (در تیر ۱۴۰۵ ظاهر نمیشد) | بررسی مجدد ما، مهر ۱۴۰۵ |
| فعالسازی Serverless | ⏳ با ثبت درخواست و قرار گرفتن در لیست انتظار | بررسی مجدد ما، مهر ۱۴۰۵ |
| CLI Access Token (پیشنیاز لاگین) | ⛔ فقط پس از فعال شدن Serverless، از همان منو | مستندات رسمی |
این جمعبندی از دو منبع میآید: آنچه مستندات رسمی میگویند و بررسی دستاول خود ما. مستندات فقط میگویند «در BotFather بات را باز کنید، Serverless را بزنید و روشنش کنید» و هیچ اشارهای به لیست انتظار نمیکنند؛ لیست انتظار چیزی است که ما در خود BotFather دیدیم. زمان تأیید درخواست هم جایی اعلام نشده است.
تست واقعی ما: نصب و لاگین در عمل
برای اینکه این مقاله فقط بازگویی مستندات نباشد، خودمان پلتفرم را از صفر تست کردیم. محیط تست: ویندوز، Node.js، و آخرین نسخهی CLI در زمان نگارش. نتایج دقیق:
npx tgcloud --versionنسخهی رسمی0.1.2را برگرداند. پکیج رسمی@tgcloud/cliاست و دستوری که نصب میکندtgcloudنام دارد (هشدار پایین همین بخش را ببینید).npx tgcloud loginهم اجرا شد و یک prompt نمایش داد، اما نه برای توکن معمولی بات، بلکه برای CLI Access Token با قالبapp<id>:<secret>. توکن آشنای Bot API (قالب123456:AA...) اینجا پذیرفته نمیشود؛ این دو توکن کاملاً متفاوتاند (بخش بعدی را ببینید).برای گرفتن CLI Access Token، طبق مستندات باید به BotFather بروید: بات → Serverless → CLI Access. اما در تست تیر ۱۴۰۵، منوی Serverless ظاهر نشد: نه برای یک بات موجود، نه برای یک بات کاملاً جدید، و نه حتی با یک حساب تلگرام تازهساخته.
چرا این یافته مهم است؟ چون زنجیرهی راهاندازی در یک نقطهی مشخص قطع میشود: CLI عمومی است و لاگین کار میکند، اما کلیدِ ورود (توکن CLI) فقط بعد از فعال شدن Serverless برای بات شما در دسترس است. در تیر ۱۴۰۵ این منو اصلاً ظاهر نمیشد؛ در بررسی مجدد ما در مهر ۱۴۰۵ منو هست، اما فعالسازی با ثبت درخواست در لیست انتظار انجام میشود. اگر CLI را نصب کردهاید و پشت همین در ماندهاید، مشکل از شما نیست: درخواست را ثبت کنید و تا تأیید آن کدتان را بنویسید. بقیهی این مقاله نقشهی کامل را برای وقتی که دسترسی باز شد به شما میدهد.
npx tgcloud فقط وقتی CLI رسمی را اجرا میکند که @tgcloud/cli در همان پروژه یا بهصورت سراسری نصب باشد. اگر آن را در یک پوشهی خالی اجرا کنید، npx پکیجی با نام دقیق tgcloud را از npm دانلود و اجرا میکند که متعلق به توسعهدهندهی دیگری است و جزو پلتفرم رسمی تلگرام نیست. پس اول پروژه را با npm create @tgcloud/bot بسازید یا CLI را با npm install -g @tgcloud/cli نصب کنید، و هرگز توکن CLI را به ابزاری که منشأش را بررسی نکردهاید ندهید.مدل احراز هویت: دو توکن که نباید اشتباه بگیرید
تلگرام حالا عملاً دو نوع credential مختلف برای باتها دارد و تجربهی ما نشان داد این اولین جایی است که توسعهدهندهها گیج میشوند:
| Bot API Token | CLI Access Token | |
|---|---|---|
| قالب | 123456:AAxxxxxxxx... | app<id>:<secret> |
| برای چه کاری | فراخوانی مستقیم Bot API (sendMessage و غیره) | اتصال پروژهی محلی به کلود تلگرام از طریق tgcloud |
| از کجا میآید | BotFather → API Token | BotFather → بات → Serverless → CLI Access |
| کجا ذخیره میشود | هر جا خودتان امن نگه دارید | .tgcloud/credentials (بهصورت خودکار git-ignore) |
| در CI | متغیر محیطی دلخواه شما | متغیر محیطی TGCLOUD_TOKEN |
چند نکته از مستندات که ارزش دانستن دارد: بخش app<id> عمومی است و ممکن است در خروجیها چاپ شود، اما بخش secret هرگز در لاگ یا خطاها ظاهر نمیشود. login تنها دستوری است که توکن میپرسد: هیچ دستور دیگری وسط کار prompt نمیزند (تا اسکریپتها و CI هنگ نکنند)، و اگر توکن ذخیرهشده باطل شود، CLI آن را پاک میکند و از شما میخواهد دوباره login کنید.
نکتهی جالب برای کسانی که با پلتفرم رسمی کار میکنند: داخل هندلرها اصلاً به هیچ توکنی نیاز ندارید. api در SDK از قبل به بات شما متصل است، یکی از تفاوتهای ملموس با الگوی شخصثالث که در آن باید توکن بات را در متغیر محیطی Worker نگه دارید.
دو رفتار api هم با Bot API خام فرق دارد: نتیجه بدون پوشش { ok, result } برمیگردد (getMe() مستقیماً شیء کاربر را میدهد)، و هر پاسخ ok: false بهجای یک مقدار falsy، خطای BotApiError پرتاب میکند که code، description و parameters (مثل retry_after در خطای 429) را دارد. پس مدیریت خطا را با try/catch بنویسید، نه با چک کردن فیلد ok.
ساختار پروژه در Telegram Serverless
یک پروژهی سرورلس تلگرام، یک پوشهی معمولی تحت کنترل نسخه است: نه build step دارد، نه node_modules در زمان اجرا، نه فایل ورودی سرور. ساختار استاندارد (خروجی npm create @tgcloud/bot):
example_bot/
├─ docs/
│ └─ tgcloud-sdk.md # مرجع SDK — برای شما و ابزارهای AI
├─ handlers/ # نقطههای ورود — یک فایل به ازای هر نوع آپدیت (flat)
│ ├─ message.js
│ └─ callback_query.js
├─ lib/ # کد مشترک — تنها پوشهای که زیرپوشه مجاز است
│ └─ internal/util.js
├─ AGENTS.md # راهنمای پروژه برای دستیارهای کدنویسی AI
├─ package.json
├─ schema.js # تعریف جدولهای پایگاهداده — یک فایل، در ریشه
└─ .tgcloud/ # وضعیت CLI: توکن، کش، کپی مرجع (git-ignored)
سه نوع کد بیشتر وجود ندارد و مسئولیت هر کدام دقیقاً مشخص است:
handlers/: نقطههای ورود بات. هر فایل متناظر یک نوع آپدیت تلگرام است:handlers/message.jsبرای پیامها،handlers/callback_query.jsبرای دکمهها،handlers/inline_query.jsبرای اینلاین و به همین ترتیب برای هر نوع آپدیت Bot API. وقتی آپدیتی میرسد، پلتفرم آن را به هندلر همنام مسیریابی میکند وexport defaultآن فایل را با payload بازشده صدا میزند (هندلرmessageمستقیماً شیءMessageرا میگیرد، نه کلUpdateرا). هندلر یک آرگومان دوم هم میگیرد، یعنیctx، کهUpdateخام را درctx.updateنگه میدارد؛ برای چیزهایی مثلupdate_idکه در payload نیستند سراغ آن بروید (درtgcloud runبا فلگ--ctxشبیهسازی میشود). فایل هندلر خالی هم مثل نبودن آن حساب میشود. اگر برای نوعی از آپدیت هندلری وجود نداشته باشد، آن آپدیت بهسادگی نادیده گرفته میشود و کد شما اصلاً اجرا نمیشود، پس فقط هندلرهایی را بسازید که واقعاً لازم دارید.lib/: کد مشترک بین هندلرها، مثل helperها، لایهی دسترسی به داده، یکپارچهسازی با سرویسهای بیرونی. پلتفرم هرگز ماژولهایlib/را مستقیم اجرا نمیکند؛ فقط برای import شدن وجود دارند.schema.js: تعریف جدولهای پایگاهداده بهصورت named export، با یک DSL شبیه Drizzle. دیپلوی این فایل هرگز خودش دیتابیس را تغییر نمیدهد (بخش بعد).
سیستم ماژول هم عمداً محدود و قابل پیشبینی است؛ در زمان اجرا فقط دو چیز قابل import است: sdk (و زیرماژولهایش مثل sdk/db) و ماژولهای خود پروژه با نام خام (from 'schema'، from 'lib/cart'). مسیر نسبی (./schema) و پسوند .js کامپایل نمیشوند، و هیچ پکیج npm ای در زمان اجرا وجود ندارد. با npx tgcloud push دقیقاً همین مجموعه (schema.js بهعلاوهی فایلهای .js داخل lib/ و handlers/) بهصورت اتمیک دیپلوی میشود و وضعیت کلود آینهی پوشهی شما میشود، شامل حذفها. بقیهی فایلها (Markdown، فایلهای کانفیگ و پوشهی .tgcloud/) هرگز دیپلوی نمیشوند، و اگر فقط چند فایل را push کنید (مثلاً push handlers/message.js)، ماژولهای دیگر حذف نمیشوند.
پایگاه داده: SQLite داخلی و مدل مهاجرت
هر بات یک پایگاهدادهی اختصاصی مبتنی بر SQLite دارد که بین اجراها باقی میماند و از هر ماژولی با db در دسترس است. اگر با Drizzle ORM کار کرده باشید، عملاً چیزی برای یادگیری ندارید: column builderها، select().from().where()، اپراتورها، onConflictDoUpdate و تگ sql همان رفتار آشنا را دارند؛ فقط از sdk/db import میشوند. یک نمونهی واقعی از مستندات:
// 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 [row] = await db.insert(counters)
.values({ chatId: message.chat.id, seen: 1 })
.onConflictDoUpdate({
target: counters.chatId,
set: { seen: sql`${counters.seen} + 1` },
})
.returning()
.run();
await api.sendMessage({
chat_id: message.chat.id,
text: `تا حالا ${row.seen} پیام از شما دیدهام.`,
});
}
DSL ستونهای text، integer، real، blob، boolean و json را دارد، زمان را با mode: 'timestamp' به Date تبدیل میکند، و از ایندکسهای جزئی و عبارتی، قیدهای unique و check و ستونهای generated پشتیبانی میکند. یک دام کوچک: این تبدیلها فقط در query builder انجام میشوند. اگر با db.all(sql`...`) کوئری خام بزنید، boolean بهصورت 0/1، JSON بهصورت رشته و timestamp بهصورت عدد برمیگردد.
چرا push و migrate از هم جدا هستند؟
این جداسازی مهمترین تصمیم طراحی پلتفرم در بخش داده است: دیپلوی کد هرگز به پایگاهداده دست نمیزند.
npx tgcloud push # دیپلوی ماژولها؛ تغییرات معلقِ دیتابیس را فقط گزارش میکند
npx tgcloud migrate # بازبینی و اعمال تغییرات اسکیما — با تأیید شما
وقتی schema.js تغییرکردهای را push میکنید، پلتفرم اسکیمای جدید را ثبت میکند و به شما میگوید دیتابیس «چه تغییری خواهد کرد»، اما هیچ چیزی را اعمال نمیکند. دلیلش ساده و عاقلانه است: یک دیپلوی روتین کد نباید بتواند بهطور تصادفی یک migration داده را اجرا کند. تغییر داده همیشه یک تصمیم آگاهانه و جداگانه است.
migrate تفاوت بین اسکیمای شما و دیتابیس زنده را محاسبه میکند و هر تغییر را بر اساس ریسک دستهبندی میکند:
| وضعیت | یعنی چه | رفتار migrate |
|---|---|---|
| safe | افزایشی و بدون ریسک: جدول، ستون یا ایندکس جدید | همه با هم، با یک تأیید اعمال میشوند |
| warning | بالقوه مخرب یا کند: حذف چیزی، یا ایندکس روی جدول بزرگ | یکییکی نمایش داده و هر کدام جداگانه تأیید میشود |
| manual | خودکار ممکن نیست: مثل تغییر type یک ستون | با توضیح و راهکار پیشنهادی نشان داده میشود؛ خودتان انجام میدهید |
| undocumented | در دیتابیس هست ولی در اسکیمای شما نیست | فقط برای آگاهی نمایش داده میشود |
دو جزئیات دیگر که نشان میدهد طراحی چقدر محافظهکارانه (به معنای خوب کلمه) است: حذف یک جدول یا ستون از schema.js باعث drop شدن آن نمیشود؛ باید صریحاً آن را .deprecated('دلیل') علامت بزنید تا در migrate بعدی بهصورت یک warning قابل تأیید ظاهر شود. و «apply all» برای تغییرات مخرب وجود ندارد؛ هر drop یک تأیید جداگانه میخواهد. برای اسکریپتها هم فلگهای --dry-run، --safe و --yes تعریف شدهاند.
یک محدودیت مهم را همینجا بدانید: foreign key وجود ندارد. runtime با PRAGMA foreign_keys خاموش اجرا میشود و DSL عمداً .references() را با خطا متوقف میکند، چون یک foreign key که در سکوت کار نکند (بدون cascade و بدون محافظت از orphan) از نبودنش خطرناکتر است. روابط را با ستونهای ساده (userId) مدل کنید و یکپارچگی را در کد اپلیکیشن رعایت کنید. این یک محدودیت آگاهانهی پلتفرم است، نه فراموشکاری. از ابتدای طراحی بات به آن فکر کنید.
ساخت بات با هوش مصنوعی
مستندات رسمی یک بخش مستقل به نام Building with AI دارد و جالب اینجاست که این بخش دربارهی دو چیز متفاوت است که هر دو به این پلتفرم خوب مینشینند:
۱. ساختن بات به کمک دستیار کدنویسی AI
هر پروژهی جدید با دو فایل مخصوص ابزارهای AI ساخته میشود: AGENTS.md (راهنمای پروژه که ابزارهایی مثل Claude Code، Cursor و opencode خودکار میخوانند) و docs/tgcloud-sdk.md (مرجع کامل SDK). دلیلش این است که این پلتفرم چند قرارداد غیرمعمول دارد که codegen عمومی معمولاً آنها را اشتباه میگیرد: import با نام خام، نبودن foreign key، async بودن همهی فراخوانیهای db، یک هندلر به ازای هر نوع آپدیت، و جریان دومرحلهای push/migrate. با این دو فایل، دستیار AI از اول این قواعد را میداند. جریان کار پیشنهادی خود مستندات:
npm create @tgcloud/bot my-bot
cd my-bot
# بعد دستیار AI خود را باز کنید و به زبان ساده بگویید چه باتی میخواهید
شما بازبینی میکنید، با npx tgcloud run بدون دیپلوی تست میگیرید، و با push و migrate زنده میکنید. (اگر به این حوزه علاقه دارید، مقالهی WebMCP و ایجنتهای هوش مصنوعی را هم ببینید. همین الگوی «محیطِ از قبل آماده برای ایجنت» در وب هم در حال شکلگیری است.)
۲. ساختن بات هوش مصنوعی (اتصال به LLM)
خود مستندات، «باتهای مکالمهای AI که وضعیت هر کاربر را در دیتابیس نگه میدارند» را یکی از کاربردهای ایدهآل پلتفرم معرفی میکند. جریان درخواست اینطور است:
کاربر ← پیام میفرستد
│
▼
تلگرام ← آپدیت را به هندلر میرساند
│
▼
هندلر Serverless ← تاریخچه را از SQLite میخواند
│
▼
فراخوانی LLM از طریق sdk fetch
(OpenAI / Claude / Gemini — هر API مبتنی بر HTTP)
│
▼
پاسخ ← ذخیره در SQLite ← ارسال با api.sendMessage
دو قابلیت مستندشده این سناریو را عملی میکند: اول اینکه fetch در SDK از خواندن استریمی بدنهی پاسخ پشتیبانی میکند (for await (const chunk of res.body)) و مستندات صریحاً «خروجی token-by-token از APIهای هوش مصنوعی» را بهعنوان کاربرد آن نام میبرد. دوم اینکه تاریخچهی مکالمه در همان دیتابیس داخلی نگهداری میشود، بدون سرویس جداگانه.
دربارهی تأخیر (latency) بگذارید دقیق باشیم، نه تبلیغاتی؛ مزیت این معماری در دو سرِ زنجیره است: دریافت آپدیت و فراخوانی Bot API و دیتابیس، همه داخل زیرساخت تلگرام و سریعاند. اما خودِ فراخوانی LLM یک درخواست HTTP به بیرون است و همان قدر طول میکشد که از هر جای دیگری طول میکشید؛ در عمل، زمانِ LLM بخش غالب کل زمان پاسخ است. چیزی که این معماری واقعاً حذف میکند تأخیر و پیچیدگی زیرساختِ خودتان است، نه تأخیر مدل زبانی. دو محدودیت fetch را هم در طراحی لحاظ کنید: بدنهی پاسخ بهصورت متن خوانده میشود (json()، text() یا استریم res.body) و سقف کل پاسخ ۳۰ مگابایت است؛ استریم کردن فقط پردازش تدریجی را ممکن میکند و این سقف را بالا نمیبرد.
چیتشیت دستورات tgcloud
دستورهایی که روزانه استفاده میشوند، به همان ترتیبی که در کار واقعی میآیند:
npm create @tgcloud/bot my-bot # ساخت پروژه و نصب CLI رسمی داخل آن (Node.js 18 یا جدیدتر)
cd my-bot
npx tgcloud login # اتصال پروژه به بات (CLI Access Token میخواهد)
npx tgcloud status # چه چیزی نسبت به نسخهی دیپلویشده تغییر کرده (آفلاین)
npx tgcloud run handlers/message '{ chat: { id: 1 }, text: "hi" }' # اجرا روی پلتفرم بدون دیپلوی
npx tgcloud push # دیپلوی اتمیک ماژولها به کلود تلگرام
npx tgcloud migrate # بازبینی و اعمال تغییرات اسکیمای دیتابیس
و فهرست کامل دستورها طبق مرجع CLI:
| دستور | کار |
|---|---|
init | ساخت اسکلت پروژهی جدید در پوشهی فعلی |
add | ساخت یک ماژول جدید (هندلر یا ماژول lib)، مثلاً add handlers/callback_query |
login | اتصال پروژه به بات و ذخیرهی توکن در .tgcloud/credentials |
status | چه چیزی نسبت به نسخهی دیپلویشده تغییر کرده (کاملاً آفلاین) |
diff | تفاوت خطبهخط تغییرات (آفلاین) |
push | دیپلوی اتمیک؛ وضعیت کلود را آینهی پوشهی شما میکند |
migrate | اعمال تغییرات اسکیما با دستهبندی safe / warning / manual |
run | اجرای یک هندلر روی پلتفرم با فایلهای محلی، بدون دیپلوی؛ سریعترین حلقهی تست |
fetch | بهروزرسانی کپی مرجع محلی از کلود، بدون دست زدن به فایلهای شما |
pull | همراستا کردن فایلهای محلی با وضعیت کلود |
reset | دور ریختن تغییرات محلی و بازگشت به وضعیت کلود |
webhook | بازرسی Webhookِ مدیریتشده توسط پلتفرم؛ webhook sync آن را دوباره همگام میکند |
completion | اسکریپت تکمیل خودکار شل (bash/zsh/fish) |
یک مکانیزم ظریف که ارزش اشاره دارد: هر پروژه یک revision صعودی در کلود دارد. اگر همتیمی شما (یا ماشین دیگری) زودتر دیپلوی کرده باشد، push شما رد میشود تا کار او را بیصدا بازنویسی نکنید؛ بعد با fetch یا pull همگام میشوید، یا آگاهانه push --force میزنید. همین optimistic concurrency است که کار تیمی بدون فرآیند قفلگذاری را ممکن میکند.
برای CI: همهی دستورها در صورت خطا با کد غیرصفر خارج میشوند، توکن از متغیر TGCLOUD_TOKEN خوانده میشود، و migrate بدون فلگ در محیط غیرتعاملی خطا میدهد؛ در pipeline از migrate --dry-run یا migrate --safe استفاده کنید.
محدودیتهای پلتفرم رسمی
صادقانه بگوییم چه چیزهایی الان محدود یا نامشخص است. اول محدودیتهای مستند:
فقط جاوااسکریپت: runtime یک V8 sandbox است؛ نه Python، نه Go، نه هیچ زبان دیگری.
بدون پکیج npm در زمان اجرا: فقط
sdkو ماژولهای خود پروژه قابل import هستند. نه grammY، نه Telegraf، نه هیچ کتابخانهی دیگری. هر چیزی که لازم دارید یا در SDK هست یا باید خودتان درlib/بنویسید.بدون فایلسیستم و شبکهی آزاد: دسترسی به بیرون فقط از طریق
fetchدر SDK است؛ بدنهی پاسخها بهصورت متن خوانده میشود و سقف کل هر پاسخ ۳۰ مگابایت است؛ ارسال بایت یا فایل در بدنهی درخواست (مثلاً آپلود به یک API بیرونی) پشتیبانی میشود.کار با فایلها حالا ممکن است، با سقفهای Bot API: در نسخهی قبلی این مقاله نوشته بودیم که دانلود و آپلود بایت فایل از داخل هندلر هنوز پشتیبانی نمیشود. مستندات فعلی این را برطرف کردهاند: با
InputFileفایل جدید آپلود میکنید و باapi.getFileContent(file_id)یاapi.getFileStream(file_id)بایتهای یک فایل را میخوانید، بدون اینکه به توکن یا آدرس دانلود دست بزنید. سقفها همان سقفهای Bot API است: آپلود تا ۵۰ مگابایت (عکس ۱۰ مگابایت) و دانلود تا ۲۰ مگابایت.بدون foreign key: همانطور که در بخش دیتابیس گفتیم، آگاهانه و قطعی.
عرضهی محدود: منوی Serverless حالا در BotFather هست، اما فعالسازی فعلاً با لیست انتظار است (بررسی ما در مهر ۱۴۰۵؛ بالاتر).
و مواردی که هنوز مستند نشده و ما هم حدس نمیزنیم: اینها «نامشخص» هستند، نه «بد»:
قیمتگذاری: مستندات فعلی هیچ اشارهای به هزینه، سطح رایگان یا سقف مصرف نمیکند.
محدودیتهای runtime: سقف زمان CPU یا مدت اجرای هر فراخوانی، سقف حافظه، و اندازهی مجاز پایگاهداده اعلام نشده است.
سهمیهها (quotas): تعداد فراخوانی مجاز در واحد زمان و رفتار پلتفرم زیر بار سنگین مشخص نیست.
وظایف زمانبندیشده: چیزی معادل Cron در مستندات فعلی وجود ندارد؛ مدل اجرا فقط واکنش به آپدیتهاست.
اکوسیستم هم طبیعتاً جوان است: نسخهی CLI هنوز 0.x است، نمونهکدها و ابزارهای جانبی جامعه هنوز شکل نگرفتهاند، و بهترین شیوهها (best practices) در حال کشف شدناند. هیچکدام از اینها ایراد نیست؛ فقط یعنی این پلتفرم امروز جای پروژهی جدید و آزمایش است، نه جای مهاجرت دادن بات حیاتی کسبوکارتان.
وابستگی به پلتفرم (Vendor Lock-in): معاملهای که میکنید
هر پلتفرم مدیریتشدهای یک معامله است و این یکی هم استثنا نیست. بیایید دو کفهی ترازو را بیطرفانه بسنجیم.
آنچه به دست میآورید:
زیرساخت صفر: نه سرور، نه container، نه گواهی SSL، نه پیکربندی Webhook. حتی توکن هم داخل هندلر لازم نیست.
مقیاسپذیری خودکار بدون هیچ پیکربندی.
سادهترین مسیر دیپلویی که تا امروز برای بات تلگرام وجود داشته:
pushو تمام.دیتابیس، Bot API و runtime همه کنار هم، بدون تأخیر شبکه بین اجزا و بدون یکپارچهسازی دستی.
آنچه واگذار میکنید:
قابلیت انتقال کد: منطق خالص جاوااسکریپت شما قابل انتقال است، اما همهچیز حول SDK اختصاصی (
sdk،sdk/db) نوشته میشود. مهاجرت بعدی به Cloudflare یا VPS یعنی بازنویسی لایهی دیتابیس و API، شبیه همان قفلشدگی D1 در Cloudflare، نه بدتر و نه بهتر. یک تخفیف کوچک در این حکم: چون DSL و query builder از Drizzle پیروی میکنند، لایهی دیتابیس شما به Drizzle روی SQLite یا D1 نزدیک است و مهاجرتش احتمالاً از بازنویسی کامل ارزانتر است. این برداشت ماست و هنوز آن را تست نکردهایم.قابلیت انتقال داده: دادهی شما در SQLite تلگرام است. مستندات فعلی ابزار export یا backup مستقیمی معرفی نکرده است (نامشخص، شاید بعداً اضافه شود). خروج داده فعلاً یعنی کوئری گرفتن و انتقال دستی.
وابستگی عملیاتی کامل به تلگرام: uptime، ظرفیت، قیمتگذاری آینده و حتی ادامهی حیات سرویس، همه تصمیم تلگرام است. برای باتی که کل کسبوکار شماست، این یک ریسک واقعی است که باید آگاهانه بپذیرید.
جمعبندی منصفانه: برای باتهای شخصی، ابزارهای داخلی تیم و MVPها، این معامله تقریباً همیشه به نفع شماست، زمانی که صرفهجویی میکنید از ریسک قفلشدگی باارزشتر است. برای محصولی که درآمد اصلیتان به آن گره خورده، منطق برعکس میشود: یا الگوی شخصثالث با ابزارهای استانداردتر را انتخاب کنید، یا لایهی دسترسی به داده را از اول طوری جدا بنویسید که مهاجرت بعدی ارزان باشد.
الگوی جایگزین: سرورلس روی پلتفرمهای شخصثالث
تا پیش از پلتفرم رسمی، «بات سرورلس تلگرام» یعنی همین: بات شما روی Cloudflare Workers، AWS Lambda یا Vercel اجرا میشود و از طریق Webhook با Bot API صحبت میکند. این الگو همچنان کاملاً معتبر است، و تا وقتی دسترسی پلتفرم رسمی محدود است، عملاً تنها گزینهی سرورلسی است که همین امروز میتوانید استفاده کنید. مزیتهای دیگرش هم سر جایشان است: آزادی انتخاب زبان (در Lambda)، اکوسیستم npm کامل، و ابزارهای بالغ.
معماری سنتی در مقابل معماری سرورلس
برای اینکه تفاوت را ملموس کنیم، بیایید دو رویکرد را کنار هم بگذاریم. (این مقایسه برای هر دو نوع سرورلس، رسمی و شخصثالث، صادق است.)
معماری سنتی: معماری سرورلس:
تلگرام تلگرام
│ │
▼ ▼
Webhook (دامنه + SSL شما) Runtime سرورلس
│ (فقط لحظهی نیاز اجرا میشود)
▼ │
VPS همیشهروشن ▼
│ SQLite / دیتابیس edge
▼
پایگاهدادهی جدا
| معیار | معماری سنتی (VPS) | معماری سرورلس |
|---|---|---|
| استقرار (Deployment) | نصب دستی یا اسکریپت CI/CD روی سرور | git push یا دستور CLI، دیپلوی در چند ثانیه |
| زیرساخت | مدیریت کامل توسط شما (سیستمعامل، پچهای امنیتی، فایروال) | کاملاً مدیریتشده توسط پلتفرم |
| هزینه | هزینهی ثابت ماهانه، حتی وقتی بات بیکار است | پرداخت بر اساس مصرف؛ اغلب سطح رایگان کافی است |
| نگهداری (Maintenance) | آپدیت سیستمعامل، Node.js، وابستگیها، مانیتورینگ سرور | تقریباً صفر؛ فقط کد اپلیکیشن |
| مقیاسپذیری | دستی یا نیازمند تنظیم Load Balancer/Auto Scaling | خودکار و آنی، از صفر تا هزاران درخواست |
| پایگاه داده | معمولاً PostgreSQL/MySQL روی همان سرور یا سرویس جدا | SQLite داخلی (پلتفرم رسمی) یا دیتابیس edge مثل D1 |
| مانیتورینگ | نیاز به ابزار جداگانه (Prometheus، Grafana، Uptime Robot) | معمولاً Dashboard و Log داخلی پلتفرم |
| Cold Start | صفر (سرور همیشه روشن است) | معمولاً چند میلیثانیه تا چند صدم ثانیه، بسته به پلتفرم |
| امنیت | مسئولیت کامل با شماست (پچ، فایروال، SSH) | سطح حملهی بسیار کوچکتر؛ SSL و شبکه را پلتفرم مدیریت میکند |
نکتهی مهم دربارهی ردیف Cold Start: در معماری سنتی، سروری که همیشه روشن است اصلاً cold start ندارد، اما در عوض دائم منابع مصرف میکند حتی وقتی هیچ پیامی نمیآید. در پلتفرمهایی که روی V8 Isolates کار میکنند، cold start معمولاً آنقدر کوچک است که برای یک بات چت عملاً محسوس نیست؛ Cloudflare Workers نمونهی شناختهشدهی آن است. Telegram Serverless هم طبق مستندات روی V8 isolate اجرا میشود، اما تلگرام عددی برای cold start اعلام نکرده؛ پس این را برای آن یک انتظار منطقی بدانید، نه دادهی اندازهگیریشده.
این معماری از داخل چطور کار میکند
بیایید مسیر کامل یک پیام را در الگوی شخصثالث، از لحظهای که کاربر در تلگرام تایپ میکند تا لحظهای که پاسخ را میبیند، دنبال کنیم.
کاربر پیام میفرستد
│
▼
سرورهای تلگرام
│ (HTTPS POST به آدرس Webhook شما)
▼
┌─────────────────────────┐
│ Edge Function │ ← مثلاً یک Cloudflare Worker
│ (اجرای کد JavaScript) │
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ پایگاه داده (SQLite/D1) │ ← خواندن/نوشتن وضعیت کاربر،
└─────────────────────────┘ تاریخچه مکالمه، تنظیمات و غیره
│
▼
فراخوانی Telegram Bot API
(متد sendMessage و مشابه)
│
▼
پیام به کاربر میرسد
مراحل بهصورت دقیقتر:
Incoming Update: وقتی کاربر پیامی میفرستد، تلگرام یک شیء JSON به نام
Updateمیسازد که شامل اطلاعات پیام، فرستنده، چت، و غیره است، و آن را با یک درخواستPOSTبه آدرس Webhook شما ارسال میکند.Runtime: پلتفرم serverless (مثلاً Cloudflare Workers) بلافاصله یک نمونهی سبک از محیط اجرای JavaScript را فعال میکند، نه یک ماشین مجازی کامل، بلکه یک V8 Isolate که در حد میلیثانیه آماده است.
Execution: کد شما
Updateرا پردازش میکند: تشخیص میدهد این یک دستور است یا پیام معمولی، منطق کسبوکار را اجرا میکند، و در صورت نیاز به پایگاه داده مراجعه میکند.SQLite: برای ذخیرهسازی وضعیت (مثل تاریخچهی مکالمه، تنظیمات کاربر، یا دادههای سفارش)، از یک پایگاهدادهی سازگار با SQLite که مستقیماً در لبهی شبکه (edge) در دسترس است استفاده میشود؛ Cloudflare D1 دقیقاً همین است: یک SQLite توزیعشده که بدون نیاز به سرور جداگانه، از همان Worker شما در دسترس است.
Response: در نهایت کد شما یک درخواست HTTP به متدهای Bot API (مثل
sendMessage) میزند تا پاسخ را برای کاربر ارسال کند، و اجرای تابع همانجا تمام میشود؛ هیچ فرآیندی در پسزمینه باقی نمیماند.
این چرخهی کامل، از دریافت پیام تا پاسخ، معمولاً کمتر از یک ثانیه طول میکشد و هیچ سروری در این میان «همیشه روشن» نیست. تفاوتش با پلتفرم رسمی را هم حالا میتوانید دقیق ببینید: اینجا Webhook، توکن و دیتابیس را خودتان به هم وصل میکنید؛ آنجا پلتفرم همه را از قبل به هم وصل کرده است.
کد واقعی: یک نمونهی حداقلی روی Cloudflare Workers
برای اینکه این معماری انتزاعی نماند، این هم یک نمونهی کد واقعی و حداقلی. این نمونه برای یادگیری ساختار طراحی شده، نه استفادهی مستقیم در پروداکشن، فاقد مدیریت خطا، اعتبارسنجی امضای Webhook، و محدودسازی نرخ درخواست است.
۱. معرفی آدرس Webhook به تلگرام (یکبار، بعد از دیپلوی Worker):
curl -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-worker.your-subdomain.workers.dev/webhook"}'
۲. خودِ Worker: دریافت Update، ذخیره در D1، ارسال پاسخ:
export default {
async fetch(request, env) {
if (request.method !== "POST") return new Response("OK");
const update = await request.json();
const message = update.message;
if (!message) return new Response("OK");
const chatId = message.chat.id;
const text = message.text ?? "";
// خواندن/نوشتن وضعیت مکالمه در D1 (سازگار با SQLite)
await env.DB.prepare(
"INSERT INTO messages (chat_id, text, created_at) VALUES (?, ?, ?)"
).bind(chatId, text, Date.now()).run();
await fetch(`https://api.telegram.org/bot${env.BOT_TOKEN}/sendMessage`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ chat_id: chatId, text: `پیام شما دریافت شد: ${text}` }),
});
return new Response("OK");
},
};
۳. تعریف جدول در D1 (یکبار، قبل از اولین دیپلوی):
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chat_id INTEGER NOT NULL,
text TEXT,
created_at INTEGER NOT NULL
);
همین سه قطعه، یک بات کارکنندهی کامل است: Webhook معرفی شده، Worker پیام را میگیرد و در D1 ذخیره میکند، و پاسخ را برمیگرداند. نسخهی پروداکشنآماده به موارد بیشتری نیاز دارد (اعتبارسنجی هدر X-Telegram-Bot-Api-Secret-Token، مدیریت خطای شبکه، و جداسازی منطق دستورات)، اما ساختار پایه همین است.
مقایسهاش با نمونهی رسمی در بخش دیتابیس آموزنده است: آنجا نه setWebhook بود، نه env.BOT_TOKEN، نه ساخت دستی جدول، هر سه را پلتفرم جذب کرده بود. این دقیقاً همان «boilerplate»ای است که Telegram Serverless حذف میکند.
مزایای این رویکرد
این مزایا بین هر دو مسیر سرورلس (رسمی و شخصثالث) مشترکاند:
بهرهوری توسعهدهنده: بدون نیاز به تنظیم SSH، فایروال، یا پیکربندی Nginx، توسعهدهنده میتواند مستقیماً روی منطق بات تمرکز کند. زمان بین «ایده» تا «اولین دیپلوی» میتواند از چند روز به چند دقیقه کاهش پیدا کند.
کاهش هزینه: بیشتر پلتفرمهای serverless سطح رایگان سخاوتمندانهای دارند. یک بات با ترافیک متوسط (مثلاً چند هزار پیام در روز) اغلب کاملاً در محدودهی رایگان Cloudflare Workers یا Vercel جا میشود، در حالی که کوچکترین VPS معمولاً حداقل ۵ دلار در ماه هزینه دارد، حتی وقتی بات کاملاً بیکار است. (قیمتگذاری پلتفرم رسمی تلگرام هنوز اعلام نشده.)
دیپلوی سریعتر: با CLI پلتفرم (wrangler deploy در Cloudflare، tgcloud push در پلتفرم رسمی) یا حتی یک git push ساده، نسخهی جدید کد در عرض چند ثانیه زنده میشود.
مقیاسپذیری خودکار: چه بات شما یک کاربر داشته باشد چه ده هزار کاربر همزمان، پلتفرم بهصورت خودکار تعداد نمونههای اجرایی را تنظیم میکند. نیازی به تنظیم دستی Auto Scaling Group یا نگرانی دربارهی ترافیک ناگهانی نیست.
امنیت: چون سروری برای پچ کردن یا مدیریت وجود ندارد، سطح حمله (attack surface) بهشدت کوچکتر است. مدیریت گواهی SSL، فایروال شبکه، و ایزولهسازی محیط اجرا بهطور کامل به عهدهی پلتفرم است.
مناسب برای MVP، هکاتون و پروژههای شخصی: وقتی هدف اعتبارسنجی سریع یک ایده است، صرف چند ساعت روی راهاندازی زیرساخت منطقی نیست. این الگو دقیقاً برای همین سناریوها طراحی شده: از ساخت یک بات در طول یک هکاتون ۴۸ ساعته تا راهاندازی یک ربات شخصی برای یادآوری کارها.
محدودیتهای الگوی شخصثالث
هیچ معماریای بدون Trade-off نیست، و این یکی هم استثنا نیست. (محدودیتهای پلتفرم رسمی را بالاتر جداگانه بررسی کردیم.)
قفلشدگی به فروشنده (Vendor Lock-in): کدی که با API اختصاصی یک پلتفرم (مثلاً D1Database در Cloudflare Workers) نوشته میشود، بهسادگی به پلتفرم دیگری قابل انتقال نیست. مهاجرت از Cloudflare Workers به AWS Lambda معمولاً به معنای بازنویسی بخش قابلتوجهی از لایهی زیرساخت است.
محدودیت زمان اجرا (Execution Limits): توابع serverless معمولاً یک سقف زمانی سختگیرانه دارند. Cloudflare Workers در سطح رایگان محدودیت زمان CPU دارد (نه زمان کل درخواست) و در سطح پولی این محدودیت بازتر میشود؛ AWS Lambda حداکثر ۱۵ دقیقه اجازهی اجرا میدهد. برای منطق سادهی بات این کاملاً کافی است، اما برای عملیات سنگین، محدودکننده میشود.
کارهای طولانیمدت (Long-running Jobs): اگر بات شما نیاز به یک فرآیند پسزمینه دارد که ساعتها طول بکشد (مثلاً پردازش دستهای فایلها یا polling مداوم یک سرویس خارجی)، معماری serverless گزینهی مناسبی نیست؛ این نوع کار باید در جای دیگری (مثل یک Worker Queue یا Cron Job جدا) انجام شود.
بارهای سنگین محاسباتی: پردازش تصویر، مدلهای یادگیری ماشین سنگین، یا هر عملیاتی که به CPU/GPU زیادی نیاز دارد، معمولاً با محدودیتهای منابع پلتفرمهای edge سازگار نیست.
نیازمندیهای سازمانی: شرکتهای بزرگ اغلب به کنترل کامل روی شبکه (VPC)، انطباق با استانداردهای خاص (مثل نگهداری داده در یک منطقهی جغرافیایی مشخص)، یا معماریهای چندلایهی پیچیده نیاز دارند که با مدل سادهی serverless همخوانی کامل ندارد.
مقایسهی کامل: Telegram Serverless، Cloudflare Workers، Vercel و AWS Lambda
حالا که هر دو مسیر را میشناسید، بیایید چهار گزینهی اصلی را کنار هم بگذاریم. ستون Telegram Serverless بر اساس مستندات رسمی است و مواردی که هنوز اعلام نشده، صادقانه «نامشخص» علامت خوردهاند.
| معیار | Telegram Serverless | Cloudflare Workers | Vercel Functions | AWS Lambda |
|---|---|---|---|---|
| Runtime | V8 sandbox: فقط JS، بدون npm | V8 Isolate: JS/TS + WASM | Node.js (Fluid Compute) | Container: زبانهای متعدد |
| دیپلوی | tgcloud push (اتمیک) | wrangler deploy | git push / CLI | Console / SAM / CDK / Terraform |
| Webhook تلگرام | خودکار: پلتفرم مدیریت میکند | دستی (setWebhook) | دستی (setWebhook) | دستی + API Gateway |
| پایگاهداده | SQLite داخلی (Drizzle-like) | D1، KV، Durable Objects | دیتابیسهای Marketplace (مثل Neon و Upstash) و سرویسهای خارجی | DynamoDB، RDS، هر سرویس AWS |
| مقیاسپذیری | خودکار (طبق مستندات) | خودکار | خودکار | خودکار |
| Cold Start | Isolate سبک؛ عدد رسمی اعلام نشده | بسیار کم (میلیثانیه) | کم تا متوسط | متوسط تا کند |
| قیمت | نامشخص: هنوز اعلام نشده | سطح رایگان سخاوتمندانه | یکپارچه با پلن Vercel | پرداخت بهازای اجرا |
| قفلشدگی | بالا (SDK و دیتابیس اختصاصی) | متوسط تا بالا (D1/KV) | متوسط | متوسط تا بالا (اکوسیستم AWS) |
| بهترین کاربرد | بات خالص تلگرامی، سادهترین راه ممکن | بات با نیاز به کنترل بیشتر + edge واقعی | باتی که بخشی از پروژهی وب/Next.js است | یکپارچگی عمیق با زیرساخت AWS |
نگاه نزدیکتر به سه پلتفرم شخصثالث
Cloudflare Workers روی مدل V8 Isolates کار میکند، یعنی بهجای اجرای یک container کامل برای هر درخواست، کد شما در یک نمونهی سبک از موتور جاوااسکریپت کروم اجرا میشود. نتیجهی مستقیم این معماری، سریعترین cold start در بین گزینههای شخصثالث است. از نظر ذخیرهسازی، ترکیب D1 (سازگار با SQLite)، KV و Durable Objects دقیقاً همان چیزی است که برای اکثر باتهای تلگرام لازم است، و سطح رایگان آن یکی از سخاوتمندانهترینهاست.
AWS Lambda پیشگام مفهوم serverless است و از نظر بلوغ اکوسیستم، یکپارچگی با سایر سرویسهای AWS (مثل DynamoDB، S3 و API Gateway)، و آزادی انتخاب زبان (Python، Go، داتنت و غیره) قدرتمندترین گزینه است. نقطهضعفش cold start کندتر بهخاطر مدل container است. اگر تیم شما از قبل روی AWS است، همین یکپارچگی میتواند تعیینکننده باشد.
Vercel اساساً برای فرانتاند (بهخصوص Next.js) طراحی شده. اگر بات تلگرام شما بخشی از یک پروژهی بزرگتر با داشبورد وب یا لندینگپیج است، همهچیز در یک ریپازیتوری و یک دیپلوی جمع میشود، تجربهی توسعهی بسیار روانی است. SQLite بومی ندارد؛ Vercel Postgres و KV دیگر ارائه نمیشوند و جایشان را دیتابیسهای Vercel Marketplace (مثل Neon و Upstash) گرفتهاند که بهراحتی یکپارچه میشوند.
آیا باتهای موجود باید مهاجرت کنند؟
پاسخ کوتاه: بستگی دارد، و تصمیم باید بر اساس واقعیتهای فنی بات شما گرفته شود، نه صرفاً به این دلیل که «serverless مد روز است»، یا حالا، به این دلیل که «رسمی شده».
جدول تصمیم بر اساس جایی که الان هستید:
| پلتفرم فعلی شما | توصیهی ما |
|---|---|
| VPS سنتی | اگر بات واکنشی و کمترافیک است، مهاجرت به سرورلس (فعلاً شخصثالث؛ رسمی وقتی دسترسی گرفتید) تقریباً همیشه بهصرفه است. اگر به Cron و فرآیند طولانی وابستهاید، بمانید یا معماری ترکیبی بسازید. |
| Railway / Render / هاست مدیریتشده | وضعیت بینابینی دارید؛ دردِ نگهداریتان کم است. فقط اگر هزینه آزارتان میدهد یا میخواهید سادهسازی کنید مهاجرت کنید. عجلهای نیست. |
| Cloudflare Workers | بمانید. شما همین حالا سرورلس هستید، با ابزار بالغتر و بدون محدودیت npm. پلتفرم رسمی را برای پروژهی بعدیتان آزمایش کنید، نه برای بازنویسی این یکی. |
| Firebase Functions | اگر فقط برای بات تلگرام از آن استفاده میکنید، Cloudflare Workers یا پلتفرم رسمی (پس از دسترسی) سبکتر و ارزانترند. اگر به بقیهی اکوسیستم Firebase وابستهاید، بمانید. |
| n8n / ابزارهای No-code | برای اتوماسیونهای ساده، n8n منطقی است. مهاجرت نکنید. وقتی منطق پیچیده شد و به کد واقعی نیاز پیدا کردید، مستقیم سراغ یکی از دو مسیر سرورلس بروید. |
| Webhook سنتی روی هاست اشتراکی (PHP و مشابه) | بهترین کاندیدای مهاجرت. هاست اشتراکی نه مقیاسپذیری دارد نه قابلیت اطمینان؛ حتی سطح رایگان Workers ارتقای جدی است. |
مهاجرت منطقی است وقتی:
بات شما ترافیک متوسط تا پایین دارد و بیشتر منابع سرور فعلی بلااستفاده میماند.
منطق بات عمدتاً واکنشی است (پاسخ به پیام) و نیازی به فرآیندهای پسزمینهی طولانی ندارد.
هزینه یا بار نگهداری سرور فعلی برای شما یا تیمتان مشکلساز شده است.
میخواهید مقیاسپذیری خودکار داشته باشید بدون درگیر شدن با تنظیمات زیرساخت.
مهاجرت منطقی نیست وقتی:
بات به وظایف زمانبندیشده یا فرآیندهای طولانیمدت (بیش از چند ثانیه) وابسته است.
از یک پایگاهدادهی رابطهای سنگین با کوئریهای پیچیده استفاده میکنید که بهسختی با مدل edge سازگار میشود.
تیم شما از قبل زیرساخت پایداری روی VPS دارد و مهاجرت هزینهی مهندسی بیشتری نسبت به مزایای آن دارد.
نیازمندیهای سازمانی خاص (انطباق، کنترل شبکه، محل نگهداری داده) دارید که با مدل serverless همخوانی ندارد.
در بسیاری از موارد، رویکرد ترکیبی منطقیتر است: منطق سبک و واکنشی بات (دریافت پیام و پاسخ سریع) روی serverless، و فرآیندهای سنگینتر (مثل پردازش دستهای یا Cron Jobهای طولانی) همچنان روی یک سرور یا سرویس صفبندی جدا.
کاربردهای عملی
الگوی بات سرورلس تلگرام (رسمی یا شخصثالث) برای طیف وسیعی از سناریوهای واقعی مناسب است:
باتهای پشتیبانی مشتری: پاسخگویی خودکار به سؤالات متداول، هدایت کاربر به بخش صحیح، و در صورت نیاز، انتقال مکالمه به یک اپراتور انسانی.
باتهای CRM: ثبت لیدها و مخاطبین مستقیماً از طریق تلگرام، بدون نیاز به فرم جداگانه.
مدیریت سفارش: پیگیری وضعیت سفارش، اطلاعرسانی تغییر وضعیت، و حتی پردازش سفارشهای ساده مستقیماً در چت.
اعلانها (Notifications): ارسال هشدار قیمت، یادآوری، یا اعلانهای سیستمی از یک سرویس بکاند به کاربران.
دستیارهای هوش مصنوعی: اتصال بات به یک مدل زبانی (LLM) برای پاسخگویی هوشمند، خلاصهسازی، یا ترجمه، با ذخیرهی تاریخچهی مکالمه در همان پایگاهدادهی SQLite. مستندات رسمی این را صریحاً یکی از کاربردهای ایدهآل پلتفرم میداند.
بکاند Mini Appها: پلتفرم رسمی علاوه بر باتها، بکاند Mini Appهای تلگرام را هم پوشش میدهد؛ ذخیرهی دادهی کاربر و سرو محتوای پویا.
بازیها و ابزارها: جدول امتیازات، کوییزها و ابزارهای تعاملی.
باتهای داخلی سازمانی: اتوماسیون فرآیندهای داخلی تیم، مثل ثبت مرخصی، گزارش روزانه، یا هشدارهای مانیتورینگ سرور، بدون نیاز به یک اپلیکیشن جداگانه.
آیندهی این اکوسیستم
اینجا باید یک اعتراف صادقانه بکنم: در نسخهی اول همین مقاله نوشتم که «بعید است خودِ تلگرام وارد بازار میزبانی serverless شود، چون خارج از حوزهی اصلی محصولش است.» دقیقاً همان اتفاقی که بعید میدانستم، افتاد. این را حذف نمیکنم و پشتش قایم نمیشوم؛ درسش مهمتر از آبروی پیشبینی است: تلگرام سالهاست به سمت پلتفرمشدن حرکت میکند (Mini Appها، Stars، و حالا Serverless) و ظاهراً هر جایی که توسعهدهندهها اصطکاک دارند، بالقوه محصول بعدی تلگرام است.
با این دیدگاه اصلاحشده، روندهایی که به نظر میرسد ادامه پیدا کنند:
تکمیل تدریجی پلتفرم رسمی: باز شدن لیست انتظار و دسترسی عمومی، اعلام قیمتگذاری و سهمیهها، و احتمالاً وظایف زمانبندیشده. پشتیبانی از فایل، که در نسخهی اول این مقاله هنوز موجود نبود، حالا اضافه شده است.
رقابت جدیتر بر سر تجربهی توسعه: حالا که تلگرام سادهترین مسیر ممکن را تعریف کرده (بدون webhook، بدون توکن، بدون دیتابیس جدا)، پلتفرمهای شخصثالث و فریمورکهای بات برای سادهسازی تحت فشار بیشتری هستند.
ادغام عمیقتر با هوش مصنوعی: هم در لایهی ساخت (AGENTS.md و ابزارهای AI-friendly که تلگرام از روز اول در پروژهها گذاشته) و هم در لایهی محصول (باتهای LLM-محور با تاریخچه در SQLite).
بلوغ پایگاهدادههای edge-native: Cloudflare D1، Turso و راهحلهای مشابه پختهتر میشوند و محدودیتهای SQLite توزیعشده کمتر.
پرسشهای متداول
آیا تلگرام یک پلتفرم سرورلس رسمی برای باتها دارد؟
بله. این تغییر مهم نسبت به گذشته است. تلگرام مستندات رسمی Telegram Serverless را در core.telegram.org منتشر کرده: اجرای کد بات در V8 sandbox روی زیرساخت خود تلگرام، با پایگاهدادهی SQLite داخلی و CLI رسمی به نام tgcloud. منوی Serverless حالا در BotFather هست، اما در بررسی ما (مهر ۱۴۰۵) فعالسازی با ثبت درخواست در لیست انتظار انجام میشود.
چرا نمیتوانم Serverless را در BotFather فعال کنم؟
در تست تیر ۱۴۰۵ منو اصلاً ظاهر نمیشد. در بررسی مجدد ما در مهر ۱۴۰۵ منو هست، اما فعالسازی با ثبت درخواست در لیست انتظار انجام میشود و مستندات رسمی زمانی برای تأیید اعلام نکردهاند. توکن CLI فقط بعد از فعال شدن Serverless از همین منو قابل دریافت است؛ تا آن موقع میتوانید کدتان را آماده کنید یا از الگوی شخصثالث استفاده کنید.
تفاوت CLI Access Token با توکن معمولی بات چیست؟
توکن Bot API (قالب 123456:AA...) برای فراخوانی متدهای بات است؛ CLI Access Token (قالب app<id>:<secret>) فقط برای اتصال tgcloud به پروژهی کلود شماست و از مسیر BotFather → Serverless → CLI Access گرفته میشود. این دو قابل تعویض نیستند.
آیا در Telegram Serverless میتوان از پکیجهای npm استفاده کرد؟
خیر. در زمان اجرا فقط SDK پلتفرم (sdk و زیرماژولهایش) و ماژولهای خود پروژه قابل import هستند. هر منطق دیگری را باید خودتان در lib/ بنویسید.
پایگاهدادهی Telegram Serverless چیست؟
هر بات یک پایگاهدادهی اختصاصی مبتنی بر SQLite دارد که بین اجراها باقی میماند. اسکیمای آن در schema.js با DSLای شبیه Drizzle تعریف میشود و تغییرات با tgcloud migrate (جدا از دیپلوی کد) اعمال میشوند. نکتهی مهم: foreign key عمداً پشتیبانی نمیشود.
آیا بات سرورلس رایگان است؟
Bot API تلگرام رایگان است. قیمتگذاری پلتفرم رسمی Serverless هنوز اعلام نشده. در الگوی شخصثالث، هزینه به مصرف شما بستگی دارد و اکثر باتهای کوچک تا متوسط در سطح رایگان Cloudflare Workers یا Vercel جا میشوند.
بهترین پلتفرم سرورلس برای بات تلگرام کدام است؟
اگر به پلتفرم رسمی دسترسی دارید و بات شما خالص تلگرامی و جاوااسکریپتی است، سادهترین مسیر همان است. در غیر این صورت Cloudflare Workers بهخاطر cold start بسیار کم و D1 برای اکثر باتها انتخاب اول است؛ اگر پروژه از قبل روی AWS یا Vercel است، همان اکوسیستم منطقیتر است.
تفاوت webhook و polling در بات تلگرام چیست؟
در polling، بات مدام از سرورهای تلگرام میپرسد پیام جدیدی هست، که نیاز به یک فرآیند همیشهروشن دارد. در webhook، تلگرام خودش هنگام دریافت پیام جدید، درخواست را مستقیماً به آدرس شما ارسال میکند. در پلتفرم رسمی حتی webhook هم خودکار مدیریت میشود و لازم نیست خودتان تنظیمش کنید.
آیا میتوان یک بات موجود روی VPS را به سرورلس مهاجرت داد؟
بله، اما ابتدا بررسی کنید که آیا بات به فرآیندهای پسزمینهی طولانی یا پایگاهدادهی رابطهای پیچیده وابسته است یا نه. برای پلتفرم رسمی، محدودیتهای اضافه (فقط JS، بدون npm، بدون foreign key) را هم در نظر بگیرید.
آیا زبان برنامهنویسی محدود به جاوااسکریپت است؟
در پلتفرم رسمی تلگرام: بله، فقط جاوااسکریپت. در الگوی شخصثالث: خیر. AWS Lambda از Python، Go، داتنت و زبانهای دیگر هم پشتیبانی میکند و Cloudflare Workers علاوه بر JS/TS از WASM.
جمعبندی
داستان این مقاله خودش خلاصهی خوبی از این اکوسیستم است: زمانی که نسخهی اولش را نوشتم، «بات سرورلس تلگرام» یک الگوی جامعهمحور بود و تلگرام هیچ محصول رسمیای نداشت، و مقاله همین را شفاف گفته بود. حالا تلگرام با Telegram Serverless دقیقاً همین را به محصول رسمی تبدیل کرده: کد شما در V8 sandbox کنار Bot API، دیتابیس SQLite داخلی، دیپلوی با یک دستور، و مدیریت حتی از داخل BotFather.
وضعیت عملی امروز (مهر ۱۴۰۵) این است: مستندات و CLI عمومیاند و منوی Serverless در BotFather هست، اما فعالسازی با لیست انتظار است. تا وقتی نوبت شما برسد، الگوی شخصثالث (بهخصوص Cloudflare Workers + D1) همچنان یک مسیر بالغ، ارزان و آمادهی پروداکشن است، و همهچیز آن در همین مقاله هست.
توصیهی نهایی من: برای بات جدید بعدیتان، اول در BotFather درخواست Serverless را ثبت کنید. وقتی فعال شد، پلتفرم رسمی را امتحان کنید: مسیر push/migrate و دیتابیس داخلی، سادهترین تجربهی ساخت بات تلگرام تا امروز است. تا آن موقع، با Workers شروع کنید و کدتان را طوری لایهبندی کنید که مهاجرت بعدی ارزان باشد. در هر دو حالت، برای یک بات ساده و واکنشی اجارهی VPS دیگر انتخاب پیشفرض نیست؛ VPS هنوز برای Cron، کارهای طولانی و کنترل کامل جای خودش را دارد.
این مطلب برایتان مفید بود؟
شمارش آرا پس از ۵ رأی نمایش داده میشود.
مقالات مرتبط
راهنمای کامل اینماد: شرایط، مدارک، مراحل دریافت و تمدید
اینماد چیست، چرا شرط دریافت درگاه پرداخت بانکی است، چه مدارکی لازم دارد و مرحلهبهمرحله چطور گرفته، تمدید و استعلام میشود؟ شامل دلایل رد درخواست و نسخه بدون ستاره.
مطالعه مقالهمال تو: اپ مدیریت زندگی که برای تقویم ایرانی ساخته شده
مالی، کارها، عادتها و تقویم در یکجا: جایی که ماه شمسی واقعاً مرز بودجه است، پول به تومان و بدون اعشار حساب میشود و هفته از شنبه شروع میشود. چه میکند و چطور شروع کنید.
مطالعه مقالهGEO چیست؟ چه فرقی با سئوی سنتی دارد؟
GEO یعنی چه، چه فرقی با سئوی سنتی دارد، و چرا نمیشود صرفاً یک نسخهی جدید از همان کار قدیمی حساب کرد.
مطالعه مقاله