← Back to projects
In production — 20,000 users

Telegram Moderation Bot

A bot originally designed as a vouch-based acceptance funnel — every user has to be vouched for by an existing member to join a group — later extended with classic moderation (keywords, links, forwards) at clients' request. Hosted on a VPS I manage myself, with a test environment fully separate from production and a fully automated deployment pipeline.

Python python-telegram-bot SQLite systemd GitHub Actions

Why this project

Originally, this isn't a classic spam filter — it's a vouch-based system. The bot is deployed across every group in the community, and each new user has to be vouched for by an existing member to be accepted — no vouch, no entry. This acceptance funnel drastically cuts down on fake accounts and mass sign-ups before a single message is even sent.

Later on, the clients using this bot asked for a more classic moderation layer: keyword filtering, link filtering, and suspicious forwarded messages. The goal stays the same — keep each group as safe and spam-free as possible — by combining entry-point vetting with ongoing monitoring once someone is in the community.

Moderating such an active community directly on production wasn't a viable option: the smallest regression could affect 20,000 people at once. That's why I strictly separated a test environment from production, each with its own Telegram bot and its own database.

How it's built

The bot runs on a Linux VPS I administer myself, as two separate instances managed by systemd: one for testing, one for production. Each has its own process, its own SQLite database, and its own Telegram token, fully isolating the two environments — a regression in test can never reach the 20,000 members of the real community.

Moderation actions (bans, message deletions, sanctions) go through a custom async queue I built in Python (asyncio), to serialize calls to the Telegram API, avoid rate-limiting, and keep SQLite writes consistent.

On the monitoring side, each service writes its logs via journalctl. On top of that, a second Telegram bot dedicated to monitoring sends real-time alerts, and a Slack automation notifies automatically whenever a service goes down or the code breaks — no need to watch the logs constantly.

GitHub Actions tests + deploy SSH LINUX VPS bot-mod-test systemd service SQLite (test) moderation_test.db bot-mod-prod systemd service SQLite (prod) moderation_prod.db Async queue asyncio · serializes actions Telegram Bot API

GitHub Actions deploys to the VPS over SSH. Both bots (test/prod) run as isolated systemd services, each with its own SQLite database, and go through a shared async queue before calling the Telegram API.

What it actually does

  • Two fully isolated environments (test and production), each with its own systemd process, its own SQLite database, and its own Telegram bot — a bug in test can never reach the real community
  • Automatic service restart on crash via systemd (Restart=on-failure), no manual intervention needed
  • Custom async queue that serializes moderation actions (bans, message deletions, sanctions) to respect the Telegram API's rate limits and avoid concurrent writes to SQLite
  • GitHub Actions pipeline that runs tests automatically on every push, then deploys to the VPS over SSH and restarts the relevant service on merge to the main branch
  • Logs available via journalctl for each service, for quick incident diagnosis
  • Active monitoring: a second, dedicated Telegram bot sends real-time alerts, backed by a Slack automation that notifies automatically whenever a service goes down or the code breaks (crash, unhandled error, failed deployment)

By the numbers

20K users moderated
2 isolated environments (test/prod)
100% automated deployments via CI/CD