← all articles
~/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.

// need help with a project?

I build backends, bots, automations and AI tools.

get in touch →