Host Telegram bot for free, with persistent storage!

I used to run my Telegram bots on Heroku, but since they decided to remove their free plan that is no longer an option (for me). Luckily there is Fly.io which allows you to run up to 3 apps for free, with 3 GB of free persistent storage! I'd argue that deploying & managing apps on Fly is even easier than on Heroku.

This tutorial is written for Telegram bots made with Node.js, but shouldn't be too difficult to apply to other languages as well.

Preparing your app

Your app needs to listen to some port for it to work on Fly.io. In my previous tutorial I used express for this but we can achieve the same using Node's built-in HTTP server.

// server.js
const http = require("http");

const server = http.createServer((req, res) => {
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end("Hello World");

module.exports = { server };

Then just import your server and do server.listen(process.env.PORT || 3000). You can confirm that everything's working smoothly by running the bot and going to localhost:3000. It should give you a "Hello World" text.

Creating Fly.io app

After you've installed flyctl and signed up, you can create your Fly app (and generate necessary config files) with fly launch. Note that we don't want to do fly deploy (which can also be used to create the app) since we need to do some stuff before the actual deployment.

Make sure to give your app a proper name, since renaming it later is impossible as far as I know.


Add your BOT_TOKEN with fly secrets set BOT_TOKEN=xxx. You can see list of your secrets with fly secrets list if needed.

Persistent storage

If you don't need persistent storage, just skip this step.

Create a volume for your app with fly volumes create node_persist --region fra --size 1. This creates 1 GB volumes on FRA region. The region must be the same where you created your Fly app (specified when we first did the fly launch), and the 1 GB volume is the smallest volume possible to create.

After that, add a [[mounts]] section to your fly.toml config file which was generated automatically on app creation. I'm using node-persist with my Telegram bots since it's super easy to use and fast enough for my purposes. It saves stored items in JSON files inside a .node-persist directory, so that's the directory I want to mount.

By default, Fly apps are located inside /app directory, so remember to add that to the destination path. You can change the app directory inside Dockerfile if you want.

  source = "node_persist"
  destination = "/app/.node-persist"

Deploying the app

Make sure your Node app has a start script. Then just deploy the app with fly deploy. Afterwards you're able to view the logs with fly logs.

✌🏼 Like my content? Subscribe via RSS feed.