Skip to main content

Backend Project Structure

Clean, modular FastAPI backend designed for rapid development and scalability.

Directory Structure

back/
├── src/
│ ├── main.py # FastAPI app & router setup
│ ├── models/ # Database & API models
│ │ ├── db_models.py # SQLModel database tables
│ │ └── api_models.py # Pydantic API schemas
│ ├── routers/ # API endpoints by feature
│ │ ├── chat.py # AI chat interface
│ │ ├── ocr.py # Document processing
│ │ └── embedding.py # Vector search
│ ├── services/ # Business logic & integrations
│ │ ├── database_service.py # DB sessions
│ │ ├── mistral_service.py # AI API calls
│ │ └── storage_service.py # File uploads
│ ├── utils/ # Authentication & helpers
│ └── workflow/ # Abraxas async processes
├── alembic/ # Database migrations
├── docker/ # PostgreSQL setup
├── pyproject.toml # Dependencies (uv)
└── worker.py # Worker for Abraxas

Architecture Overview

Data Flow:

Request → Router → Service → Database

Response ← Pydantic ← SQLModel

Key Components:

  • main.py - FastAPI app, middleware, and router registration
  • models/ - Type-safe data models for database and API
  • routers/ - API endpoints organized by feature domain
  • services/ - Business logic, external APIs, and data access
  • utils/ - Authentication, validation, and shared helpers
  • workflow/ - Long-running processes with Abraxas

📊 Data Models

Database models (db_models.py):

class Task(ModelWithIdAndTimestamps, table=True):
title: str
completed: bool = Field(default=False)
user_id: UUID = Field(foreign_key="user.id")

API models (api_models.py):

# Auto-generated from base models
CreateTaskDTO = create_create_model(TaskBase, "CreateTask")
TaskDTO = create_read_model(TaskBase, "Task")

class UserWithTasks(UserBase):
tasks: list[TaskDTO]

🔄 Background Processing

Workflows handle complex, multi-step processes:

@workflow
class DataProcessingWorkflow:
@workflow.run
async def run(self, user_id: int) -> dict:
# Multi-step process with automatic retries
pass

Worker (worker.py) processes workflows in the background.

🛠️ Development Setup

Database migrations:

uv run alembic revision --autogenerate -m "Add feature"
uv run alembic upgrade head

Local database:

cd back/docker && docker-compose up -d

🎯 Design Principles

  • Separation of concerns - Routes, services, models have distinct roles
  • Dependency injection - Clean, testable service dependencies
  • Type safety - SQLModel + Pydantic throughout the stack
  • Feature organization - Related code grouped together

This structure scales from simple APIs to complex applications while keeping the codebase organized and maintainable.