A tutorial for running two or more python bots on Railway inside one container and one service, with independent crash recovery for each.
Deploying Multiple Python Bots to a Single Railway Container
If you're running more than one Python bot — say, a Telegram ingestion bot and a Discord notification bot that share a database — deploying each as its own Railway service means double the hosting cost and double the configuration for something that's logically one unit. This tutorial covers deploying both bots inside a single Railway container, with each one still getting fully independent crash recovery.
Table of Contents
- Why Two Services Is Usually Overkill
- The Naive Fix and Why It Falls Short
- Step 1: Install StayPresent
- Step 2: Structure Your Project
- Step 3: Configure Multiple Bots in One Entry Point
- Step 4: Read Railway's Assigned Port
- Step 5: Deploy as a Single Railway Service
- Verifying Both Bots Are Running
- FAQs
- Conclusion
Why Two Services Is Usually Overkill
Railway (like most PaaS platforms) charges per service, and each service needs its own configuration, environment variables, and deployment pipeline. If two bots are closely related — sharing a database, a queue, or just conceptually belonging to the same project — running them as two separate Railway services duplicates all of that for no real benefit.
The Naive Fix and Why It Falls Short
A common first instinct is a shell script:
python telegram_bot.py & python discord_bot.py & wait
This runs both, but there's no real process supervision here — if telegram_bot.py crashes, nothing restarts it, and you still haven't solved Railway's HTTP port requirement, since neither script opens one.
Step 1: Install StayPresent
pip install staypresent[prod]
# requirements.txt
staypresent[prod]
Step 2: Structure Your Project
project/
├── main.py
├── telegram_bot.py
├── discord_bot.py
├── requirements.txt
Both bot scripts stay exactly as they are — nothing about their internal logic needs to change.
Step 3: Configure Multiple Bots in One Entry Point
main.py:
import os
import staypresent
staypresent.web.json({"status": "running", "bots": 2})
staypresent.run(
bots=[
{"file": "telegram_bot.py"},
{"file": "discord_bot.py"},
],
)
Each bot listed here is launched as its own subprocess, monitored independently — if telegram_bot.py crashes and restarts, discord_bot.py is completely unaffected and keeps running.
If each bot needs different environment variables:
staypresent.run(
bots=[
{"file": "telegram_bot.py", "env": {"ROLE": "ingestion"}},
{"file": "discord_bot.py", "env": {"ROLE": "notifications"}},
],
)
Step 4: Read Railway's Assigned Port
import os
import staypresent
staypresent.web.json({"status": "running", "bots": 2})
staypresent.run(
bots=[
{"file": "telegram_bot.py"},
{"file": "discord_bot.py"},
],
port=int(os.getenv("PORT", 8080)),
)
Step 5: Deploy as a Single Railway Service
Set your Railway start command to:
python main.py
Deploy once. Both bots now run inside the same container, under one Railway service, with one hosting bill.
Verifying Both Bots Are Running
If you're on a recent StayPresent version, visit /status on your deployed URL — each bot appears as its own row, with its own uptime and restart count, so you can confirm both are actually healthy at a glance rather than guessing from Railway's own single-service view.
You can also give each bot its own lightweight endpoint for a quick manual check:
staypresent.web.json({"status": "online"}, path="/telegram")
staypresent.web.json({"status": "online"}, path="/discord")
FAQs
Does one bot crashing affect the other?
No — each bot in the bots list gets its own restart counter and its own monitoring thread, completely independent of the others.
Can I run more than two bots this way?
Yes — bots accepts as many entries as you need, each independently supervised.
Does this work the same way on Render or Koyeb?
Yes — the same main.py and multi-bot configuration work unchanged across any platform that follows the standard $PORT convention.
Conclusion
Running multiple related Python bots on Railway doesn't require multiple services. staypresent.run(bots=[...]) supervises each one independently — separate crash recovery, separate restart counters — while sharing a single container, a single port, and a single deployment.
pip install staypresent[prod]
Top comments (0)