Telegram bot with Rust

by Afanasy Barbarov

Building a Telegram Bot with Rust

After giving Rust another chance, I decided to build something real: a Telegram bot that lets users upload documents and ask questions about them using OpenAI's assistants API.

The requirements were straightforward - accept file uploads, process them through OpenAI's vector search, and stream responses back. What I didn't expect was how well Rust handled the async complexity.

Architecture

┌─────────────┐    ┌──────────────┐    ┌─────────────┐
│   Telegram  │───▶│  Rust Bot    │───▶│   OpenAI    │
│   Webhook   │    │  (teloxide)  │    │ Assistants  │
└─────────────┘    └──────────────┘    └─────────────┘


                   ┌──────────────┐
                   │  PostgreSQL  │
                   │  (users/auth)│
                   └──────────────┘

                   ┌──────────────┐
                   │    SQLite    │
                   │ (chat state) │
                   └──────────────┘

The bot runs as a single binary with webhook endpoints. When users upload files, they get downloaded locally, uploaded to OpenAI's vector store, then deleted. Chat state persists across restarts using SQLite storage.

User access is gated by promo codes stored in PostgreSQL. Each user gets their own OpenAI assistant instance with attached file storage.

Building with Bazel

Bazel proved excellent for Rust. Cross-compilation to ARM64 and x86_64 with musl linking produces tiny, portable binaries. The final container images are under 20MB.

The build system handles dependency management better than Cargo for this type of deployment. Reproducible builds and hermetic compilation made deployment predictable.

What Worked

The bot has been running for months without issues. Rust's memory safety eliminated entire classes of bugs I'd typically worry about. The async runtime handles concurrent users without performance surprises.

Most importantly, once built, it just works. No memory leaks, no mysterious crashes, no surprise GC pauses. The upfront compiler fights paid off with a service that requires zero maintenance.

Future posts will dive deeper into the Bazel setup and deployment strategies.

Written by Afanasy Barbarov — Tech Lead with 15+ years shipping production systems in Rust, Go, and TypeScript. Facing a similar challenge? Reach out on LinkedIn. Support my work.

More articles

Previous post

A second try to use Rust for personal projects.

Read more

Next post

Give Nomad second chance.

Read more