Feature-based vs layer-based project structure
Structuring code for scale.
layer-based groups by technical role and is simple early but scatters a feature across folders; feature-based groups by domain, improving cohesion and ownership at the cost of some duplication and…
WHAT THIS TESTS Whether you reason about maintainability trade-offs at scale rather than dogmatically favoring one folder layout. It probes judgment about cohesion, coupling, and team workflow.
A GOOD ANSWER COVERS Layer-based structure groups code by technical role: all routers in routers/, all Pydantic schemas in models/, all business logic in services/. Pros: immediately familiar, low ceremony, and fine for small or early projects. Cons: as the project grows, working on one feature means jumping across many folders, related code is far apart so cohesion drops, and the folders become large and unfocused. Feature-based or vertical-slice structure groups by domain: a users package containing its own router, schemas, service, and tests, likewise for orders, billing, and so on. Pros: high cohesion since everything for a feature sits together, easier navigation and onboarding, clear team ownership boundaries, and changes stay localized, which suits a large or multi-team codebase. Cons: you must decide where genuinely shared code lives (a common or core package), there can be some duplication, and cross-feature concerns need conventions. The honest answer is that small apps do fine layer-based, while large, domain-rich, multi-team apps usually benefit from feature slices, possibly with a shared core.
COMMON WRONG ANSWERS Declaring one structure always best without context. Ignoring team ownership and navigation costs. Claiming feature-based has no downsides, overlooking shared-code placement and duplication. Conflating folder structure with architectural layering itself.
LIKELY FOLLOW-UPS Where do shared schemas and utilities go in a feature-based layout? How does this affect APIRouter composition? How would you migrate an existing layer-based project incrementally?
ONE CONCRETE EXAMPLE In layer-based, adding a field to users touches models/user.py, services/user_service.py, and routers/users.py in three separate trees. In feature-based, the same change stays within app/users/, which holds router.py, schemas.py, service.py, and tests, so one cohesive folder changes and another team's billing/ slice is untouched.
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.