How to Keep a Telegram Bot Running Reliably 24/7
Quick Summary
A Telegram bot is expected to be available at all times. Users do not know that the server has run out of memory, a process has crashed, or the database has stopped responding. From their perspective, there is only one metric that matters: the bot either replies or it does not.
Many reliability problems begin with a simple launch command such as:
python bot.py
or
node bot.js
During development, this approach is perfectly reasonable. A few weeks later, the bot starts handling real enquiries, processing payments, communicating with CRM systems, or interacting with AI services. At that point, even a minor outage can result in lost messages, failed transactions, and frustrated users.
Reliable Telegram bot hosting depends on several layers working together. The application process should start automatically after a server reboot and recover from unexpected failures. The database must remain available during periods of increased activity. Task queues should absorb traffic spikes without becoming overloaded. Monitoring systems should detect problems before users begin reporting them.
Support teams regularly encounter situations where the bot itself is functioning correctly, yet the application becomes unavailable because of basic infrastructure issues. A Python process may terminate after a failed update. A disk may fill up with log files. PostgreSQL may stop accepting connections after a memory shortage. The owner starts investigating the Telegram API or application code, while the real problem exists at the server level.
At Era.Host, similar cases are often seen during migrations from test environments to production systems. The application code itself is usually not the issue. More often, the root cause is an infrastructure component that was never designed for continuous operation under real-world conditions.

A properly configured VPS can withstand these situations without losing messages, enquiries, orders, or other important data. For that reason, the long-term stability of a Telegram bot depends not only on code quality, but also on how the surrounding infrastructure is designed, monitored, and maintained.
Article plan
- Why Running a Bot Manually Leads to Downtime
- How to Configure Automatic Startup for a Telegram Bot with systemd
- How to Configure Automatic Restarts with PM2
- How to Monitor Memory Usage in a Telegram Bot
- How to Avoid Losing Messages When a Bot Crashes
- Handling Traffic Spikes Without Taking Your Telegram Bot Offline
- How to Monitor the Health of a Telegram Bot
- How to Receive Telegram Alerts When Something Goes Wrong
- How to Organise Reliable Backups for a Telegram Bot
- Common Mistakes That Prevent a Telegram Bot from Running Reliably 24/7
Why Running a Bot Manually Leads to Downtime
Most Telegram bots start out the same way. A developer connects to the server via SSH and launches the application with a command such as:
python bot.py
or
node bot.js
For testing purposes, this is perfectly adequate. The bot starts, receives messages, and appears to work without any issues.
The problems begin later, once real users start relying on it.
Support teams regularly see the same pattern. A bot runs without incident for weeks or even months, then suddenly stops responding. The owner checks Telegram, reviews the Webhook configuration, attempts to restart the application, and only then discovers that the process terminated long ago.
The cause can be almost anything. The SSH session used to start the bot may have been closed. The server may have rebooted after a system update. The application may have crashed because of an unhandled exception. The operating system may have terminated the process after running out of memory. A dependency update may have failed and left the application unable to start.
The issue is not the failure itself. Every application encounters failures sooner or later. The real problem arises when there is no mechanism in place to bring the process back online automatically.
Consider a simple example. A bot collects enquiries from a website and forwards them to a sales team. Overnight, a VPS reboot occurs after routine maintenance. The operating system starts normally, the database is running, and network connectivity is available. The bot, however, never starts because it was launched manually through SSH several days earlier.
At 9 a.m., users begin sending messages. Telegram continues delivering requests as expected. No responses are returned. Complaints start arriving, and only then does the owner realise that the bot has been offline for hours.
Support engineers also encounter a different version of the same problem. A bot operates flawlessly for several weeks before a single coding error causes the Python or Node.js process to terminate. The server itself remains fully operational, so everything appears healthy from an infrastructure perspective. In reality, Telegram begins receiving delivery failures while new enquiries and requests go unprocessed.
This is why launching a production bot with python bot.py or node bot.js should be considered a development-only approach. A production Telegram bot must restart automatically after a server reboot, be supervised continuously, and recover from failures without requiring manual intervention.
Once a bot has been deployed to a VPS, the next step should be configuring a process management system such as systemd, PM2, or another service supervisor capable of automatic monitoring and recovery.
How to Configure Automatic Startup for a Telegram Bot with systemd
For Python-based Telegram bots running on a VPS, systemd is usually the preferred solution. It is the standard service manager on most modern Linux distributions and can start applications automatically, bring them back online after a server reboot, and restart them if the process crashes unexpectedly.
Assume the bot is installed in /opt/bot, the main application file is bot.py, and a dedicated user called botuser has been created to run the service.
Create a service file:
sudo nano /etc/systemd/system/telegram-bot.service
A basic configuration might look like this:
[Unit]
Description=Telegram Bot
After=network.target
[Service]
User=botuser
WorkingDirectory=/opt/bot
ExecStart=/usr/bin/python3 /opt/bot/bot.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
In this example, User=botuser defines which Linux user will run the bot. WorkingDirectory=/opt/bot sets the application's working directory. ExecStart contains the startup command.
The Restart=always option tells systemd to restart the process whenever it exits unexpectedly. RestartSec=5 introduces a five-second delay before restarting, preventing the service from entering an endless loop of immediate restarts if there is a coding error or configuration problem.
After creating the service file, reload the systemd configuration and enable the service:
sudo systemctl daemon-reload
sudo systemctl enable telegram-bot
sudo systemctl start telegram-bot
You can verify the service status with:
sudo systemctl status telegram-bot
If everything starts correctly, the output will include:
active (running)
If the service exits immediately, the first things to check are the Python path, the location of bot.py, the permissions assigned to botuser, and any required environment variables.
Logs are usually easiest to review through journalctl:
sudo journalctl -u telegram-bot -f
Support engineers regularly encounter the same configuration mistake. A service file is created correctly, but it points to the system Python interpreter instead of the project's virtual environment. The bot runs perfectly when started manually, yet fails under systemd because required packages cannot be imported.
When a virtual environment is being used, it is generally better to specify its Python interpreter directly:
ExecStart=/opt/bot/venv/bin/python /opt/bot/bot.py
Once configured properly, the bot no longer depends on an active SSH session. The server can reboot after maintenance, the process can crash unexpectedly, or the application can temporarily fail because of a software issue, and systemd will attempt to restore service automatically.
For a production Telegram bot, this level of process management is not an optional enhancement. It is a basic requirement for reliable 24/7 operation. Without it, maintaining uptime quickly becomes a manual task that depends on someone noticing failures and restarting the application by hand.
How to Configure Automatic Restarts with PM2
For Node.js projects, PM2 remains one of the most widely used process managers. Many Telegram bots written in JavaScript or TypeScript rely on it for day-to-day operation. PM2 does far more than simply launch an application. It monitors the process, restarts it automatically after failures, and provides convenient tools for tracking the health of the bot.
Installation usually takes only a few seconds:
npm install pm2 -g
Once installed, the bot can be started with:
pm2 start bot.js --name telegram-bot
The --name parameter assigns a readable name to the process. This becomes particularly useful when a server hosts multiple bots or several Node.js applications.
After starting the bot, it is worth checking the process list:
pm2 list
If everything is working correctly, the bot will appear with an online status.
Many administrators stop here and assume the setup is complete. The problem often becomes visible only after the first server reboot. The VPS restarts normally, but the bot never comes back online because PM2 was not configured to restore processes automatically.
To enable startup after a reboot, run:
pm2 startup
pm2 save
The first command creates a system service that starts PM2 during boot. The second saves the current process list so PM2 knows which applications should be restored automatically.
A quick test is to reboot the VPS and then verify that the bot has returned:
pm2 list
Support teams regularly encounter situations where a bot is launched through PM2 and runs perfectly for weeks or even months. Everything appears stable until the first maintenance reboot. After the server comes back online, the application remains offline because pm2 save was never executed. The infrastructure is healthy, the operating system is running, and the database is available, yet the bot stays down until someone notices and starts it manually.
PM2 also simplifies troubleshooting when a bot becomes unstable. Built-in log viewing allows problems to be identified quickly:
pm2 logs
In many cases the logs immediately reveal the root cause. Database connection failures, API timeouts, memory-related problems, unhandled exceptions, and configuration mistakes are often visible within seconds.
Another useful command is:
pm2 monit
This opens a real-time monitoring dashboard showing CPU usage, memory consumption, restart counts, and other process statistics. If a Telegram bot normally consumes 300–400 MB of RAM but gradually grows to 2 GB over several days, PM2 can help identify the trend before the operating system begins killing processes due to memory exhaustion.
For production Telegram bots, PM2 solves several operational problems at once. It starts the application automatically, keeps it running after crashes, restores processes after server reboots, and provides tools for monitoring and diagnostics. For Node.js-based bots, it remains one of the simplest and most effective ways to achieve reliable 24/7 operation without constant manual supervision.
How to Monitor Memory Usage in a Telegram Bot
Memory exhaustion remains one of the most common causes of unexpected Telegram bot outages. The problem rarely appears immediately after deployment. Much more often, a bot runs without issues for weeks, then gradually starts disappearing offline, responding more slowly, or restarting unexpectedly.
Current memory usage can be checked with:
free -h
or:
htop
Support teams regularly encounter the same pattern. A newly deployed bot consumes around 300–400 MB of RAM. Over the following days or weeks, memory usage slowly increases. Conversation history accumulates, task queues grow, database connections remain open longer, and additional API integrations are introduced. Eventually memory consumption reaches 1–2 GB, often without the owner noticing.
The first signs are usually small message-processing delays. Next, the operating system begins using swap space. As memory pressure increases, Linux starts reclaiming resources for other processes. When available RAM becomes critically low, the Out Of Memory Killer (OOM Killer) may terminate one of the running processes.
From the owner's perspective, the behaviour can be confusing. The server is reachable, no code changes have been deployed, and everything seemed fine moments earlier. Yet the bot suddenly stops responding.
You can check whether the OOM Killer has terminated any processes with:
dmesg | grep -i kill
or:
journalctl -k | grep -i oom
Typical log entries look like:
Out of memory: Killed process 12543 (python3)
or:
OOM Killer terminated process node
Once messages like these appear, investigating Telegram API issues or external services is usually a waste of time. The operating system is explicitly reporting that the application ran out of memory.
If memory exhaustion occurs repeatedly, the goal should not be limited to adding more RAM. The real cause of the growth needs to be identified. Support investigations most commonly reveal one of several scenarios. Task queues are not being cleared after processing. Entire conversation histories are kept in memory. Database queries return unnecessarily large result sets. A third-party dependency contains a memory leak. In other cases, the leak originates in the application's own code.
When memory usage is high, it is also useful to identify the largest consumers:
ps aux --sort=-%mem | head
This command quickly shows which processes are using the most RAM at the time of inspection.
For Node.js applications running under PM2, additional monitoring is available:
pm2 monit
The dashboard displays memory consumption, CPU usage, restart counts, and other runtime metrics. A bot that starts at 400 MB but grows to 2 GB over several days becomes immediately visible through these statistics.
For Telegram bots, a single memory snapshot rarely tells the full story. Trends are far more important. If a bot uses 300–400 MB immediately after startup but steadily climbs to 2 GB within a week despite stable traffic levels, investigation should begin long before the first outage occurs.
This is why memory monitoring should be treated as a permanent part of server operations rather than an occasional troubleshooting task. Most serious incidents do not begin with a coding error. They start with a gradual increase in resource consumption that goes unnoticed until the OOM Killer intervenes and takes the bot offline.
How to Avoid Losing Messages When a Bot Crashes
Message loss often does not happen during a complete server outage. It happens between individual steps inside the application.
The bot receives a user request, starts processing it, completes part of the logic, and then the process exits because of an exception, memory shortage, or failure in an external API. The owner sees that the bot has restarted, but some of the data never reached the database.
One risky pattern looks like this:
process_message()
save_to_db()
At first glance, the logic seems reasonable. The bot processes the message and then saves the result. The problem appears if the process crashes between those two operations. The user has already submitted data and the bot has started working, but no database record has been created. After the application restarts, recovering that message may be difficult, especially if it involved a lead, payment, booking, or important customer request.
A more reliable approach reverses the order:
save_to_db()
process_message()
The incoming event should be recorded in a database or queue first. Processing should happen afterwards. Even if the bot crashes while contacting a CRM platform, payment provider, or AI API, the original message remains stored and can be processed again after recovery.
Production Telegram bots often use a dedicated table for incoming events. This table stores the user ID, message content, event type, timestamp, and processing status. A new message may start with the status new, change to processed after successful handling, or move to failed if an error occurs. In some systems, failed events remain available for retry.
A simplified version of the logic might look like this:
event_id = save_incoming_event(user_id, message_text)
try:
process_event(event_id)
mark_event_as_processed(event_id)
except Exception as error:
mark_event_as_failed(event_id, str(error))
This approach is especially important for bots that handle payments, orders, appointments, bookings, or internal business requests. If a user has paid for a service, selected an appointment slot, or submitted an enquiry, that data should never exist only in the memory of the running process. It must be stored before any complex processing begins.
Support teams regularly encounter situations where the bot appears to work, yet some requests are lost. After investigation, the cause is often simple: the application tried to send data to a CRM or payment system first and only then planned to save the event locally. If the external service returned an error or the connection failed, no local record was created.
Task queues make this design more reliable. The bot quickly stores the incoming event and places a task into a queue. A separate worker then performs heavier operations such as contacting the CRM, sending notifications, processing files, calling an AI API, or generating reports.
Redis, RabbitMQ, or a PostgreSQL-backed queue can all be suitable depending on the project. Redis is commonly used for fast background jobs. RabbitMQ is useful when message routing and delivery rules become more complex. A PostgreSQL queue can be enough when the project already uses PostgreSQL and there is no need to add another service.
The core principle remains the same: important data should not live only in memory until processing is complete. Store the event first, process it afterwards, and mark the result only when the operation succeeds. This design allows the bot to survive process crashes, API timeouts, and temporary service failures without losing messages, enquiries, or orders.
Handling Traffic Spikes Without Taking Your Telegram Bot Offline
Traffic spikes rarely arrive as a gradual increase. More often, they hit all at once. A marketing campaign goes live, a newsletter is sent, the bot is added to a popular channel, a link is published on a website, or a new AI feature attracts attention.
Under normal conditions, the bot may receive a few dozen messages per hour. Then, within minutes, it suddenly receives as many requests as it previously handled in an entire day.
The most fragile architecture is processing every request immediately inside the main bot process.
user ↓ AI API user ↓ AI API user ↓ AI API
When traffic is low, this works perfectly well. A user sends a message, the bot immediately calls an AI API, CRM system, payment gateway, or another external service, and then returns a response.
The problems begin during a surge.
Every user starts triggering resource-intensive operations at the same time. The main bot process spends most of its time waiting for responses from external services. Message processing slows down, response times increase, timeouts appear, and eventually some requests begin to fail.
A more resilient design separates message reception from message processing.
user ↓ queue ↓ worker ↓ processing
In this model, the bot immediately stores the incoming event and places a task into a queue. The user's message is safely recorded even if processing takes several minutes. A separate worker then retrieves tasks from the queue and performs the heavier operations such as AI processing, CRM synchronisation, file handling, report generation, or notification delivery.
Support teams regularly see the difference between these two approaches.
In the first scenario, the entire bot effectively freezes during a traffic spike because the main process becomes occupied with long-running requests. In the second scenario, the bot continues accepting messages while the queue absorbs the surge. Responses may arrive later, but the requests themselves are not lost.
Redis, RabbitMQ, and PostgreSQL are all commonly used for queue management.
Redis is often chosen for fast background jobs and lightweight task processing. RabbitMQ is suitable for more complex routing and delivery workflows. PostgreSQL can be a perfectly adequate queue backend when the project already relies on PostgreSQL and the workload remains moderate.
Queueing becomes especially important for AI-powered bots.
Imagine ten users uploading large PDF documents at exactly the same time. Launching ten simultaneous AI processing tasks directly inside the main application process can quickly exhaust server resources. A better approach is to store the requests, place them into a queue, and process them with a limited number of workers.
For example, only two or three AI jobs might run concurrently while the remaining tasks wait safely in the queue.
A simplified workflow could look like this:
event_id = save_incoming_event(user_id, message_text) add_task_to_queue(event_id) send_message( user_id, "Your request has been received and queued for processing." )
A separate worker handles the heavy lifting:
while True: event_id = get_next_task() process_task(event_id) mark_task_as_done(event_id)
This architecture protects the bot during sudden traffic surges. The main process remains responsive, incoming events are stored immediately, the queue absorbs temporary spikes, and workers process tasks at a pace that both the server and external APIs can handle safely.
Queues also provide valuable operational insight.
If the queue continuously grows and never returns to normal levels, that is a clear warning sign. It usually means workers cannot keep up with incoming traffic. At that point, several options become available: increase the number of worker processes, allocate more VPS resources, optimise task execution, or limit the number of resource-intensive operations each user can trigger.
The goal during peak traffic is not to execute everything instantly at any cost.
The real priority is ensuring that incoming messages, enquiries, orders, and requests are never lost while preventing resource-intensive operations from overwhelming the main bot process.
A queue makes that possible. The bot accepts the request, records it safely, and processes it when the infrastructure is ready to complete the task reliably rather than failing under pressure.
How to Monitor the Health of a Telegram Bot
Most Telegram bot owners only start thinking about monitoring after the first major outage. Until then, it is easy to assume that if the bot is responding to messages, everything is working correctly. In reality, there is often a gap of several hours or even days between a healthy system and a complete service failure.
Support teams regularly encounter situations where a bot appears operational while problems are already accumulating in the background. Task queues begin growing, database connection errors appear, memory consumption increases, or a percentage of requests starts failing. Users typically notice these issues much later than the server does.
That is why monitoring should not be viewed as a tool for investigating outages after they happen. Its real purpose is to detect warning signs before they become visible to users.
If the bot runs under systemd, one of the first checks should be the service status:
systemctl is-active telegram-bot
A healthy service returns:
active
A stopped service returns:
inactive
or:
failed
In many situations, this single command is enough to determine whether the process is still running.
Another useful diagnostic tool is checking active ports and listening services:
ss -tulpn
This command shows which applications are accepting network connections. If the bot uses a webhook, it helps confirm that the process is actually listening for incoming requests.
For example:
tcp LISTEN 0 128 0.0.0.0:8443
If the expected port is missing, the problem may be within the application itself rather than Telegram.
System logs remain one of the most valuable troubleshooting tools:
journalctl -u telegram-bot -f
The -f option follows new log entries in real time.
This is often where the first signs of trouble appear:
Connection timeout
Database connection failed
Out of memory
Unhandled exception
Support engineers frequently identify the root cause of outages directly from service logs when the only visible symptom is that the bot has stopped responding.
For applications managed by PM2, monitoring becomes even more straightforward.
View running processes:
pm2 list
View logs:
pm2 logs
PM2 also makes it easy to track restart counts, which can reveal hidden stability issues.
For example:
restarts: 0
indicates stable operation.
However:
restarts: 57
within a few hours is a strong indication that the application is repeatedly crashing and being restarted automatically. Users may not notice immediately, but the issue requires investigation.
Production Telegram bots should be monitored beyond the process itself. A proper monitoring strategy typically includes memory usage, CPU utilisation, task queue health, database availability, disk space, and application errors.
A server can appear healthy while the database has stopped responding or the disk has reached 100% capacity. From the user's perspective, the bot is broken even though the process remains online.
For this reason, effective monitoring follows a simple principle: monitor not only the application process but everything the bot depends on. That includes the database, available memory, disk capacity, task queues, external integrations, and system logs. Problems can then be detected when the first symptoms appear rather than after users start reporting failures.
For small and medium-sized projects, a dedicated monitoring platform is often sufficient. One of the most popular options is Uptime Kuma.
Uptime Kuma can monitor webhook endpoints, APIs, web interfaces, and other infrastructure components from a single dashboard. If a bot stops responding, a service becomes unavailable, or response times begin increasing, notifications can be sent automatically to Telegram, Discord, email, and other channels.
Support teams regularly see situations where an owner learns about a failure only after receiving complaints from users. With Uptime Kuma in place, an alert usually arrives within minutes of the issue occurring, giving administrators time to resolve the problem before it affects a larger number of users.
Larger deployments often extend monitoring with Prometheus, Grafana, and similar observability platforms. These tools provide detailed metrics for CPU usage, memory consumption, databases, task queues, application performance, and infrastructure health.
For most Telegram bots running on a VPS, however, Uptime Kuma is often enough to monitor availability and receive timely alerts when something starts going wrong. The goal is not simply to know when the bot has stopped working. The goal is to detect the conditions that lead to failure while there is still time to prevent it.
How to Receive Telegram Alerts When Something Goes Wrong
Automatic restarts help bring a Telegram bot back online quickly, but they do not solve another important problem. The owner may have no idea that the service has been crashing and restarting repeatedly for days or even weeks.
Support teams occasionally encounter situations where systemd or PM2 successfully restores a process after every failure, making the bot appear healthy from the outside. Users may notice only occasional delays, while the owner assumes everything is running normally. Later it turns out that the application was crashing dozens of times per day because of a coding error, memory exhaustion, or database issues.
That is why it is worth configuring alerts that are delivered directly to Telegram.
One of the simplest methods uses the Telegram Bot API and a curl request.
Example:
curl -s \
https://api.telegram.org/botTOKEN/sendMessage \
-d chat_id=CHAT_ID \
-d text="Telegram bot service is down"
Running this command manually should immediately send a message to the selected Telegram chat.
Once that works, a simple watchdog script can be created.
For example:
#!/bin/bash
SERVICE="telegram-bot"
if ! systemctl is-active --quiet $SERVICE
then
curl -s \
https://api.telegram.org/botTOKEN/sendMessage \
-d chat_id=CHAT_ID \
-d text="Service $SERVICE is not running"
systemctl restart $SERVICE
fi
The logic is straightforward. The script checks the service status. If the process is not running, it sends a Telegram alert and immediately attempts a restart.
A common approach is to run the check every few minutes using cron:
*/5 * * * * /opt/scripts/check-bot.sh
This allows the owner to learn about failures almost immediately instead of discovering them hours later through user complaints.
For PM2-managed applications, a similar approach can be implemented through custom monitoring scripts or PM2's built-in monitoring capabilities.
Alert messages become even more useful when they include diagnostic information rather than simply reporting that a service has failed. Details such as available memory, recent log entries, restart counts, or the detected error can significantly reduce troubleshooting time.
A notification might look like this:
Telegram Bot Alert
Service: telegram-bot
Status: FAILED
Memory usage: 97%
Reason: Out of memory
Time: 14:23:51
With information like this, administrators can often identify the cause of the failure immediately without logging into the server for an initial investigation.
For example, the watchdog script can be expanded to collect memory statistics before sending an alert:
#!/bin/bash
SERVICE="telegram-bot"
if ! systemctl is-active --quiet $SERVICE
then
MEMORY=$(free -m | awk '/Mem:/ {printf "%.0f%%", $3/$2 * 100}')
curl -s \
https://api.telegram.org/botTOKEN/sendMessage \
-d chat_id=CHAT_ID \
-d text="Service: $SERVICE
Status: FAILED
Memory usage: $MEMORY"
systemctl restart $SERVICE
fi
For larger projects, alerting is often integrated with monitoring platforms such as Uptime Kuma, Prometheus Alertmanager, Grafana, Zabbix, or other monitoring systems. Instead of checking a single process, these tools can monitor databases, queues, APIs, disk space, memory consumption, response times, and many other parts of the infrastructure.
Regardless of the monitoring platform used, the principle remains the same. A production Telegram bot should never rely on users to report problems first. The system owner should receive alerts before customers notice that something is wrong.
The earlier a failure is detected, the lower the risk of losing enquiries, messages, bookings, orders, or other business-critical data.
How to Organise Reliable Backups for a Telegram Bot
Most Telegram bot owners only start thinking about backups after the first serious incident. Until then, it is easy to assume that everything is safe because the database is on the server and the application files are still there.
Support teams regularly encounter the opposite situation. The bot still starts successfully, the application code remains intact, but after a failure the enquiry history is gone, user documents have disappeared, or critical configuration settings cannot be restored. The reason is usually simple: only part of the system was being backed up.
For a Telegram bot, protecting the database alone is not enough.
In most projects, a complete backup should include the PostgreSQL or SQLite database, Redis snapshots if Redis is being used, user-uploaded files, application configuration files, environment files containing credentials and settings, and the bot's source code or deployment scripts.
User-uploaded files are one of the most commonly forgotten components. The database is restored successfully, users can still see their enquiries and records, but all uploaded documents, images, and archives have disappeared because the uploads directory was never included in the backup process.
For PostgreSQL, pg_dump is commonly used.
A simple backup command looks like this:
pg_dump botdb > backup.sql
For automated daily backups, a cron job can be used.
For example, running every day at 02:00:
0 2 * * * pg_dump botdb > /backup/botdb_$(date +\%F).sql
SQLite is even simpler to back up because the entire database is stored in a single file.
cp database.db /backup/database_$(date +%F).db
If Redis is part of the infrastructure, its snapshots should also be preserved. Many administrators treat Redis as temporary storage and exclude it from backup routines. After a failure, they discover that task queues, cached data, or information about unfinished operations has disappeared.
User file directories should also be archived regularly:
tar -czf uploads_$(date +%F).tar.gz /opt/bot/uploads
Configuration files are often just as important as the database itself. After an outage, it may be possible to restore the data while still spending hours reconstructing API credentials, file paths, database connection settings, queue configurations, and other operational parameters.
For that reason, a complete Telegram bot backup usually includes application data, user files, configuration files, environment settings, and any supporting components required to restore the service fully.
Many administrators eventually move beyond individual backup commands and create a dedicated backup script.
A simple example might look like this:
#!/bin/bash
BACKUP_DIR="/backup/$(date +%F)"
mkdir -p $BACKUP_DIR
pg_dump botdb > $BACKUP_DIR/postgresql.sql
cp /opt/bot/database.db \
$BACKUP_DIR/database.db 2>/dev/null
tar -czf $BACKUP_DIR/uploads.tar.gz \
/opt/bot/uploads
tar -czf $BACKUP_DIR/config.tar.gz \
/opt/bot/.env \
/opt/bot/config
echo "Backup completed: $BACKUP_DIR"
The script can then be executed automatically through cron:
0 2 * * * /opt/scripts/backup.sh
This approach keeps all backup components together and reduces the risk of forgetting important directories or configuration files.
Another problem often remains hidden until the first recovery attempt.
Backups may be created successfully for months, but nobody ever verifies that they can actually be restored. When a disaster occurs, the archive turns out to be incomplete, corrupted, or missing critical data.
Support teams regularly see situations where backups were generated every day for several months, only to discover during recovery that the uploads directory had never been archived or that the database dump contained only part of the data because of an unnoticed export error.
For this reason, periodic test restores on a separate server are just as important as the backup process itself.
A backup should not be considered valid simply because a file exists. The only reliable proof that a backup works is a successful restoration. Testing the recovery procedure confirms that databases, files, configurations, and application components can all be brought back online when they are actually needed.
In practice, the most dangerous backup is not the one that fails to run. It is the one that appears to work for months but cannot restore the bot when a real incident occurs.
Common Mistakes That Prevent a Telegram Bot from Running Reliably 24/7
Mistake #1. Running the Bot Directly from an SSH Session
This is one of the most common mistakes during the early stages of a project.
A developer connects to the server via SSH and starts the bot manually:
python bot.py
or:
node bot.js
At first, everything appears to work perfectly. The bot responds to messages, enquiries are processed, and no errors are visible.
The problems appear later.
The SSH session is closed. The server reboots after a system update. The application exits because of an unhandled exception. The process is terminated after running out of memory.
When that happens, the bot stops working along with it.
In many cases, the owner only discovers the outage hours later, after users begin reporting that the bot is unavailable.
Support teams regularly encounter situations where a bot remained offline all night simply because it had been started manually and never came back online after a reboot.
For production deployments, process management through systemd or PM2 should be considered mandatory. A Telegram bot should restart automatically after a server reboot and recover from failures without requiring administrator intervention.
Mistake #2. No Automatic Restart Configuration
Some owners already use systemd or PM2 but forget to configure automatic process recovery.
As long as the application runs without errors, the problem remains invisible.
The situation changes when an exception occurs, the database becomes temporarily unavailable, or an external API returns an unexpected response. The process exits and remains offline until someone manually starts it again.
This often becomes apparent after updates.
For example, a dependency is upgraded, an API response format changes, the application receives unexpected data, and the process crashes. The server itself continues operating normally, but the bot stops responding.
With systemd, a single directive is usually enough:
Restart=always
PM2 provides similar behaviour automatically.
Support teams frequently investigate multi-hour outages where the root cause turns out to be surprisingly simple: the process crashed once and nobody had configured it to restart.
The failure itself was minor. The downtime occurred because the bot never recovered.
Mistake #3. Operating Without Monitoring
Many administrators assume that if the bot is responding right now, everything must be healthy.
In reality, there is often a long period between the first warning signs and a complete service failure.
Memory usage begins creeping upward. Occasional database connection errors appear. Response times gradually increase. Task queues start growing faster than they can be processed.
Users usually notice the problem only at the very end of that chain.
Support engineers regularly see servers where memory utilisation has remained above 95% for days, disk space is nearly exhausted, and the owner only becomes aware of the issue after the bot stops processing requests altogether.
Without monitoring, administrators are almost always the last people to learn about a failure.
At a minimum, monitoring should cover:
Process status
Memory consumption
CPU utilisation
Database availability
Free disk space
Application and system errors
Even better, alerts should be delivered automatically through Telegram, email, or another notification channel.
The goal is not simply knowing that the bot has failed. The goal is detecting the conditions that lead to failure while there is still time to act.
Mistake #4. No Backup Strategy
Backups are often postponed until later.
The bot is running normally. Data is being stored successfully. No major changes are taking place. It feels as though backups can wait.
The flaw in that thinking becomes obvious after the first serious incident.
A database becomes corrupted. A critical table is deleted accidentally. The server suffers a hardware failure. User files disappear during an update.
Only then does it become apparent that there are no backups at all, or that the most recent backup was created months ago.
Support teams have repeatedly dealt with situations where the value of lost data far exceeded the cost of the server itself.
This is especially critical for bots that process payments, bookings, orders, CRM records, or internal business workflows.
Backing up only PostgreSQL or SQLite databases is not enough.
User-uploaded files, application configuration files, environment variables, Redis snapshots, and task queue data can be just as important as the database itself.
A backup should never be considered complete simply because an archive file exists.
A backup is only valuable if it can be restored successfully.
That is why periodic recovery testing is just as important as the backup process itself.
Mistake #5. Relying on SQLite Under Heavy Load
SQLite is an excellent choice for small projects.
It requires no dedicated database server, is easy to configure, and performs extremely well during the early stages of development.
For that reason, many Telegram bots begin their life on SQLite.
The limitations become visible as the project grows.
More users begin sending messages simultaneously. Database activity increases. Background jobs appear. Document processing is introduced. AI integrations are added. Additional services start interacting with the application.
SQLite relies on file-level locking during write operations.
At low traffic levels, this is barely noticeable.
As concurrency increases, write operations begin waiting for locks to be released.
The first symptom is usually slightly slower responses.
Then errors begin appearing:
database is locked
Soon afterwards, task queues start growing and response times become increasingly unpredictable.
Support teams regularly see projects attempting to solve these problems by optimising code, upgrading CPUs, or adding more memory. In many cases, the real bottleneck is not the application or the server. It is the database architecture itself.
Bots that actively process enquiries, CRM data, message histories, payments, bookings, or AI workloads often reach the limits of SQLite long before they exhaust server resources.
As projects grow, the database frequently becomes the first infrastructure component that requires scaling.
SQLite remains an excellent choice for development, testing, and small production workloads. For larger 24/7 Telegram bots, PostgreSQL typically provides far more predictable performance, better concurrency handling, and a much stronger foundation for future growth.


