# FastAPI-Template: an admin backend template with RBAC and audit built in

> FastAPI-Template is a Python project template for a FastAPI service that ships the parts an internal admin backend always needs, JWT login with refresh, role and menu and API permissions, audit logs, file upload, an arq queue, Prometheus metrics and Docker Compose. It suits a team starting an admin API and wanting the plumbing already in place, and it is deliberately not a minimal example.

**JiayuXu0/FastAPI-Template** — A production-ready FastAPI backend template with clean architecture. 一个功能完整、架构清晰的企业级FastAPI后端模板，专为团队开发设计，开箱即用。

- Repository: https://github.com/JiayuXu0/FastAPI-Template
- Website: https://jiayuxu0.github.io/FastAPI-Template/
- Stars: 529 · Forks: 78
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/jiayuxu0-fastapi-template

## What the template ships and who it is for

FastAPI-Template is described as a production-ready FastAPI backend template with clean architecture, and the readme summarises it as five minutes to an enterprise FastAPI backend with authentication, RBAC, audit, files, queues, Docker and CI all in place.

The readme is unusually direct about who should not use it, with a table of suitable and unsuitable cases. It is for enterprise backends and admin APIs, for SaaS and multi-team permission systems, for internal tools, operations platforms and admin backends, for services that need permissions, audit, files and a task queue, and for people learning FastAPI layered architecture and engineering practice. It is not for a minimal single-file demo, not for a full React or Vue front end template, not for a microservice platform with the whole toolchain, not for a stateless HTTP forwarding layer, and not for people who want to hand-write every basic module from scratch.

That last exclusion is the useful one, because it tells you the intended user. The template assumes you want the standard admin modules rather than a minimal service.

The second table makes the same point in terms of what is included. A background API base you can start business on, with users, roles, menus, API permissions, departments, files and audit logs. A clearly structured FastAPI sample with API, Service, Repository and Model separation. A template with production infrastructure, listing Redis, PostgreSQL, Docker, Prometheus, Sentry and an arq worker. And a starting point suitable for long-term team maintenance, with uv, ruff, pytest, coverage, GitHub Actions and layered configuration.

The stack badges give the version floors: Python 3.11 or newer and FastAPI 0.100 or newer, with a CI badge, an MIT badge, and an English readme alongside the Chinese one.

One detail in the package metadata is worth noting before you install. The project name in pyproject.toml is evoai-backend-template, the author is the EvoAI Team, and the description calls it an enterprise FastAPI backend template with a ready-to-use three-layer architecture. The repository and the package are therefore named differently, which is a minor trap if you publish the result or depend on it by name.

## Running it in five minutes

The quick start is a short sequence, and the tooling choice is uv rather than pip and poetry.

```bash
git clone https://github.com/JiayuXu0/FastAPI-Template.git
cd FastAPI-Template
uv sync
cp .env.example .env
uv run aerich init-db
uv run uvicorn src:app --reload --host 0.0.0.0 --port 8000
```

Six commands: clone, install the locked dependencies, copy the environment template, initialise the database with Aerich, and start the server. The default database engine in the .env example is sqlite, so the first run needs no database server at all, which is why the quick start works this quickly.

Then there is a second route, a scaffolding tool that creates a new project with a different name so you do not have to edit the template metadata:

```bash
npx create-fastapi-app@latest my-backend
cd my-backend
uv run uvicorn src:app --reload --host 0.0.0.0 --port 8000
```

The readme points at a separate create-fastapi-app repository for that tool.

The default credentials are documented in the readme and in the .env example, admin with the password abcd1234, and the readme attaches an important note to them: change the default password after the first start, and in production replace SECRET_KEY, SWAGGER_UI_PASSWORD and the database password. That is a reasonable instruction, but it is worth knowing that the shipped default is a trivially guessable one and that the SECRET_KEY in the example is a placeholder rather than a random value.

The exposed endpoints are listed in a table: Swagger UI at /docs, ReDoc at /redoc, a health endpoint at /api/v1/base/health, a version endpoint at /api/v1/base/version and a metrics endpoint at /api/v1/base/metrics.

## The Docker Compose stack and how the services split

The compose file starts four services and the dependency ordering between them is done properly, which is more than most templates manage.

The postgres service runs postgres:15-alpine with the database name, user and password taken from the environment with defaults, a named volume for the data directory and port 5432 published. Its healthcheck uses pg_isready against the configured user on a five second interval with three retries. The redis service is redis:7-alpine started with --appendonly yes, a named volume, port 6379 published and a healthcheck that runs redis-cli ping.

The web service builds from the Dockerfile, runs the docker-entrypoint.sh script, reads the .env file and overrides the database host, the database port, the Redis URL and the arq Redis database number. Its depends_on entries use the condition service_healthy for both postgres and redis, which means the web container waits for the health checks to pass rather than merely for the containers to exist. That is the difference between a Compose stack that starts reliably and one that races.

The worker service builds from the same image and runs the arq worker through its settings module, with PYTHONPATH set to /app/src and the same Redis and database environment. It has its own healthcheck that runs arq with a --check flag against the worker settings, so the queue worker is verified rather than assumed.

The Dockerfile itself is a Python 3.11 slim image with the working directory at /app, PYTHONDONTWRITEBYTECODE and PYTHONUNBUFFERED set and the timezone set to Asia/Shanghai. It installs gcc, g++, libpq-dev and curl, installs the project with pip, creates an app group and user, chowns the app and scripts directories, switches to that user with USER app and exposes port 8000.

Two choices in there are worth flagging. The Dockerfile rewrites the Debian apt sources to a mirror, and pip installs from a mirror index, both aimed at speeding up builds. And the healthcheck deliberately calls the business health endpoint rather than /docs, with a comment explaining that /docs is behind Basic Auth and would return 401 and be misread as unhealthy. That is the kind of detail that usually only appears after someone spent an afternoon on it.

## The three-layer convention and the module inventory

The architecture is drawn as a flowchart and then reduced to five rules, and the rules are the useful part for anyone extending the template.

The flow runs client to API layer in src/api/v1, to the service layer in src/services, to the repository layer in src/repositories, to the model layer in src/models, and then to SQLite or PostgreSQL. The API layer also connects to the auth and permission machinery built on JWT and RBAC and to the Prometheus metrics, and the service layer connects to the Redis cache and to the arq task queue, which feeds a worker process that also writes to the database.

The five conventions follow that structure. Routes stay thin and only handle parameters, dependencies and responses. Business logic goes in the service layer, where permission checks, validation and orchestration live. Data access goes through repositories, so ORM queries are not scattered through the service code. Models only describe data structures, with the Tortoise models separated from the Pydantic schemas. And all I/O is async-first, with the database, the cache and the task queue all using asynchronous interfaces.

The directory tree in the readme shows the same split in code: src/api/v1 with users, roles, menus and tasks subpackages for the routes, src/services for business logic, src/repositories for data access, src/models for the Tortoise ORM models, src/schemas for the Pydantic schemas, src/core for middlewares, metrics and dependencies, src/tasks for the arq worker, queue and jobs, src/utils for cache, JWT, password and helpers, src/settings for runtime configuration, plus migrations/ for the Aerich migrations and tests/.

The module inventory in the feature matrix maps onto that tree with an API prefix for each: users at /api/v1/users with create, update, delete, query and password reset, roles at /api/v1/role with role CRUD and menu and API authorisation, menus at /api/v1/menu for multi-level menu configuration, API permissions at /api/v1/api for syncing and managing the API permission table, departments at /api/v1/dept for organisation structure, files at /api/v1/files for secure upload and file mapping, audit logs at /api/v1/auditlog for request behaviour records, and task status queries at /api/v1/tasks for arq jobs.

The engineering stack table names the choices: Tortoise ORM as the async-first data access layer, Aerich for versioned migrations, Redis for caching with TTL, null protection, jitter and permission cache invalidation, prometheus-client for the metrics endpoint, Sentry enabled through SENTRY_DSN, arq for Redis-backed async jobs, Loguru for JSON structured logging with a request id, and GitHub Actions running lint, format, pytest, coverage and a security scan.

## Authentication, rate limiting and the config layer

The authentication section of the feature matrix lists six items and marks them all as done, and two of them are the ones that usually get skipped in a template.

JWT login with an access token and a refresh token. Login rate limiting at 5 attempts per minute by default. Refresh token rate limiting at 10 per minute by default. RBAC modelled as user to role to API or menu. A superuser dependency named SuperUserRequired. And API documentation protection, with Basic Auth on Swagger and ReDoc.

The rate limits are enforced with slowapi, which is in the dependency list, and the dependency list also carries PyJWT for the tokens, pydantic-settings for configuration, passlib with bcrypt and argon2-cffi for password hashing, and httpx for outbound calls. Having two password hashing backends listed is a slight oddity, since normally you pick one, but it does mean the template will work with whichever you configure.

The .env.example file is a good description of the configuration layer, and it is grouped by concern. Python path configuration with PYTHONPATH=src. Application configuration with a version, a title, a project name and a description. Security configuration marked as must-change, with SECRET_KEY, SWAGGER_UI_USERNAME and SWAGGER_UI_PASSWORD. Application configuration with an environment, the JWT algorithm HS256 and a 240 minute access token expiry. Database configuration with the engine defaulting to sqlite and a host, port, user, password and name. CORS origins given as a comma-separated list of localhost and 127.0.0.1 on ports 3000 and 8080. A debug flag. Redis cache settings with a URL and a 300 second TTL. Observability settings including the metrics endpoint IP allowlist, which defaults to loopback and the private ranges. Sentry with a DSN and a 0.1 trace sample rate. And the arq queue settings, with a separate Redis database number, a queue name, a maximum job count of 10, a 300 second job timeout and a 3600 second result retention.

The separate Redis database for the queue, with ARQ_REDIS_DB=1 against the cache on database 0, is a small decision that avoids the queue and the cache flushing each other's keys, and the comment in the file says so.

## Where FastAPI-Template is the wrong choice

The first limitation is that it is a starting point with opinions baked in, and the opinions are numerous. Three-layer separation, Tortoise ORM, Aerich, arq, Loguru, Prometheus, Sentry, Redis caching with permission cache invalidation, a user-role-menu-API permission model, a departments table and an audit log table. Every one of those is a reasonable choice and every one of them is a decision you are now committed to, because the module structure, the dependency list and the schema all assume them. Teams who want SQLAlchemy, or Celery, or a different authorisation model, will be rewriting rather than adapting.

The second is the sheer size relative to many real needs. The readme's own unsuitable list includes a simple file demo and a stateless HTTP forwarding layer, and the usual case of a small service or a microservice sits in the same region. The dependency list is twenty packages and the compose stack is four services, so the smallest useful deployment of this template is a web container, a worker container, Redis and PostgreSQL. That is a real operational cost for a small service.

The third is the default credentials and the default key material. The shipped admin password is abcd1234 and the SECRET_KEY placeholder says to generate one with openssl rand hex 32. A template with a documented default password is normal and the readme warns about it, but a team that clones and deploys without reading that note has an admin account with a password that is in a public repository.

The fourth is the release state. The last push was on 2026-05-07, the repository publishes no GitHub releases, and the pyproject version is 1.0.0 while the repository records no tagged release history. The CHANGELOG.md is in the repository, but a template with no releases means no upgrade path between versions and no way to tell which template state a running deployment came from.

The fifth is the front end. The readme says outright that this is not for people who need a complete React or Vue front end template, so what you get is a backend with Swagger and ReDoc and the menu and permission tables that a front end would consume. That is a coherent choice, but it means the menu data model is the contract with a UI you have to write.

## Conclusion

FastAPI-Template fits a team that is about to build an internal admin or SaaS API and would rather start with users, roles, menus, API permissions, departments, files and audit logs already working than write them, since the layering convention is documented and the operational pieces, Redis caching, Prometheus, Sentry, structured logs and a Compose stack, are assembled. It is the wrong choice if you want a small service, since the readme itself lists a simple file demo and a stateless HTTP proxy as cases it does not suit, and it is the wrong choice if you want the React or Vue front end it also does not include. Before adopting it, read the security checklist, change the default admin password and the SECRET_KEY, SWAGGER_UI_PASSWORD and database password as the readme instructs, and note that the last push was on 2026-05-07 with no GitHub releases published.

## FAQ

### How do I run the FastAPI-Template project locally?

Clone the repository, run uv sync, copy .env.example to .env, run uv run aerich init-db to create the database, and start the server with uv run uvicorn src:app --reload --host 0.0.0.0 --port 8000. The default database engine in the environment example is sqlite, so no database server is needed for a first run.

### What admin modules does FastAPI-Template include out of the box?

User management at /api/v1/users, roles at /api/v1/role with menu and API authorisation, menus at /api/v1/menu, API permissions at /api/v1/api, departments at /api/v1/dept, files at /api/v1/files, audit logs at /api/v1/auditlog and arq task status queries at /api/v1/tasks.

### What is the layering convention in FastAPI-Template?

Routes stay thin and handle only parameters, dependencies and responses, business logic goes in the service layer, data access goes through repositories, models only describe data structures with Tortoise models separated from Pydantic schemas, and all I/O including the database, cache and task queue uses asynchronous interfaces.

### Which services does the FastAPI-Template Docker Compose stack start?

Four: web, the FastAPI application; postgres, for PostgreSQL; redis, for the cache and the arq queue; and worker, the arq background task worker. The web and worker services wait on service_healthy conditions for both postgres and redis before starting.

### What licence is FastAPI-Template released under?

MIT, as declared in the pyproject.toml with the LICENSE file at the repository root. The last push to the repository was on 2026-05-07 and the repository publishes no GitHub releases, though the package metadata records the project as evoai-backend-template at version 1.0.0.

## Sources

- [Issues](https://github.com/JiayuXu0/FastAPI-Template/issues)
- [JiayuXu0/FastAPI-Template on GitHub](https://github.com/JiayuXu0/FastAPI-Template)
- [License: MIT](https://github.com/JiayuXu0/FastAPI-Template/blob/main/LICENSE)
- [Project website](https://jiayuxu0.github.io/FastAPI-Template/)
- [README](https://github.com/JiayuXu0/FastAPI-Template/blob/main/README.md)

---

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