---
title: Architecture
description: High-level architecture and design principles of Alita Robot.
---

Alita Robot is a modern Telegram group management bot built with Go and the gotgbot library. This document provides an overview of the architectural decisions, technology stack, and design principles that guide the codebase.

## Technology Stack

**Go Runtime**

| Component | Technology | Purpose |
|-----------|------------|---------|
| **Language** | Go 1.26+ | Core application runtime |
| **Telegram Library** | gotgbot v2 | Telegram Bot API wrapper |
| **Build System** | GoReleaser | Multi-platform builds and releases |

**PostgreSQL**

| Component | Technology | Purpose |
|-----------|------------|---------|
| **Database** | PostgreSQL | Persistent data storage |
| **ORM** | GORM | Object-relational mapping |
| **Migrations** | Custom Engine | Schema versioning with transactional execution |

The database uses a **surrogate key pattern**: auto-increment `id` as PK with external IDs (`user_id`, `chat_id`) as unique constraints.

**Redis**

| Component | Technology | Purpose |
|-----------|------------|---------|
| **Caching** | Redis | Distributed caching layer |
| **Client** | gocache | Go cache library with marshaling |
| **Stampede Protection** | Shared loads | One database load per key among concurrent callers |

All cache keys are prefixed with `alita:` for namespace isolation. TTLs range from 20 seconds (anonymous admin verification) to 1 hour (language preferences).

**Monitoring**

| Component | Technology | Purpose |
|-----------|------------|---------|
| **Metrics** | Prometheus | Metrics and observability |
| **Tracing** | OpenTelemetry | Distributed tracing with OTLP/console exporters |
| **Health** | HTTP /health | Unified health, metrics, pprof on single port |

## Architecture Components

**Dispatcher**

Routes incoming Telegram updates to appropriate handlers. Configurable max goroutines (default: 200) with enhanced error handling and panic recovery.

**Module System**

Feature modules in `alita/modules/` follow a consistent pattern: `moduleStruct`, handler methods, `LoadModule` registration. Help module loads last to collect all commands.

**Cache Layer**

Redis caching with shared-load stampede protection. Per-type TTLs, automatic invalidation on writes, and distributed cache with namespace isolation.

**Permission System**

Centralized permission validation in `alita/utils/chat_status/`. Checks are cached to reduce Telegram API calls. Supports anonymous admin detection.

**Monitoring**

4-tier auto-remediation, activity tracking (per-chat and per-user DAU/WAU/MAU), background stats every 30s, and GC triggers on memory thresholds.

**Graceful Shutdown**

Central coordinator with LIFO handler execution. Each handler gets panic recovery. Total timeout: 60 seconds.

## Core Design Principles

### 1. Domain Functions Pattern

All database operations are organized by domain in `alita/db/{domain}/repository.go` files (e.g., `alita/db/warns/repository.go`, `alita/db/filters/repository.go`). Each package provides Get/Add/Update/Delete functions for its domain, with surrogate key pattern (auto-increment `id` as PK, external IDs as unique constraints):

```go
// Example: Direct domain function calls
settings := chats.GetChatSettings(chatId) // package alita/db/chats
```

### 2. Command Pipeline

New commands register through `helpers.WrapCommand(dispatcher, helpers.CommandDescriptor{...}, handler)` in `alita/utils/helpers/command_pipeline.go`. The wrapper handles cross-cutting concerns uniformly:

- Permission and precondition checks via `CommandDescriptor.RequiredChecks` (`helpers.RequireGroup()`, `helpers.RequireUserAdmin()`, `helpers.CanBotRestrict()`, ...). The first failing check handles its own feedback (a reply, or silence for a disabled command) and the command returns `ext.EndGroups`.
- Panic recovery via `error_handling.RecoverFromPanic`
- Ending handler-group iteration after a connected-chat swap (`endGroupsAfterChatSwap`)
- Alias and disableable-command registration from the descriptor

`alita/utils/helpers/decorators.go` only holds the legacy `MultiCommand` alias loop, which adds no wrapping, and the disableable-command registry (`AddCmdToDisableable`, `IsDisableable`, `DisableableCommands`).

### 3. Worker Pools

Concurrent processing uses bounded worker pools with panic recovery:

- **Dispatcher**: Limited to 200 max goroutines by default (configurable via `DISPATCHER_MAX_ROUTINES`)
- **Message Pipeline**: Concurrent validation stages
- **Bulk Operations**: Parallel batch processors with generic framework

### 4. Redis Caching

Redis-based caching with stampede protection:

- Distributed cache using Redis for persistence across restarts
- Concurrent callers for the same key share one database load (`cache.GetFromCacheOrLoad`)
- Configurable TTLs per data type (30min - 1hr typically)

## Request Flow Diagram

```
                                    +------------------+
                                    |    Telegram      |
                                    |    Bot API       |
                                    +--------+---------+
                                             |
                          +------------------+------------------+
                          |                                     |
                   Webhook Mode                           Polling Mode
                          |                                     |
                          v                                     v
               +----------+----------+              +-----------+-----------+
               |   HTTP Server       |              |      Updater          |
               |      /webhook       |              |   GetUpdates loop     |
               +----------+----------+              +-----------+-----------+
                          |                                     |
                          +------------------+------------------+
                                             |
                                             v
                                  +----------+----------+
                                  |     Dispatcher      |
                                  | (configurable routines)|
                                  +----------+----------+
                                             |
                         +-------------------+-------------------+
                         |                   |                   |
                         v                   v                   v
                  +------+------+     +------+------+     +------+------+
                  |   Handler   |     |   Handler   |     |   Handler   |
                  |  (Command)  |     | (Callback)  |     |  (Message)  |
                  +------+------+     +------+------+     +------+------+
                         |                   |                   |
                         +-------------------+-------------------+
                                             |
                              +--------------+--------------+
                              |                             |
                              v                             v
                    +---------+----------+        +---------+----------+
                    |   Redis Cache      |        |   PostgreSQL       |
                    |   (cache lookup)    |        |   (via GORM)       |
                    +--------------------+        +--------------------+
```

## Key Subsystems

### Dispatcher

The dispatcher routes incoming Telegram updates to appropriate handlers:

- Configurable max goroutines (default: 200)
- Enhanced error handler with structured logging
- Recovery from panics in any handler

```go
dispatcher := ext.NewDispatcher(&ext.DispatcherOpts{
    Error: func(b *gotgbot.Bot, ctx *ext.Context, err error) ext.DispatcherAction {
        // Error handling with structured logging
        return ext.DispatcherActionNoop
    },
    MaxRoutines: config.AppConfig.DispatcherMaxRoutines,
})
```

### Module System

Each feature module follows a consistent pattern:

1. Define a `moduleStruct` with module name
2. Implement handler functions as methods
3. Register handlers in a `LoadModule` function
4. Self-register in `init()` via `RegisterLegacyModule(name, priority, loadFunc)`
5. Loaded collectively via `modules.LoadAllModules(dispatcher)` in priority order

### Cache Layer

Redis caching with stampede protection:

- **Cache Keys**: Prefixed with `alita:` for namespace isolation
- **Stampede Protection**: `GetFromCacheOrLoad` shares one database load per key among concurrent callers
- **TTL Management**: Per-type expiration (settings: 30min, language: 1hr)

### Monitoring

Comprehensive monitoring subsystems:

- **Activity Monitor**: Automatic group activity tracking with configurable thresholds
- **Background Stats**: Samples memory and goroutine counts every 30 seconds and database stats every minute, and reports every 5 minutes
- **Auto-Remediation**: GC triggers when memory exceeds thresholds

## Concurrency Model

### Bounded Concurrency

```go
// Dispatcher limits concurrent handler execution
MaxRoutines: 200  // Configurable via DISPATCHER_MAX_ROUTINES

// Hot bulk paths have fixed local limits: purges, flood cleanup, admin checks,
// and multi-member greetings. They are intentionally not configuration knobs.
```

### Shared Cache Loads

`alita/db/cache.GetFromCacheOrLoad` runs one load per key and shares it among concurrent callers. Each caller keeps its own cancellation and deadline. The shared query has a 30-second deadline (`loadWaitTimeout`) and is cancelled when its last waiting caller leaves. Failed or cancelled loads are not cached. See [Caching](/architecture/caching#stampede-protection).

### Graceful Shutdown

```go
// Shutdown manager coordinates cleanup in order
shutdownManager := shutdown.NewManager()
shutdownManager.RegisterHandler(func() error {
    // Cleanup monitoring, database, cache
    return nil
})
```

## Error Handling Strategy

Alita uses a 4-layer error handling hierarchy:

:::note[Error Recovery Layers]
The 4-layer hierarchy ensures that no panic or error goes unhandled. Each layer catches what the layer below it might miss, providing defense-in-depth against crashes.
:::

### Layer 1: Dispatcher Level

```go
Error: func(b *gotgbot.Bot, ctx *ext.Context, err error) ext.DispatcherAction {
    defer error_handling.RecoverFromPanic("DispatcherErrorHandler", "Main")
    // Log error with structured fields
    return ext.DispatcherActionNoop
}
```

### Layer 2: Worker Level

Worker pools implement panic recovery:

```go
go func() {
    defer func() {
        if r := recover(); r != nil {
            log.WithField("panic", r).Error("Panic in worker")
        }
    }()
    // Worker logic
}()
```

### Layer 3: Handler Level

Handlers outside the pipeline call the `chat_status` predicates directly and return early:

```go
// Permission checks return early on failure
if !chat_status.RequireUserAdmin(b, ctx, nil, user.Id) {
    return ext.EndGroups
}
```

### Layer 4: Command Pipeline

`helpers.WrapCommand` adds panic recovery, `RequiredChecks` permission validation and chat-swap group termination around every command it registers:

```go
// The pipeline wraps the handler with checks, panic recovery and group termination
helpers.WrapCommand(dispatcher, helpers.CommandDescriptor{
    Name:    "cmd",
    Aliases: []string{"alias"},
    RequiredChecks: []helpers.CheckFunc{
        helpers.RequireGroup(),
        helpers.RequireUserAdmin(),
    },
}, handler) // handler: func(c *helpers.CommandContext) error
```

## Database Schema Design

The database uses a **surrogate key pattern**:

- **Primary Keys**: Auto-incremented `id` field (internal identifier)
- **Business Keys**: `user_id` and `chat_id` with unique constraints
- **Benefits**:
  - Decouples internal schema from Telegram IDs
  - Stable identifiers if external systems change
  - Better performance for joins and indexing

:::note[Why Surrogate Keys?]
Telegram IDs are external identifiers that the project does not control. Using auto-increment internal IDs as primary keys decouples the schema from Telegram's ID space, provides stable join targets, and allows better index performance on frequently queried columns.
:::

## Next Steps

- [Project Structure](/architecture/project-structure) - Directory layout and key files
- [Request Flow](/architecture/request-flow) - Detailed update processing pipeline
- [Module Pattern](/architecture/module-pattern) - How to add new modules
- [Caching](/architecture/caching) - Redis caching architecture
