Over the past few years, I’ve built quite a few FastAPI applications for various projects. Each time I started a new one, I found myself copying and pasting the same boilerplate code, setting up the same project structure, and making the same architectural decisions over and over again. Sound familiar?

I got tired of this repetitive process and decided to do something about it. I wanted to create a comprehensive FastAPI template that would save me (and hopefully others) hours of setup time while incorporating all the lessons I’ve learned from building APIs in production.

In this post, I want to share the journey of creating this template, the decisions I made along the way, and why I think it could be useful for your next FastAPI project too.

The Problem with Starting from Scratch

Building APIs from scratch often leads to common pitfalls. Projects start with simple flat structures that become nightmares to navigate as they grow. Proper logging gets forgotten until something breaks in production. APIs work perfectly on development machines but fall apart under real-world load.

Each painful experience taught me something valuable, but I kept repeating the same setup process for every new project. I wanted to create a template that would help me (and others) start with the right foundation from day one:

Architectural Design: Lessons from Netflix

After evaluating various project structures, a layered architecture inspired by Netflix’s Dispatch project emerged as the most effective approach. This design addresses the common problems with typical “organize by file type” structures taught in many tutorials.

Here’s what works well in practice:

The Four-Layer Architecture

API Layer: Handles HTTP requests and responses, defines endpoints and routes, and depends on the service layer. Each domain has its own router module, keeping endpoints organized and focused.

Service Layer: Implements business logic, coordinates activities between multiple repositories, handles exceptions and error responses, and serves as the orchestration layer between the API and data access layers.

Repository Layer: Provides data access abstraction through the repository pattern, implements CRUD operations, and can be easily swapped between different storage backends without affecting higher layers.

Model Layer: Defines data structures using Pydantic for validation and serialization, ensuring type safety throughout the application.

This separation has saved me countless hours when debugging issues or adding new features. I can work on one layer without worrying about breaking others, and testing becomes much more straightforward.

The Repository Pattern: Beyond Simple CRUD

The repository pattern may seem like unnecessary abstraction for simple CRUD operations, but it proves its value when applications need to scale or adapt to changing requirements. The benefits become clear when switching between different storage backends without affecting business logic.

The repository pattern provides value through:

A generic base repository interface covers common operations used in most projects. This eliminates repetitive code and ensures consistency across different domains.

Logfire: Modern Observability Solution

Traditional observability setups with ELK stacks, Jaeger configuration, and complex monitoring systems can be challenging to implement. Logfire from the Pydantic team offers a streamlined alternative that simplifies observability while maintaining comprehensive functionality.

Logfire provides:

The integration with FastAPI’s middleware system enables automatic tracing of requests, database queries, and custom events without manual instrumentation.

Taskiq: Modern Alternative to Celery

Celery has been the standard for background tasks, but its async support feels bolted on rather than built-in. This often leads to workarounds when integrating with async FastAPI applications.

Taskiq offers a modern alternative with native async support:

The template includes configuration for both development and production setups, complete with Docker Compose files for quick setup.

Database Migrations with Alembic

Database schema evolution is a critical aspect of any long-lived project. The template includes Alembic configuration for handling database migrations with SQLAlchemy . The setup includes:

Testing

Writing tests is essential for maintaining code quality and enabling confident refactoring. Early-career developers often view tests as impediments to velocity, but experience shows they’re critical for long-term maintainability and debugging capabilities.

Building testing into every project from the beginning prevents technical debt. The template includes a testing structure that mirrors the application architecture:

Using pytest with async support throughout means tests can be written in the same style as application code, eliminating context switching between sync and async patterns.

Development Tools

Effective development requires tools that work reliably without extensive configuration. The template includes carefully selected tools that enhance the development experience:

Makefile: Provides simple commands for common tasks like running tests, starting services, and managing dependencies.

Pre-commit Hooks: Automatically format code and run linters before commits, ensuring consistent code quality across team members.

Ruff : Modern Python linter and formatter that’s significantly faster than traditional tools while providing comprehensive code quality checks.

UV : Modern package management solution that provides significantly improved performance over traditional Python package managers.

These tools eliminate friction from the development workflow without requiring extensive configuration.

Production-Ready Deployment

Development environments often mask issues that surface in production. Making applications work reliably under real-world conditions requires addressing concerns like resource management, error handling, and monitoring.

The template includes Docker configuration refined through multiple production deployments:

These considerations address real production environment challenges rather than theoretical concerns.

Security and Authentication

Security cannot be retrofitted into applications effectively. The authentication system is designed to be flexible for different use cases while maintaining security by default:

The authentication system is built as a reusable FastAPI dependency, making it easy to extend or replace based on specific project requirements.

Configuration Management

Configuration issues are common sources of deployment problems. Wrong environment variables, missing settings, and values that work in development but fail in production can cause significant issues.

The template uses Pydantic Settings to address these problems:

Domain-Driven Project Structure

Organizing code by business domains rather than technical layers has proven more maintainable than traditional file-type organization. The template structures each domain as follows:

PLAINTEXT
domain/
├── __init__.py
├── config.py          # Domain-specific configuration
├── deps.py            # Domain dependencies
├── exceptions.py      # Domain exceptions
├── models.py          # Database models
├── repository.py      # Data access layer
├── schemas.py         # Pydantic models
├── service.py         # Business logic
├── utils.py           # Domain utilities
└── views.py           # API endpoints
Click to expand and view more

This structure improves maintainability by keeping related functionality together. When working on user management, everything needed is in the users directory. When debugging authentication issues, the relevant code is easily located.

Monitoring and Metrics

Beyond basic logging, the template includes comprehensive monitoring capabilities:

Prometheus Integration: Automatic collection of application metrics including request counts, response times, and custom business metrics.

Health Checks: Multiple health check endpoints that verify different aspects of the application:

Request Tracing: Complete request tracing through the application stack, making it easy to identify performance bottlenecks and debug issues in production.

Worker Integration

The template seamlessly integrates background task processing with the main API application. Taskiq workers can be deployed alongside the API or separately, providing flexibility for different deployment scenarios.

The worker system includes:

Template Philosophy and Goals

This template represents practical solutions to common API development challenges. It’s designed as a starting point that can be adapted to specific project needs rather than a rigid framework that must be followed exactly.

The patterns and practices included address real problems encountered in production environments. Teams may need different authentication mechanisms or prefer different observability tools, and the modular architecture accommodates these changes.

Building software involves making tradeoffs, and this template makes opinionated choices based on production experience. The goal is providing a solid foundation that enables focus on business value rather than infrastructure concerns.

Key Insights and Lessons

Looking back at this development journey, several key insights shaped this template:

Building production-ready APIs involves creating systems that can be maintained, debugged, and extended reliably. This template captures essential practices for building robust FastAPI applications.

The template will continue to evolve based on new experiences and community feedback, incorporating improvements and lessons learned from real-world usage.

Start searching

Enter keywords to search articles

↑↓
ESC
⌘K Shortcut