Why We Still Reach for Django + GraphQL
February 10, 2026
Every few months someone on the team half-jokingly asks if we should rewrite the API layer in something newer. It's a fair question — Django and GraphQL aren't the stack you'd pick if you wanted to be interesting on a conference stage. Here's why we've kept them anyway, and what would actually change my mind.
The ORM is doing more work than people give it credit for
Our data model isn't simple: pricing rules, customer interactions, vehicle documentation, and service schedules, all tenant-scoped, all with different lifecycle rules. Django's ORM handles that complexity without us hand-rolling query builders or fighting an abstraction that was designed for simpler shapes. The admin panel alone — free, generated from the same models — has saved us weeks of building internal tooling we'd otherwise need for support and operations staff who aren't engineers.
GraphQL earns its complexity at the aggregation layer
Our React frontend needs to assemble views that pull from rentals, vehicles, customers, and billing in a single screen. Doing that over REST meant either over-fetching or maintaining a pile of purpose-built endpoints that drifted out of sync with what the frontend actually needed. A GraphQL schema, once the discipline of managing it is in place, lets the frontend ask for exactly the shape it wants and lets us evolve the backend without breaking every client at once.
The cost is real: schema design takes longer up front than sketching a REST endpoint, and a bad
resolver can hide an N+1 query problem that's invisible until it isn't. We use select_related and
prefetch_related aggressively and treat resolver performance as something to review, not assume.
Where I'd reconsider
If I were starting a new service today that was mostly I/O-bound, high-throughput, and didn't need a rich admin interface, I'd look hard at FastAPI — the async story is better, and we don't always need everything Django brings. We've started using FastAPI for a couple of smaller internal services for exactly that reason. It's not an all-or-nothing choice; it's about matching the tool to what a given service actually needs to do, and not rewriting a system that's working just because something newer exists.
The actual lesson
"Boring" technology isn't a compliment people mean kindly, but it's underrated. Django and GraphQL are mature enough that when something breaks, the answer is usually already written down somewhere, by someone who hit the same problem years ago. That's worth more to a small team than novelty is.