April 1, 2025·7 min read

Why I Moved From Django to FastAPI (And When I Still Use Django)

I spent four years building Django apps before switching to FastAPI for most new projects. Here's what drove the switch, what I gained, what I gave up, and the situations where I still reach for Django.

I started with Django in 2016. It was the framework that taught me what a 'batteries included' framework actually meant — admin panel, ORM, migrations, auth, all wired together. For four years it was my default answer to every Python web project.

What changed

The shift started when I joined a team building a real-time communication platform. We needed WebSocket support, async task processing, and sub-100ms API responses at scale. Django could handle all of this, but it felt like fighting the framework — ASGI support was bolted on, and the ORM is fundamentally synchronous.

What FastAPI does better

  • Async-native from day one. Async/await works everywhere without fighting the ORM or middleware stack.
  • Dependency injection is a first-class citizen. FastAPI's Depends() system makes auth, DB sessions, and feature flags clean and testable.
  • Automatic OpenAPI docs. The interactive /docs page is generated from your type hints — no extra work.
  • Pydantic v2 integration. Request validation, serialization, and response models all share the same schema definitions.
  • Performance. Benchmarks show FastAPI 2–3x faster than Django REST Framework on equivalent endpoints.

What Django still does better

  • The admin panel. Django admin is unmatched for internal tooling. Building the same thing in FastAPI takes days.
  • The ORM for complex queries. Django's ORM with select_related and prefetch_related is still the most ergonomic way to work with relational data. SQLAlchemy 2.x comes close, but the learning curve is steeper.
  • Built-in auth. Django's auth system — sessions, groups, permissions — is battle-tested and covers 90% of use cases out of the box.
  • Migrations. Django migrations are the best database migration DX I've used. Alembic is fine, but it requires more manual work.
  • Ecosystem. Thousands of reusable apps: django-allauth, django-storages, django-celery-beat. FastAPI is catching up, but it's not there yet.

My decision framework

I use FastAPI when: the project is API-first with heavy async requirements, I'm building microservices, or performance is a primary concern. I use Django when: there's an admin-heavy workflow, the team is more comfortable with Django's conventions, or I need to ship quickly and the built-in batteries matter.

Migration strategy

If you're migrating an existing Django project, don't do a big-bang rewrite. Introduce FastAPI as a sidecar service for new high-traffic endpoints, keep Django for the admin and complex ORM queries, and share the database between them. Gradually route traffic to the FastAPI service as confidence grows.

python
# Coexistence: FastAPI handles the API layer,
# Django still owns admin + ORM-heavy operations

# fastapi_app/routers/calls.py
@router.post("/calls", response_model=CallResponse)
async def create_call(payload: CallCreate) -> CallResponse:
    # Motor directly to same MongoDB the Django app uses
    doc = await db.calls.insert_one(payload.model_dump())
    return CallResponse(id=str(doc.inserted_id), **payload.model_dump())

The honest answer

Both frameworks are excellent. The real answer is: use whichever one your team knows well and fits the project's requirements. I choose FastAPI for new API-first projects because async-native feels right for 2025, but I have deep respect for what Django represents — a framework that has shipped millions of successful applications.

Written by
Nasir Hussain
Sr. Full-Stack Developer
Work Together