Why we pick FastAPI for SMB backends
Why FastAPI is our default Python backend for SMBs — speed, typing, OpenAPI, and a small operations footprint.
We are not religious about it
We use Django for content-heavy CRUD apps. We use Node when the client's team already runs Node. For everything in between — APIs, integrations, automation, data services — FastAPI is our default.
Why FastAPI over Flask
Flask is fine. We have shipped a lot of Flask. FastAPI gives us three things Flask does not:
- Pydantic-based validation out of the box — bad input is rejected at the boundary, not in business logic
- Automatic OpenAPI docs that we hand to the client's frontend team
- Async support that actually matches the runtime model for I/O-heavy code
For an integration backend that talks to five SaaS APIs, async is not a nice-to-have. It cuts response times by 60–80% on multi-source endpoints.
Why FastAPI over Django REST
Django REST is the right tool when the app is fundamentally a CRUD admin with users, sessions, and a database. The admin alone is worth two months of engineering.
FastAPI is the right tool when the app is fundamentally an integration or automation layer. You do not need the Django admin, you do not need the ORM, you do not need templates. Carrying them costs memory and startup time.
Why FastAPI over Node
Honest answer: client preference and team skill. Node is faster for some workloads. Python wins for anything touching data — pandas, scikit, the entire ML ecosystem, and a saner standard library for date math and CSVs.
Most SMB backends touch data. So we pick Python.
The stack we ship
- FastAPI for the HTTP layer
- Pydantic for input/output models
- SQLAlchemy + Alembic for Postgres
- Celery + Redis for background jobs
- Sentry for error tracking
- Docker for deployment
This is boring. It is supposed to be boring. Boring backends do not wake you up at night.
What we will not use
We will not put a SaaS backend on serverless-only platforms (cold starts kill webhook reliability), and we will not run Celery without a Postgres or Redis the client owns. Vendor lock-in on the runtime is fine; on the data, it is not.