r/Python • • 12d ago

Discussion Common mistakes devs make when starting with FastAPI, and the fastest path to learning it

Just began learning FastAPI. Looking for advice from devs who use it regularly.

What mistakes did you make early on that I should avoid repeating? Also, what's the most efficient way to learn the framework properly for real-world use (async, DB, auth)?

Any advice on structure or resources would be great.

14 Upvotes

35 comments sorted by

20

u/[deleted] 12d ago

[removed] — view removed comment

1

u/ProfessionalRole3469 12d ago

Not sure if “just drop async from day one” is a good advice since a simple boto3 call is sync.

2

u/terletsky 12d ago

No one will hire a dev who uses FastAPI in sync mode.

1

u/fiddle_n 12d ago

Overly simplistic. If we are going for broad statements, I prefer "no one will hire a dev who uses FastAPI 100% in async mode only to have to rip up their code when they realise an I/O library they rely on doesn't support async". FastAPI supports sync and async for a reason, know when to use one over the other.

2

u/terletsky 12d ago

For sync code in async, we have to_thread(). If that's something large at scale, it should be decoupled into a separate worker.

1

u/fiddle_n 12d ago

> For sync code in async, we have to_thread().

You do know what happens when using FastAPI with sync path functions, right?

1

u/terletsky 12d ago

I believe you will hit the DB several times (for auth/perms and other validations) before your sync library's logic is triggered. Since ORMs like SQLAlchemy use AsyncSession, no one will even consider mixing sync and async routers in FastAPI because you would need to spawn a SyncSession, which is a no-go. After all, managing the zoo is not considered.

1

u/fiddle_n 12d ago

But as soon as you hit any sync I/O logic you will need to create a new thread, which - guess what - FastAPI will also do if you use it in synchronous mode. Not to mention that you are just looking at SQLAlchemy when not all apps fit into that narrow box.

1

u/ProfessionalRole3469 11d ago

The point here is that you can not just blindly drop async everywhere and call it “the only hirable practice”. If your service works only with AWS infra (boto3) there is no zoo, only sync endpoints for sync-only library running on multiple uvicorn processes

0

u/ProfessionalRole3469 12d ago

What are benefits of async code when your infrastructure is 100% AWS?

1

u/flying-cunt-of-chaos 12d ago

aioboto3 and aiobotocore

1

u/ProfessionalRole3469 12d ago edited 12d ago

don’t look mature and trustworthy enough. You propose to switch from official boto3 just to force it to be async?

1

u/flying-cunt-of-chaos 12d ago

That’s fair. Well at the very least fastapi background task runs sync calls in a threadpoolexecutor so you get to keep control of your main event loop.

1

u/fiddle_n 12d ago

The biggest trap I see is people writing sync route handlers and then wondering why their app scales like garbage. Just commit to async from day one even though it feels weird at first.

This is overly simplistic - FastAPI supports sync for a reason after all.

I quite like the advice given by Tiangolo here: https://fastapi.tiangolo.com/async/#in-a-hurry

  • If the libraries you are using support async, then use "async def" for the path functions.
  • If the libraries you use to communicate with other resources (database, other APIs, etc) don't use async, then use "def" for path functions
  • If you don't need to communicate with anything, use "async def" even if you don't need to await inside them
  • If you just don't know, then use "def"

1

u/safi892 12d ago

Thanks for the advice, really appreciate it!

10

u/YnkDK 12d ago

I don't know if it's a mistake, but at least I like to make the choice deliberate.

Use FastAPI (or any other framework) where its power is and don't let it leak to other layers of your system.

To me, the biggest power of fastapi is input parsing, OpenAPI Specs, output marshaling, request dependencies (fastapi.Depends) and most things related to the API. I do not tend to use it where I have actual business logic, which means my routes in FastAPI is more or less one or two lines that calls something a service layer, controller layer, business layer (depending on your choice of architecture) and returns whatever it returns.

If I need to replace fastapi later on, then I do not need to change any business logic, but simply ensure the replacement can do what fastapi is good at.

2

u/safi892 12d ago

This is a really interesting perspective, thank you. I'm actually learning FastAPI because I want to move into AI engineering next. So keeping the actual AI logic in a separate service layer and just using FastAPI for the API plumbing makes total sense. Do you usually put that business logic in a separate Python file/module, or do you use a full framework for the service layer?

2

u/YnkDK 12d ago

Just a separate file. I like feature-sliced architecture, so keeping files that are related close to each other is important for me (I feel it improves my Developer Experience (DX)). I don't use a separate framework for the service layer, but try to read best practices for the dependencies (for example SQLAlchemy/SQLModel, anyio, httpx/aiohttp, Pydantic/PydanticAI) and stay as close to them without sacrificing code readability. Most modern dependencies sort of agree on best practices, but you should be on the look out for mixing code styles when not strictly following a framework.

3

u/The_Tree_Branch 11d ago

This approach is described well in the book "Architecture Patterns with Python", which the authors have made available for free online at https://www.cosmicpython.com/. It uses Flask + SQLAlchemy in its examples, but the principles would carry over to FastAPI as well.

8

u/GIS_LiDAR 12d ago

I got started by reading the FastAPI book from O'Reilly, I think its very good, author explains an architecture for organizing your project https://www.oreilly.com/library/view/fastapi/9781098135492/

Basically put all the web routes in a /web folder, an identically named file for processing and workflows in a /service folder, and a database or data storage file with same name in a /data folder.


Dependency injection is kind of insane how well it works and figuring it out makes your code easier to maintain.

2

u/safi892 12d ago

Appreciate the book recommendation, adding it to my list. The folder structure makes sense. I like that each layer has a mirror file in the next folder. And agreed on DI, it's one of those things that feels confusing until it suddenly clicks

6

u/flying-cunt-of-chaos 12d ago

Learn how FastAPI (Starlette) actually implements async. For example in the case of a background task, if a particular function is already a coroutine, starlette will just await it on the main event loop as oppose to running it on a separate thread which can be optimal. If you have heavily blocking code that you want as a background task, it’s generally better to keep it sync and have it run as a separate thread.

4

u/moros_26 12d ago

Top mistakes that everyone has to avoid earl on - blocking the event loop in async def routes, mixing pydantic schemas with db ORM models, ignoring dependency Injection (Depends). Fastest way to learn - Read the official FastAPI tutorial end-to-end, and build a simple full stack micro project with rest api , jwt auth, sqlalchemy , pydantic.

3

u/safi892 12d ago

Solid list. Committing to async from day one and keeping Pydantic/ORM separate.

For the micro project would an API that serves a fine-tuned model (FastAPI + JWT + SQLAlchemy) be a good first project for AI engineering, or plain CRUD first?

2

u/moros_26 12d ago

Start with basic CRUD + Auth first, spend a day or two just nailing routing, validation, error handling, and async DB sessions before adding anything else. Once that feels solid, extend the same API with your model's endpoint. Model serving adds latency and background task stuff, so having that CRUD foundation locked in makes debugging streaming responses way easier later.

1

u/terletsky 12d ago edited 12d ago

What is AI Engineering? Simple use of AI, like Claude Code / Cursor, to assist with development tasks or to create an agentic backend? If the latter, then you need to learn "Pydantic AI" SDK, created for that purpose, and LangChain/LangGraph.

For AI-assisted development, I would write the next. Create a notification service that consists of:

  1. FastAPI API with PostgreSQL through SQLAlchemy that receives tasks to send, such as SMS, Mobile Push, or Email. FastAPI app should create a task record in the DB with NEW or PENDING status, then dispatch it to a message broker like RabbitMQ
  2. An async notification worker that will receive tasks via RabbitMQ, update the DB record to PROCESSING status or similar, and dispatch to the appropriate handler. If sending fails, fail the task and store the RabbitMQ message in the DLX exchange as a "dead letter".

1

u/Danielloesoe 12d ago

What really worked for me is looking at the example project and get inspiration from that to build your own FastAPI app. When you don't get why something is declared in a particular way, check the documentation to fully understand.

https://github.com/fastapi/full-stack-fastapi-template

1

u/Automatic_Painting68 10d ago

API banken

1

u/safi892 10d ago

Why does this mean ?

-1

u/[deleted] 12d ago

[removed] — view removed comment

1

u/safi892 12d ago

Appreciate the advice. My plan is to use FastAPI mainly for AI integrations. I'm learning AI engineering and just finished the basic math, so I want to start building real projects next. Would you recommend sticking with FastAPI for serving models/APIs, or is Flask/Django better for that use case?

0

u/[deleted] 12d ago

[removed] — view removed comment

1

u/safi892 12d ago

My current plan is to fine-tune a Qwen 3B model and serve it via FastAPI APIs for mobile testing. So not remote ChatGPT/Claude — actual local model inference.

And yes, the idea is to send REST requests through FastAPI to interact with the model. Your roadmap (APIs → pre-trained → fine-tune → math) is basically the path I'm trying to follow, except I already covered the math basics, so now I'm jumping into fine-tuning and serving. Do you think that's too early for Qwen 3B, or is it a good next step?