aiogram bot hosting, without a server to keep alive
aiogram 3 is asyncio through and through, which is exactly what a long-running process wants. Push the repository, set BOT_TOKEN, deploy. The bot polls Telegram, restarts if it ever exits, and redeploys on every commit.
A minimal aiogram 3 bot that deploys as is
import asyncio, os
from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
bot = Bot(os.environ["BOT_TOKEN"])
dp = Dispatcher()
@dp.message(CommandStart())
async def start(message: Message):
await message.answer("Hello from FadeHost")
async def main():
await dp.start_polling(bot)
asyncio.run(main())Save it as bot.py, add aiogram to requirements.txt, push. The panel detects Python, installs the requirements and runs python bot.py.
FSM state, storage and databases
aiogram's MemoryStorage forgets everything on restart, which is fine for a menu bot. For state that must survive a redeploy, point RedisStorage at a managed Redis (one click, private network) or keep a SQLite file under /data, which persists across deploys.
Webhooks with aiogram
aiogram ships an aiohttp webhook runner. It needs the app's https address, so use it on a paid app whose address stays up, listen on 0.0.0.0 and the PORT the panel sets, and set the webhook to https://name.fadehost.app/webhook. On the free tier, keep polling.
Frequently asked questions
Which aiogram version?
aiogram 3 is what current tutorials use and what the snippet above targets. aiogram 2 still runs; pin it in requirements.txt and keep its executor-based start.
Polling or webhook?
Polling works everywhere and needs nothing but the token: the bot asks Telegram for updates. A webhook needs a public https address; every hosted app has one at name.fadehost.app with its plan, but on the free tier that address sleeps when idle, so polling is the simpler choice for a free bot and a webhook is for a paid app that stays up.
Where does the token go?
In the environment variables of the app, as BOT_TOKEN or whatever name your code reads, never in the repository. The panel masks the values and injects them when the bot starts.
Why does my bot exit right after starting?
Almost always an unhandled exception at startup: a missing BOT_TOKEN, a wrong library version, or a module not in requirements.txt. The console shows the traceback and the crash doctor names the cause.
What does the free tier include?
One bot with 256 MB of RAM, always on, placed where there is room for it (a paid plan picks the region), with the live console, environment variables and redeploys on push. A second bot or more memory is the Starter plan at $2 a month.