The Complete Guide to Keeping Python Bots Alive Using StayPresent
If you've ever deployed a Telegram bot, Discord bot, or background worker on a free hosting tier, you've probably watched it die a slow, quiet death a few minutes after your last request. One moment it's responding instantly, the next it's completely unresponsive until someone happens to poke it again. This is the single most common problem developers run into when they try to keep a python bot alive on modern cloud platforms, and it has a well-understood cause and a genuinely simple fix.
This guide walks through why it happens, and how a small package called StayPresent solves it with one line of code.
Table of Contents
- Why Python Bots Stop Running
- How Free Hosting Platforms Actually Work
- What a "Keep-Alive Server" Really Is
- Introducing StayPresent
- Installing StayPresent
- Your First Keep-Alive Bot
- The Built-In Health Endpoint
- Deploying to Render
- Best Practices
- Common Mistakes
- FAQs
- Conclusion
Why Python Bots Stop Running
Most Python bots — Telegram bots built with Pyrogram or python-telegram-bot, Discord bots built with discord.py, scrapers, automation scripts — are designed to run forever in a loop. They don't naturally open an HTTP port; they just sit there, listening for events or polling an API.
The problem is that most free-tier hosting providers were never built for that kind of workload. They were built to serve web traffic. So they monitor for one specific signal: is something listening on an HTTP port? If nothing answers on that port for a while, the platform assumes your service is idle, and it either spins the container down or marks it unhealthy and restarts it — often destroying whatever in-memory state your bot was holding onto.
How Free Hosting Platforms Actually Work
Platforms like Render, Railway, Koyeb, and similar services generally fall into two buckets:
-
Web services, which expect an HTTP server bound to a
PORTenvironment variable, and which the platform actively health-checks. - Background workers, which don't need a port, but often come with stricter limits or aren't available at all on the free tier.
If you deploy a bot as a web service without an HTTP server, the platform will typically flag it as unhealthy because nothing responds on the expected port. This is the root cause behind most "my bot randomly stops working" reports you'll find in developer communities.
What a "Keep-Alive Server" Really Is
The fix is conceptually simple: run a tiny HTTP server alongside your bot, purely so the hosting platform has something to talk to. The server doesn't need to do anything meaningful — it just needs to exist and respond to requests.
Developers have hacked this together for years with a few lines of raw Flask, spun up in a background thread next to their bot's main loop. It works, but it means every bot ends up with its own copy of the same boilerplate: server setup, threading, process management, and eventually crash recovery once the bot starts failing in production.
That repeated boilerplate is exactly what StayPresent replaces.
Introducing StayPresent
StayPresent is a lightweight Python package that runs a Flask-powered HTTP server next to your bot script, with optional production-grade serving through Waitress. Instead of writing your own threading and process-management code, you call one function and StayPresent handles the rest — starting the server, running your bot script as a subprocess, and restarting it automatically if it crashes.
It's built specifically for platforms that require an active HTTP port, including Render, Railway, Koyeb, and Heroku, and it works just as well inside Docker or on a plain VPS.
Installing StayPresent
Standard installation:
pip install staypresent
For production deployments, install the prod extra, which pulls in Waitress and suppresses Flask's development-server warning:
pip install staypresent[prod]
Your First Keep-Alive Bot
Here's the entire setup needed to keep a bot alive:
import staypresent
staypresent.web.json({
"status": "running"
})
staypresent.run("bot.py")
That's it. staypresent.run() starts the HTTP server and launches bot.py as a subprocess at the same time. If you don't configure a response at all, StayPresent defaults to returning {"message": "I'm Present"} on the root route, so even the laziest possible setup still gives the platform something to check.
You can also serve plain text:
staypresent.web.text("Service Operational")
Or a full HTML page, read fresh from disk on every request, along with any CSS/JS/images sitting next to it:
staypresent.web.html("templates/index.html")
The Built-In Health Endpoint
StayPresent automatically exposes a dedicated /health route that always returns {"status": "ok"}. This is separate from whatever you've configured at /, so you can use / for a human-facing status page and /health specifically for platform health checks and uptime monitors.
Deploying to Render
Render assigns the port to listen on through the PORT environment variable, so your entry point should read it dynamically:
import os
import staypresent
staypresent.run(
"bot.py",
port=int(os.getenv("PORT", 8080))
)
Your start command is simply:
python main.py
Railway follows the exact same pattern since it also injects $PORT automatically.
Best Practices
-
Always bind to
0.0.0.0, not127.0.0.1, so the platform's health checker can actually reach the server. This is StayPresent's default. - Read the port from the environment on any platform that assigns one dynamically.
-
Keep
restart_on_crashenabled (it's on by default) so a bad exception in your bot doesn't take the whole service down permanently. -
Isolate your logging — StayPresent logs under its own
"staypresent"logger and never touches your root logger, so you can freely raise or lower its verbosity without affecting your bot's own logs.
Common Mistakes
-
Passing a bare string to
bot_argsinstead of a list.bot_args="--verbose"will not behave the way you expect — pass["--verbose"]. - Assuming a keep-alive server prevents platform shutdowns. It only stops the platform from marking your service idle. It won't override hard usage limits, account suspensions, or free-tier quotas.
-
Forgetting the health endpoint exists. Some platforms let you point their health check specifically at
/healthinstead of/, which is worth doing if your root route serves a dashboard.
FAQs
Does StayPresent replace Flask?
No — it wraps Flask (and optionally Waitress) to handle the hosting boilerplate for you.
Does it host my application?
No. It runs inside whatever hosting environment you've already chosen; you still need to deploy to Render, Railway, a VPS, or similar.
Does it keep my app alive forever?
No single tool can guarantee that. StayPresent solves the HTTP-port problem and can optionally self-ping to avoid inactivity sleep, but it can't override hard platform limits.
Conclusion
Keeping a Python bot alive on modern cloud platforms almost always comes down to one thing: giving the platform an HTTP port to check. StayPresent turns that requirement from a recurring chore into a single line of code, while also handling crash recovery and production-grade serving along the way.
If you're tired of rewriting the same Flask keep-alive snippet for every new bot, install StayPresent and get back to building the bot itself.
pip install staypresent[prod]
Top comments (0)