Skip to the content

Projects03 / 07 · community platform · 2023–present

WardyBot 03

Moderation, anti-spam and game mechanics for large Telegram chats — 2.1 million users served from a single $24-a-month server.

Tech lead · architect · product owner · devops
Skip to the engineering
In plain words

A chat with 28,000 people in it cannot be moderated by a human

Picture a Telegram chat with 28,000 people in it. Someone is spamming ads, someone is picking fights, someone is running bots. A human admin physically cannot keep up.

WardyBot takes that job: it catches spam, screens bots at the door, moderates toxicity and keeps the statistics. Then it does the other half — keeping people there. An in-chat currency, reputation, achievements, collectibles with a marketplace, duels, giveaways and an AI assistant give a community reasons to come back, and give its owner something to sell.

The number I care about is the ratio: two million users, one $24 virtual machine, a thousand days without a break. Not because cheap hosting is a virtue in itself — because every architectural decision below was made under that constraint, and the constraint is what makes them interesting.

For engineers

One Rails process, N bots, four currencies and a ledger that cannot drift

950 service objects, 52k lines of code against 110k lines of tests, one VPS with 2 vCPU and 3.8 GB of RAM.

One core, many bots — until it did not need to be

One Rails process served the main bot by webhook and customer bots by pollers, raising a client for an arbitrary bot id straight from the database, sessions isolated per bot · chat · user. It carried 17 white-label bots before the tenancy model was collapsed onto the chat in June 2026 — the simplification the traffic had earned.

Aggregate, don’t archive

23M messages compressed into 1.5M counter rows (user × room × day). A deliberate refusal to store per-message — which is why the database is 2.9 GB instead of ~300, and why the $24 server is still the right size.

Immutable financial ledger

Transactions cannot be deleted, and cannot be updated except for two types. 26 operation kinds, four currencies, amount sign validated against type — 82,000 transactions, no balance drift.

Reflective command router

Instead of a route table the dispatcher discovers controllers by glob and maps a command to a method by reflection — a new command module is a new file, nothing else. Exactly what you want when ten people add commands in parallel. 73 registered commands.

Moderation pipeline before routing

Eight validators in sequence; only the ones that must delete instantly run synchronously. Anti-spam expands 64 homoglyphs into regex classes, so ПpNB1т is still caught.

Cross-language RPC · AI billed at cost

Quote rendering lives in another service, in another language, on another server: request-reply over federated RabbitMQ queues with zlib+base64 transport. Upstream inference cost is read out of the provider response and converted into internal tokens, so pricing tracks the market instead of a hardcoded guess. Telegram file ids cached in Redis under versioned keys removed the most expensive part of outbound traffic.
196
zero-downtime deploys
2:1
tests to code · 12,800+ examples
2.9 GB
database at 2.1M users
2 / 3.8
vCPU / GB — the whole box
Engineering culture, since it is mine to answer for: 110k lines of tests against 52k of code, no RuboCop todo file, a pre-commit gate on Ruby and TypeScript, CI on every push, AI review on every pull request. 196 zero-downtime deploys, all of them mine.

Who worked on it · 7 contributors

Danyil Shkoropad

tech lead · architect · product owner · 2023–2026
  • Product and architecture from a blank page; the immutable ledger and all 196 deploys.
  • Set the process ten developers work inside: ticket branches, review, CI, mandatory tests.

Oleksandr Shemberko

fullstack · 2024–2026
  • Skins — the collectibles with their shop, drops, sales and moderation — plus duels and the captcha quiz at the door.
  • The web admin on Vue 3 + TypeScript, and the Mini App’s move to React with its premium shop.

Oleksii Mikhno

fullstack · 2024–2025
  • The Mini App view layer and the donation flow behind it.
  • Worked on the giveaway and achievement mechanics.

Vladyslav Fomenko

fullstack · 2024–2025
  • The quotes surface — menu, categories, backgrounds — and the API endpoint that hands a quote to the render service.
  • Hardened the error paths: Telegram client failures, AI-filter job errors, Rollbar under rate limiting.

Nataliia Makarenko

backend · data · 2024–2026
  • The OpenRouter features, the background jobs behind them, and the backup routine.
  • Kept both languages of the interface in step as the command surface grew.

Mykhail Yun

co-founder · product · 2023–2026
  • Turns chat owners’ complaints into tickets — most of the moderation rules started as a customer call.
  • Sold and onboarded the 17 white-label bots that ran on the shared core.

Claude

pull request review · 2026
  • Review the moment a pull request opens for review — never on a draft, never twice on the same push.
  • Most useful on the ledger: flags any migration that could mutate a transaction.

Read to the end and want to talk it over?

rubyco.in