# FastAPI Best Architecture: a three-tier FastAPI backend template with Celery, Casbin and Grafana

> FBA is an MIT-licensed FastAPI project skeleton that maps a Java-style three-tier layout onto an api / schema / service / crud / model directory tree, and ships Docker Compose with Postgres, Redis, Celery, Loki, Prometheus and Tempo. It is a template to fork, not a library to install.

**fastapi-practices/fastapi-best-architecture** — Enterprise-level backend architecture solution with fastapi、sqlalchemy,、celery、pydantic、grafana、docker...

- Repository: https://github.com/fastapi-practices/fastapi-best-architecture
- Website: https://docs.fba.wu-clan.cc
- Stars: 2,571 · Forks: 389
- Language: Python
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/fastapi-practices-fastapi-best-architecture

## The problem FBA solves: FastAPI gives you a router, not a backend layout

FastAPI ships routing, dependency injection and validation. It does not ship a place to put business logic, a migration story, a permission model or a task queue. Every team starting a real service rebuilds those decisions, and the rebuild is usually invisible until the third developer joins and puts a database query inside a route handler.

FastAPI Best Architecture (FBA) is that set of decisions already made. The README frames it as an enterprise-level backend architecture solution, and the repository is a full application skeleton rather than a package. The README is explicit about the intended shape: the project does not use a traditional multi-app or microservice directory structure like Django or Spring Boot, but what the README calls a self-righteous directory structure that you can give any twist if you do not like the model.

The audience is a team that has already chosen FastAPI and now needs conventions for authorisation, background jobs, migrations and metrics. It is a poor fit for a script with four endpoints, and the README does not pretend otherwise.

## The three-tier layout and how a request moves through it

The README includes a mapping table between a Java-style stack and this project. The view layer is api, the data transfer objects are schema, business logic is service, data access is crud, and the persistence model is model. That is the whole organising idea, and it is worth checking against your own habits before you clone anything.

A request therefore enters through an api module, is validated and shaped by a Pydantic v2 schema, is passed to a service that holds the logic, and reaches the database through a crud module built on SQLAlchemy 2.0. The dependency list shows sqlalchemy-crud-plus alongside sqlalchemy[asyncio], so the crud layer is not hand-rolled. Alembic is a direct dependency, which means schema changes are expected to go through migrations rather than create_all.

Two choices stand out. First, the tier boundaries are enforced by convention and directory placement, not by an import linter, so nothing stops a service from importing a model directly. Second, the project uses Casbin for authorisation, which puts policy in a model-and-policy pair rather than in FastAPI dependencies. Both are structural commitments that are annoying to reverse later.

## Installing FBA with uv and running the API on port 8001

The repository carries a pyproject.toml, a uv.lock and a generated requirements.txt whose header states it was produced with uv export -o requirements.txt --no-hashes. Python 3.10 or newer is required. The Dockerfile builds from ghcr.io/astral-sh/uv:python3.10-trixie-slim, so uv is the expected toolchain rather than pip.

The Docker path is the one the repository documents end to end. The compose file defines a bridge network named fba_network on 172.10.10.0/24 and a server service that publishes port 8001, defaulting to 8001 on the host through DOCKER_MAP_SERVER_PORT. The fba_server service is built from the Dockerfile at the repository root:

```dockerfile
FROM base_server AS fba_server

COPY deploy/backend/supervisor/fba_server.conf /etc/supervisor/conf.d/

RUN mkdir -p /var/log/fba

EXPOSE 8001
```

That is the tail of the Dockerfile in the repository. The container waits on two dependencies before starting: the compose command runs wait-for-it against fba_postgres:5432 and fba_redis:6379 with a 300 second timeout, then hands control to supervisord. If the API is not answering, the first thing to check is whether those two hostnames resolved and accepted connections, not the FastAPI code. The compose file mounts deploy/backend/docker-compose/.env.server into /fba/backend/.env, so that file is where the application reads its settings.

## Switching to MySQL is a find-and-replace, and the compose file says so

The compose file is written for PostgreSQL 16 by default and carries inline comments for MySQL users. The comments name the exact edits: change the volume fba_postgres to fba_mysql, change the depends_on entry fba_postgres to fba_mysql, and change the wait-for-it target from fba_postgres:5432 to fba_mysql:3306.

The dependency list supports both paths. asyncpg and psycopg[binary] cover Postgres, asyncmy and pymysql cover MySQL. Note the pin on psycopg[binary]==3.2.10 in pyproject.toml, which is tied to a specific issue number in the project's tracker. That pin is a signal: the Postgres driver version is not free to float, and an upgrade there deserves a test run rather than a bump.

What the compose file does not do is give you a migration path between the two databases. Choosing Postgres and later moving to MySQL means re-running Alembic against a new engine, and the README is silent on that. Pick one at the start.

## Celery, Flower and the observability stack you inherit

Background work is not optional here. Celery 5.6.3 is a direct dependency, flower ships alongside it for task inspection, and celery-aio-pool is present with a comment in pyproject.toml pointing at a Celery issue for versions below 6.0.0. The compose file also declares volumes for RabbitMQ, Loki, Prometheus and Tempo, so the intended deployment includes a broker and a metrics and tracing pipeline rather than a single process.

The OpenTelemetry instrumentation list is long and specific: asyncio, celery, fastapi, httpx, logging, redis and sqlalchemy are all instrumented, with an OTLP gRPC exporter. Prometheus client and psutil are there for metrics. That is a real advantage over a bare template, because wiring tracing into Celery and Redis after the fact is tedious.

It is also the biggest cost. A developer who wants to add one endpoint now has to understand why Tempo and Loki exist in the compose file. If your team has no collector to send OTLP data to, this instrumentation is dead weight until you add one, and the README does not describe what to disable.

## A real alternative, and the actual difference in approach

The obvious comparison is the official full-stack FastAPI template. That project is generated with cookiecutter, and its structure is deliberately smaller: it separates backend and frontend, uses SQLModel for the data layer, and leaves authorisation, task queues and tracing out of the box. FBA instead commits to SQLAlchemy 2.0 with a separate crud tier, Casbin for policy, Celery for jobs, and a bundled observability stack.

The difference is not quality, it is where the complexity lives. The cookiecutter template makes you add each of those pieces yourself and therefore makes you understand each one. FBA hands you a working arrangement of them and asks you to accept its opinions, including the api / schema / service / crud / model split and the supervisor-managed container. If you disagree with the layering, you are editing a template, not configuring a generator.

For a team that already knows it wants Celery and Casbin, FBA saves weeks. For a team that is still deciding, the smaller template is the better starting point because deleting a layer is easier than agreeing on one.

## Maintenance, licence and what an upgrade actually costs

The repository is not archived and the last push was on 2026-09-20. Releases are frequent and versioned: v1.15.1 on 2026-08-16, v1.15.0 on 2026-07-10, v1.14.0 on 2026-05-30. A CHANGELOG.md sits at the repository root, and the version cadence suggests reading it before pulling.

Upgrade cost is higher than for a library because you forked the whole tree. There is no package to bump. The practical route is to track the upstream repository and diff, and the CHANGELOG is the starting point for that. The Dockerfile adds a wrinkle: it runs a step that imports backend.plugin.requirements and calls install_requirements, meaning the container installs plugin dependencies at build time. Anything you add under backend/plugin can change what ends up in the image, so the image is not fully described by pyproject.toml alone.

The licence is MIT, stated in pyproject.toml as license = { text = "MIT" } and in the README. MIT permits commercial use and modification with the copyright notice retained; it does not grant trademark rights, and this article is not legal advice. If you redistribute the template, check the notices for the bundled dependencies, several of which carry their own licences.

## Conclusion

Adopt it if you want a FastAPI project structure already divided into api, schema, service, crud and model layers, with Celery, Casbin, Alembic and an observability stack wired in, and you accept Postgres 16 or MySQL 8 as the datastore. Do not adopt it if you want a small single-file service, a microservice-per-app layout, or a dependency set you can audit in one sitting. Before committing, read backend/plugin/requirements.py to see which plugins the Docker build installs, check whether the bundled deploy/backend/docker-compose/.env.server credentials are acceptable for your environment, and confirm that the supervisor-based container model matches how you deploy.

## FAQ

### What is the recommended architecture for FastAPI projects in FastAPI Best Architecture?

The project uses a three-tier layout that the README maps to Java conventions: api for the view layer, schema for data transfer, service for business logic, crud for data access and model for persistence. The README notes it deliberately avoids a traditional multi-app or microservice directory structure.

### What is the best folder structure for FastAPI development according to this project?

FBA organises code under a backend directory by layer rather than by feature, with separate modules for api, schema, service, crud and model. Plugins live under backend/plugin, where backend/plugin/requirements.py controls extra dependencies installed during the Docker build.

### Does FastAPI Best Architecture support MySQL as well as PostgreSQL?

Yes. The compose file defaults to postgres:16 and carries inline comments telling MySQL users to change the volume fba_postgres to fba_mysql, update depends_on, and change the wait-for-it target from fba_postgres:5432 to fba_mysql:3306. The dependency list includes asyncmy and pymysql alongside asyncpg and psycopg.

### What Python version and package manager does FastAPI Best Architecture require?

pyproject.toml sets requires-python to >=3.10, and the Dockerfile builds from ghcr.io/astral-sh/uv:python3.10-trixie-slim. The repository ships a uv.lock and a requirements.txt generated with uv export, so uv is the expected toolchain.

### How does FastAPI Best Architecture handle background tasks?

Celery is a direct dependency, with flower for task inspection and celery-aio-pool for asyncio support. The compose file also declares a RabbitMQ volume, and the OpenTelemetry instrumentation list includes opentelemetry-instrumentation-celery.

### What licence does FastAPI Best Architecture use?

The project is MIT licensed, stated in both pyproject.toml and the README. That permits commercial use and modification provided the copyright notice is retained.

## Sources

- [fastapi-practices/fastapi-best-architecture on GitHub](https://github.com/fastapi-practices/fastapi-best-architecture)
- [License: MIT](https://github.com/fastapi-practices/fastapi-best-architecture/blob/master/LICENSE)
- [Project website](https://docs.fba.wu-clan.cc)
- [README](https://github.com/fastapi-practices/fastapi-best-architecture/blob/master/README.md)
- [Releases](https://github.com/fastapi-practices/fastapi-best-architecture/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fastapi-practices-fastapi-best-architecture
