DEV Community

John Wick
John Wick

Posted on

How to Run a Python Bot on Fly.io Without It Sleeping

A tutorial for deploying a python bot on Fly.io with proper health checks and no unwanted machine suspension, using StayPresent.

How to Run a Python Bot on Fly.io Without It Sleeping

Fly.io deploys apps as lightweight VMs ("Machines") close to your users, and its free allowance is a popular choice for small bots. It also has a specific behavior worth understanding before you deploy: Fly can automatically stop machines when they're idle, and restart them on the next incoming request — great for a web app, potentially disruptive for a bot that needs to stay connected continuously. This tutorial covers deploying a Python bot on Fly.io correctly, avoiding both the standard HTTP-port issue and Fly's specific auto-stop behavior.

Table of Contents

  1. How Fly.io's Health Checks Work
  2. Fly's Auto-Stop/Auto-Start Behavior
  3. Step 1: Install StayPresent
  4. Step 2: Wrap Your Bot's Entry Point
  5. Step 3: Configure fly.toml
  6. Step 4: Disable Auto-Stop for a Bot Machine
  7. Step 5: Deploy
  8. Verifying It's Actually Staying Up
  9. FAQs
  10. Conclusion

How Fly.io's Health Checks Work

Like most modern platforms, Fly can be configured to check your service over HTTP and restart it if it stops responding. A Discord or Telegram bot doesn't open an HTTP port on its own, so without something bridging that gap, a configured health check has nothing to actually verify.

Fly's Auto-Stop/Auto-Start Behavior

This is the part that's specific to Fly and worth calling out: Fly Machines can be configured to automatically stop when idle and start again on the next request — a cost-saving feature that makes sense for a typical web app, but works against a bot that's supposed to maintain a continuous connection to Discord or Telegram in the background, with no incoming HTTP requests driving that connection at all.

Step 1: Install StayPresent

pip install staypresent[prod]
Enter fullscreen mode Exit fullscreen mode
# requirements.txt
staypresent[prod]
Enter fullscreen mode Exit fullscreen mode

Step 2: Wrap Your Bot's Entry Point

Your bot logic in bot.py stays unchanged:

# 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

Step 3: Configure fly.toml

app = "my-bot"

[env]
  PORT = "8080"

[[services]]
  internal_port = 8080
  protocol = "tcp"

  [[services.ports]]
    port = 80
    handlers = ["http"]

  [[services.tcp_checks]]
    interval = "15s"
    timeout = "2s"
Enter fullscreen mode Exit fullscreen mode

This gives Fly the HTTP surface it's looking for to consider your machine healthy.

Step 4: Disable Auto-Stop for a Bot Machine

This is the step specific to Fly that's easy to miss. In fly.toml, make sure auto-stop isn't configured against your bot service — a bot needs to stay running continuously, not spin down between requests the way a typical stateless web app would:

[[services]]
  internal_port = 8080
  protocol = "tcp"
  auto_stop_machines = false
  auto_start_machines = false
  min_machines_running = 1
Enter fullscreen mode Exit fullscreen mode

min_machines_running = 1 specifically ensures Fly always keeps at least one instance of your bot running, rather than scaling it down to zero during a quiet period.

Step 5: Deploy

fly deploy
Enter fullscreen mode Exit fullscreen mode

Verifying It's Actually Staying Up

Check fly status to confirm your machine is showing as started consistently, not cycling between stopped and started. You can also hit /health directly via your app's Fly URL to confirm StayPresent's HTTP server is responding. On a recent StayPresent version, /status gives you an ongoing uptime view, which is the clearest way to confirm the bot is staying connected over time rather than restarting repeatedly.

FAQs

Do I need staypresent.cron() on Fly.io too?
Generally no, if auto_stop_machines = false and min_machines_running = 1 are set correctly — those settings are what actually control Fly's idle behavior, unlike platforms where self-pinging is the main lever.

Does this work the same for a Telegram bot as a Discord bot?
Yes — the fix addresses the HTTP port and auto-stop behavior generically, regardless of which bot library or platform API your bot talks to.

Will min_machines_running = 1 cost more than the free tier allows?
Fly's specific pricing and free allowances change over time — check Fly's current pricing page for your usage before assuming either way.

Conclusion

Running a Python bot reliably on Fly.io means solving two separate things: giving Fly's health check an HTTP port to verify (via staypresent.run()), and explicitly disabling Fly's auto-stop behavior so your bot isn't treated like a scale-to-zero web app. Both together keep your bot connected and online continuously, the way a bot actually needs to run.

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

Top comments (0)