92d67369e9
Agent-Logs-Url: https://github.com/christianlouis/pop_puller_to_gmail/sessions/82f2f361-3513-44e6-991b-db1a19902772 Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
112 lines
3.9 KiB
Markdown
112 lines
3.9 KiB
Markdown
# ADR 003: Use FastAPI as Web Framework
|
|
|
|
**Status:** Accepted
|
|
**Date:** 2026-01-25
|
|
**Deciders:** Development Team
|
|
|
|
## Context
|
|
|
|
The multi-tenant SaaS backend requires a Python web framework that can handle:
|
|
|
|
1. High-concurrency API requests (multiple users, simultaneous email polls)
|
|
2. Asynchronous database and network I/O without blocking
|
|
3. Automatic input validation and serialization
|
|
4. Built-in interactive API documentation
|
|
5. Easy integration with the async ecosystem (asyncpg, aiosmtplib, aioimaplib)
|
|
|
|
## Decision
|
|
|
|
We will use **FastAPI** as the primary web framework for the backend API.
|
|
|
|
## Alternatives Considered
|
|
|
|
### 1. Django REST Framework (DRF)
|
|
- **Pros**: Mature ecosystem, batteries-included ORM, admin panel, well-known
|
|
- **Cons**: Synchronous-first, heavier footprint, complex async support, more boilerplate
|
|
|
|
### 2. Flask
|
|
- **Pros**: Lightweight, flexible, large community
|
|
- **Cons**: No native async support, requires extensions for validation, no auto-docs, more manual wiring
|
|
|
|
### 3. Starlette (bare)
|
|
- **Pros**: Minimal, pure async, very fast
|
|
- **Cons**: No built-in validation, no auto-documentation, requires writing more boilerplate
|
|
|
|
### 4. Tornado
|
|
- **Pros**: Battle-tested async framework, good WebSocket support
|
|
- **Cons**: Older API design, less active development, no modern type annotation support
|
|
|
|
## Rationale
|
|
|
|
FastAPI was chosen because:
|
|
|
|
1. **Native Async Support**: First-class `async`/`await` support matches our async database (asyncpg) and mail protocol (aiosmtplib, aioimaplib) libraries
|
|
2. **Automatic Validation**: Pydantic models provide request/response validation with no extra code
|
|
3. **Auto-generated Docs**: OpenAPI spec and Swagger UI at `/api/docs` out of the box
|
|
4. **Type Safety**: Python type annotations drive both validation and editor tooling
|
|
5. **Performance**: Comparable to Node.js and Go for async I/O workloads (Starlette/uvicorn underneath)
|
|
6. **Dependency Injection**: Built-in `Depends()` system for auth, database sessions, and config
|
|
7. **Modern Python**: Designed for Python 3.8+ with full typing support
|
|
|
|
## Implementation Notes
|
|
|
|
```python
|
|
# Application factory pattern with lifespan context manager
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# Startup: create tables, seed defaults
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
yield
|
|
# Shutdown: cleanup
|
|
|
|
app = FastAPI(
|
|
title="InboxConverge API",
|
|
lifespan=lifespan,
|
|
openapi_url="/api/openapi.json",
|
|
docs_url="/api/docs",
|
|
)
|
|
```
|
|
|
|
```python
|
|
# Versioned API routing
|
|
from fastapi import APIRouter
|
|
|
|
api_router = APIRouter(prefix="/api/v1")
|
|
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
|
api_router.include_router(mail_accounts.router, prefix="/mail-accounts", tags=["mail-accounts"])
|
|
```
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
- Clean, self-documenting API with zero extra work
|
|
- Async I/O throughout eliminates thread-pool bottlenecks
|
|
- Pydantic validation catches bad input before it reaches business logic
|
|
- Dependency injection decouples auth, DB, and config from route handlers
|
|
- Fast iteration: type errors and validation errors caught at startup
|
|
|
|
### Negative
|
|
- Smaller ecosystem than Django (fewer ready-made plugins)
|
|
- Pydantic v2 migration required breaking changes from v1
|
|
- Lifespan/startup patterns require careful structuring to avoid import cycles
|
|
|
|
### Neutral
|
|
- Uvicorn required as ASGI server for production
|
|
- Gunicorn can be used to manage multiple uvicorn workers
|
|
|
|
## Related Decisions
|
|
|
|
- See ADR-004 for database choice (asyncpg/SQLAlchemy async)
|
|
- See ADR-007 for JWT authentication via `Depends()`
|
|
|
|
## References
|
|
|
|
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
|
- [Starlette Documentation](https://www.starlette.io/)
|
|
- [Pydantic Documentation](https://docs.pydantic.dev/)
|
|
- [TechEmpower Framework Benchmarks](https://www.techempower.com/benchmarks/)
|