Describe a common FastAPI project structure and key directories

Scaling past one file with APIRouter and domain separation.
Main module holds the FastAPI app; domain files (users, items) expose APIRouters; dependencies in their own module; pyproject.toml as entrypoint.
WHAT THIS TESTS: The interviewer wants to know if you have built a FastAPI application large enough to require multiple files. They are checking whether you understand APIRouter as the primary mechanism for splitting endpoints by domain, how to avoid circular imports, and where to centralize shared concerns like dependencies. This question separates candidates who have only run tutorial-sized single-file examples from those who have shipped maintainable services. It also reveals whether you know how to wire modules together cleanly without creating tight coupling.
A GOOD ANSWER COVERS: First, a main module that instantiates the core FastAPI application and registers routers with app.include_router. Second, domain-specific modules such as users and items that each define an APIRouter and attach their own path operations, tags, and prefixes. Third, a separate dependencies module for reusable dependencies that are imported relatively into router modules rather than being defined inline everywhere. Fourth, configuring the entrypoint in pyproject.toml so the application can be started cleanly without memorizing long uvicorn paths. Fifth, using relative imports to avoid name collisions and tight coupling between modules, and explaining why the main app should import routers rather than the reverse.
COMMON WRONG ANSWERS: Putting every endpoint in a single main.py file and claiming it is fine for all sizes. Creating APIRouter instances but not explaining how they are included in the main app or what prefixes they carry. Inventing complex nested directory hierarchies that are not justified by the actual imports and only add navigation friction. Suggesting circular imports between router modules and the main app, such as routers importing the main FastAPI instance. Ignoring pyproject.toml and relying only on manual uvicorn commands without a configured entrypoint. Proposing a structure where business logic is mixed directly into path operation functions with no separation.
LIKELY FOLLOW-UPS: How would you handle database sessions or ORM models across these modules without creating import cycles? Where do you put shared Pydantic schemas when multiple routers need to reference them? How do you test individual routers in isolation without spinning up the full application? What happens if two APIRouters define the same path operation name, and how does that affect OpenAPI generation? How would you apply global dependencies versus router-specific dependencies?
ONE CONCRETE EXAMPLE: Imagine an app with three core files. main.py creates app = FastAPI() and calls app.include_router(users.router, prefix="/users", tags=["users"]) and app.include_router(items.router, prefix="/items", tags=["items"]). users.py defines router = APIRouter() and adds GET and POST path operations for user management. items.py does the same for inventory endpoints. dependencies.py holds a get_current_user function that both router modules import using relative imports. The pyproject.toml specifies the entrypoint so running the app uses the correct module path. This keeps each file focused and avoids a single massive module.
Read the original → fastapi.tiangolo.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.