Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 02.01: Running it, and what the reload flag costs

How you run it differs between development and production, and one of the differences has a design consequence.

Reload, workers, and shared state

Three commands with what each is for.

The code lists them.

COMMANDS = [
    ("uvicorn app.main:app --reload",
     "development", "restarts on file change; do not use in production"),
    ("uvicorn app.main:app --host 0.0.0.0 --port 8000",
     "production-ish", "one worker, no reload"),
    ("uvicorn app.main:app --workers 4",
     "production", "four processes; no shared in-memory state"),
]
print(f"{'command':52} {'for':16} note")
for command, use, note in COMMANDS:
    print(f"{command:52} {use:16} {note}")

print("""
`--reload` watches the filesystem and restarts the process. That costs
noticeable CPU and, more importantly, it restarts on any change -- including
a half-saved file, which produces confusing errors.

`--workers 4` is the one with a design consequence: four processes means any
in-memory cache, counter or rate limiter exists four times.
""")

--reload watches the filesystem and restarts on any change - including a half-saved file, which produces errors that look like bugs and are not. It costs noticeable CPU and has no place in production.

--workers 4 is the one that changes your design. Four processes means any in-memory cache, counter or rate limiter exists four times, and a restart forgets all four.

The mistake this prevents

The mistake is testing with one worker and deploying with several. Every in-process state bug is invisible until then, and the symptom - a rate limit that allows four times what it should - looks like a logic error rather than a deployment one.

Takeaway

Never use --reload in production, and remember that multiple workers mean multiple copies of anything held in memory.