tezvyn:

How do you dynamically discover and register FastAPI routers from a directory?

AI-drafted, machine-checkedSource: github.comadvanced
WHAT IT TESTS

You can safely register FastAPI routers via dynamic imports.

ANSWER OUTLINE

Scan app/routers/ with importlib, validate APIRouter objects, include_router with prefixes, and isolate failures.

WHAT THIS TESTS: This question probes your ability to build self-registering plugin architectures in Python, specifically using importlib to discover and bind FastAPI APIRouter instances at runtime. Interviewers want to see that you understand the difference between static imports and dynamic loading, that you can defend against import side effects, and that you think about operational consequences like startup latency, exception isolation, and deterministic route ordering. It also surfaces whether you treat Python modules as data or as executable code.

A GOOD ANSWER COVERS: First, a directory scanning strategy using importlib.util or pkgutil.iter_modules to list candidate files without executing them. Second, a validation layer that imports each module safely and checks for an APIRouter instance or a well-known factory function before calling app.include_router. Third, explicit metadata handling such as per-router tags, prefixes, or dependencies passed during registration rather than hardcoded inside each router. Fourth, error isolation via try/except around individual imports so one broken router does not crash the entire application. Fifth, a discussion of startup cost because dynamic discovery happens at import time and can delay cold starts in serverless or container environments.

COMMON WRONG ANSWERS: Using eval or exec on filenames to construct import statements is a security and maintainability red flag. Hardcoding a manual import list inside a loop defeats the purpose of dynamic discovery. Ignoring import side effects means a rogue router module could run top-level code that mutates global state or opens connections during scan. Failing to handle ModuleNotFoundError or AttributeError implies you have not operated this pattern in production. Another trap is assuming file order equals route precedence without explicit sorting.

LIKELY FOLLOW-UPS: How would you preserve route ordering if the file system order is non-deterministic? What happens if two routers define conflicting path operations? How would you lazy-load routers to improve startup time? Would you expose a health check that lists discovered routes? How do you test this discovery logic without relying on the real file system?

ONE CONCRETE EXAMPLE: Imagine an app/routers/ directory containing users.py and orders.py. In main.py you define a load_routes function that walks the directory with pkgutil.iter_modules, imports each module with importlib.import_module, checks for a router attribute of type APIRouter, then calls app.include_router(router, prefix="/v1", tags=[module_name]). You wrap each import in a try/except block that logs the failure and continues. You also maintain an explicit __all__ or registry dictionary so only blessed modules are mounted, preventing accidental inclusion of utility scripts. This pattern mirrors the load_routes approach seen in production FastAPI templates.

Read the original → github.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.