~/blog/telegram-bot-python-2024.md
November 15, 2024·12 min
How to Build a Telegram Bot with Python in 2024 — Complete Guide
Step-by-step guide to building a production-ready Telegram bot using Aiogram 3, PostgreSQL and Docker deployment. From zero to a working product.
PythonTelegramAiogramPostgreSQLDocker
How to Build a Telegram Bot with Python in 2024
Telegram bots are one of the fastest ways to automate business processes or build a full product. In this article I'll show you how to build a production-ready bot with a database, proper architecture, and deployment from scratch.
What We'll Build
- Bot on Aiogram 3 (async, modern API)
- PostgreSQL for data storage
.env-based configuration- Docker for deployment
- FSM (finite state machine) for multi-step scenarios
Why Aiogram 3
Aiogram 3 is the de facto standard for serious Python bots:
- Fully async (asyncio)
- Routers and middlewares like FastAPI
- Convenient FSM for dialogs
- Active maintenance and good documentation
Setup and Project Structure
pip install aiogram==3.* sqlalchemy asyncpg python-dotenv
Project structure:
bot/
├── handlers/
│ ├── __init__.py
│ ├── common.py # /start, /help
│ └── user.py # user scenarios
├── middlewares/
│ └── database.py # inject session into handlers
├── models/
│ └── user.py # SQLAlchemy models
├── keyboards/
│ └── reply.py
├── config.py
└── main.py
Configuration
# config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
BOT_TOKEN: str
DATABASE_URL: str
ADMIN_ID: int
class Config:
env_file = ".env"
settings = Settings()
Main Entry Point
# main.py
import asyncio
from aiogram import Bot, Dispatcher
from aiogram.fsm.storage.memory import MemoryStorage
from handlers import common, user
from config import settings
async def main():
bot = Bot(token=settings.BOT_TOKEN)
dp = Dispatcher(storage=MemoryStorage())
dp.include_router(common.router)
dp.include_router(user.router)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
The /start Handler
# handlers/common.py
from aiogram import Router
from aiogram.filters import CommandStart
from aiogram.types import Message
router = Router()
@router.message(CommandStart())
async def cmd_start(message: Message):
await message.answer(
f"Hey {message.from_user.first_name}! 👋\n\n"
"I'm here to automate your tasks."
)
FSM — Multi-step Dialogs
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
class OrderForm(StatesGroup):
waiting_name = State()
waiting_phone = State()
waiting_comment = State()
@router.message(Command("order"))
async def start_order(message: Message, state: FSMContext):
await state.set_state(OrderForm.waiting_name)
await message.answer("What's your name?")
@router.message(OrderForm.waiting_name)
async def got_name(message: Message, state: FSMContext):
await state.update_data(name=message.text)
await state.set_state(OrderForm.waiting_phone)
await message.answer("Your phone number:")
Database Integration
# models/user.py
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import BigInteger, String, DateTime, func
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
username: Mapped[str | None] = mapped_column(String(64))
first_name: Mapped[str] = mapped_column(String(128))
created_at: Mapped[DateTime] = mapped_column(server_default=func.now())
Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
Deploying to VPS
git clone your-repo && cd bot
cp .env.example .env # fill in tokens
docker compose up -d
Summary
A properly built Telegram bot is not just a script with if '/start'. It's a full application with routers, middlewares, a database and CI/CD. Aiogram 3 gives you all the tools for that.
Need help building a bot? Get in touch.