A step-by-step tutorial to deploy a Telegram bot on Koyeb with proper health checks and zero idle downtime, using StayPresent.
Deploy a Telegram Bot on Koyeb Without It Going Idle
Koyeb is a solid choice for hosting a Telegram bot — fast deploys, a generous free tier, support for both Git-based and Docker-based builds. But like most PaaS platforms, it expects your service to respond over HTTP, and a Pyrogram or python-telegram-bot script doesn't do that on its own. This tutorial walks through deploying a Telegram bot on Koyeb the right way, so it stays healthy and online instead of idling out.
Table of Contents
- Why Telegram Bots Go Idle on Koyeb
- Step 1: Install StayPresent
- Step 2: Wrap Your Bot's Entry Point
- Step 3: Read Koyeb's Assigned Port
- Step 4: Choose Your Deploy Path (Git or Docker)
- Step 5: Set Koyeb's Health Check Path
- Step 6 (Optional): Prevent Scale-to-Zero Idle
- Verifying the Deployment
- FAQs
- Conclusion
Why Telegram Bots Go Idle on Koyeb
A Telegram bot polls or listens for updates from Telegram's own servers — it's an outbound connection, not an inbound one. Koyeb's health checks expect the opposite: something listening on a port it can reach. Without that, Koyeb has no way to distinguish "this bot is working perfectly" from "this bot is broken," and treats the deployment as unhealthy.
Step 1: Install StayPresent
pip install staypresent[prod]
# requirements.txt
staypresent[prod]
pyrogram
Step 2: Wrap Your Bot's Entry Point
Keep your bot's actual logic in bot.py, untouched. Create main.py:
import staypresent
staypresent.web.json({"status": "running"})
staypresent.run("bot.py")
Step 3: Read Koyeb's Assigned Port
import os
import staypresent
staypresent.web.json({"status": "running"})
staypresent.run(
"bot.py",
port=int(os.getenv("PORT", 8080)),
)
Step 4: Choose Your Deploy Path (Git or Docker)
Git-based (buildpack): Koyeb detects requirements.txt and builds automatically. Set the run command to:
python main.py
Docker-based (useful if your bot needs system packages like ffmpeg):
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
main.py is identical either way — only the deployment mechanism changes.
Step 5: Set Koyeb's Health Check Path
In Koyeb's service settings, point the health check explicitly at /health rather than the default:
staypresent.web.json({"status": "running", "version": "1.0"})
# /health still returns {"status": "ok"} independently of the above
This keeps platform health checks stable even if you later change what / serves.
Step 6 (Optional): Prevent Scale-to-Zero Idle
If your specific Koyeb service type is subject to scale-to-zero behavior you want to avoid, add a self-ping against your own public URL:
staypresent.cron("https://your-app.koyeb.app", interval=240)
Verifying the Deployment
Deploy, then check Koyeb's dashboard — the service should report healthy rather than cycling through restarts. Visit https://your-app.koyeb.app/health directly to confirm it returns {"status": "ok"}. On a recent StayPresent version, /status also gives you a live dashboard showing uptime over time, which is the easiest way to confirm the fix is holding rather than just working once.
FAQs
Does this work with python-telegram-bot instead of Pyrogram?
Yes — the fix is entirely about the entry point, not which Telegram library your bot uses internally.
Do I need Docker for a simple bot?
No — Git-based buildpack deploys handle standard Python dependencies fine; Docker is only needed for extra system-level packages.
Can I reuse this main.py if I later move to Render or Railway?
Yes — as long as PORT is read from the environment, the same file works unchanged across platforms following the same convention.
Conclusion
A Telegram bot going idle on Koyeb almost always comes down to a missing HTTP port, not a problem with the bot's own polling logic. Wrapping your existing bot in staypresent.run(), reading PORT dynamically, and pointing Koyeb's health check at /health solves it completely — Git-based or Docker-based, with no changes to your bot's actual code.
pip install staypresent[prod]
Top comments (0)