Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 15.01: Building it in layers

The structure follows the layering, and four rules keep it honest.

Seven files, four constraints

Each file with its role, and the rules that hold the boundaries.

The code lists both.

STRUCTURE = {
    "app/main.py":              "creates the app, includes the router",
    "app/routers/classify.py":  "validates, calls the service, shapes errors",
    "app/services/classify.py": "pre-checks, calls the client, validates output",
    "app/clients/model.py":     "the only file that knows the provider",
    "app/models.py":            "request and response contracts",
    "app/settings.py":          "typed configuration",
    "app/dependencies.py":      "api key, settings, classifier",
}
for path, role in STRUCTURE.items():
    print(f"{path:28} {role}")

RULES = ["services/ imports no FastAPI",
         "clients/ is the only place the provider appears",
         "routers/ contains no business rules",
         "settings are read once, injected everywhere"]
print()
for rule in RULES:
    print(f"  rule: {rule}")

The rules are the part that decays without attention. "Services import no FastAPI" and "clients is the only place the provider appears" are both one-line checks a linter can enforce, and both erode the first time someone is in a hurry.

Writing them next to the structure makes them reviewable, which is the minimum needed for them to survive.

The mistake this prevents

The mistake is describing the structure and not the rules. A directory listing tells a new developer where files go and nothing about what may import what - which is the part that actually keeps the layers separate.

Takeaway

State the import rules alongside the directory layout. The structure is obvious; the constraints are what preserve it.