DEV Community

John Wick
John Wick

Posted on

Run Python Bots Without Sleep On Koyeb With StayPresent

Deploy a koyeb python bot with proper health checks, port binding, and crash recovery using StayPresent — Git and Docker deploy paths covered.

Run Python Bots Without Sleep On Koyeb With StayPresent

Koyeb supports deploying straight from a Git repository or from a Dockerfile, and like most serverless-leaning PaaS platforms, it evaluates your service's health through HTTP checks against a port it expects your app to bind. A koyeb python bot — a Discord bot, Telegram bot, or background worker — needs that same small HTTP layer every other platform in this series requires, and StayPresent provides it with the same one-line setup regardless of which Koyeb deploy path you use.

Table of Contents

  1. Two Ways to Deploy on Koyeb
  2. The Port Binding Requirement
  3. Setting Up StayPresent
  4. Configuring Koyeb's Health Check Path
  5. Self-Ping Considerations
  6. Crash Recovery
  7. Full Working Example (Git-Based)
  8. Full Working Example (Docker-Based)
  9. Best Practices
  10. Common Mistakes
  11. FAQs
  12. Conclusion

Two Ways to Deploy on Koyeb

Koyeb supports two primary deployment paths for a Python service: a Git-based buildpack deploy, where Koyeb detects and builds your app automatically from requirements.txt, and a Dockerfile-based deploy, where you provide the full container definition yourself. Both ultimately run the same command you specify and expect the same thing from it: a bound HTTP port.

The Port Binding Requirement

Koyeb injects a PORT environment variable, exactly like Render, Railway, and Heroku:

import os
import staypresent

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
)
Enter fullscreen mode Exit fullscreen mode

Without something bound to that port, Koyeb's health checks will report the service as unhealthy — independent of whether your bot itself is running perfectly fine internally.

Setting Up StayPresent

For a Git-based deploy, add the production extra to requirements.txt:

staypresent[prod]
Enter fullscreen mode Exit fullscreen mode

And set your main.py:

import os
import staypresent

staypresent.web.json({"status": "running"})

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
)
Enter fullscreen mode Exit fullscreen mode

Koyeb's run command:

python main.py
Enter fullscreen mode Exit fullscreen mode

Configuring Koyeb's Health Check Path

By default, a platform's health check often targets /. StayPresent's built-in /health endpoint — which always returns {"status": "ok"} regardless of what's configured at your root route — is generally the better target, since it stays stable even if you later change what / serves:

staypresent.web.json({"status": "running", "version": "1.0"})
# /health remains {"status": "ok"} independently
Enter fullscreen mode Exit fullscreen mode

In Koyeb's service settings, set the health check path explicitly to /health rather than relying on the default.

Self-Ping Considerations

Koyeb's specific behavior around scaling-to-zero or idle handling depends on the service type and plan you've configured — check Koyeb's current documentation for your particular setup rather than assuming. If your deployment is subject to any form of inactivity-based scaling you want to avoid, staypresent.cron() can generate outbound traffic against your own public URL:

staypresent.cron("https://my-app.koyeb.app", interval=240)
Enter fullscreen mode Exit fullscreen mode

Crash Recovery

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
    restart_on_crash=True,
    max_restarts=5,
    restart_delay=2.0,
)
Enter fullscreen mode Exit fullscreen mode

If restarts are ultimately exhausted, StayPresent exits the process with the bot's original exit code, letting Koyeb's own deployment-level restart behavior serve as a final backstop.

Full Working Example (Git-Based)

import os
import staypresent

staypresent.web.json({"status": "running"})

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
    restart_on_crash=True,
    max_restarts=5,
)
Enter fullscreen mode Exit fullscreen mode
# requirements.txt
staypresent[prod]
python-telegram-bot
Enter fullscreen mode Exit fullscreen mode

Full Working Example (Docker-Based)

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
Enter fullscreen mode Exit fullscreen mode

main.py is identical to the Git-based example above — the deploy mechanism changes, the StayPresent configuration doesn't.

Best Practices

  • Set the health check path to /health explicitly in Koyeb's dashboard rather than leaving it on a default that may target /.
  • Use the Docker deploy path if your bot has system-level dependencies (e.g. ffmpeg) that a buildpack deploy won't install automatically.
  • Keep main.py platform-agnostic (reading PORT from the environment, targeting the correct public URL for cron()) so the same file works unchanged if you later move to Render or Railway.

Common Mistakes

  • Leaving the health check path on a default that doesn't match what your root route actually serves, causing false-negative health failures.
  • Assuming a Git-based deploy and a Docker-based deploy require different StayPresent configuration. They don't — only the deployment mechanism around main.py changes.
  • Forgetting ffmpeg, ImageMagick, or other system packages a bot might depend on, which a plain Git buildpack deploy won't install — this calls for the Docker path instead.

FAQs

Does Koyeb require a Dockerfile?
No — Git-based buildpack deploys work for standard Python projects without one; Docker is only needed for more customized environments.

Can I use the exact same main.py across Koyeb, Render, and Railway?
Yes, as long as PORT is read from the environment and any self-ping URL is configured per-platform.

Does /health need to be manually created?
No — it's provisioned automatically by StayPresent unless you explicitly register your own response there.

Conclusion

A koyeb python bot, whether deployed via Git or Docker, needs the same thing every PaaS bot deployment needs: a bound HTTP port and a reliable health check target. StayPresent provides both with an identical, minimal setup regardless of which Koyeb deploy path you choose.

pip install staypresent[prod]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)