Django is a Python development classic that has been helping build and maintain web projects of all scales for two decades. But how does this monolith cope with the challenges of modern async and SPA? And why has strict backward compatibility become both its greatest advantage and its main limitation?
TL;DR: The Django + DRF stack faces serious limits with typing and async. True async in Django is still not fully fixed, but the ecosystem adapts. Developers use new tools like django-modern-rest for better APIs, or just return to SSR + HTMX.
1. The Era of Web Spaghetti: How Django and Its Contemporaries Changed the Game
The mid-2000s marked a global shift in web development. Almost simultaneously, a new generation of frameworks emerged: Ruby on Rails, Symfony, and Django. They brought order to the chaos of the lightweight web segment. They also offered a flexible alternative to the heavy Enterprise stack (Java, .NET).
Spaghetti code—where HTML, SQL queries, and business logic were mixed in a single file—was replaced by a clear separation of concerns and the concept of rapid development.
Django, like its competitors, offered developers everything they needed out of the box:
- A built-in ORM
- An authentication subsystem
- An administrative panel
The web at that time operated on the classic Server-Side Rendering (SSR) model. The server received a request, fetched data from the database, rendered an HTML template, and returned the finished page to the browser. The community embraced pure dynamic typing. Programmers valued Python for its development speed and freedom from compilation.
In this paradigm, the MTV (Model-Template-View) architecture fully met business needs. The built-in admin panel (Django Admin) became a technological breakthrough. Unlike Ruby on Rails, where Scaffolding generated physical code files, Django chose dynamic configuration. The admin panel read model metadata at application startup and generated the management interface on the fly.
However, the decision to bind the admin panel, forms, and ORM via deep dynamic model introspection carried a hidden cost. Years later, this magic would turn into a serious barrier to full static typing support. Furthermore, the monolithic synchronous nature of the old ORM would significantly slow down the framework's transition to a modern asynchronous architecture.
2. The Great Async Irony: How DRF’s Creator Paved the Way for FastAPI
By the mid-2010s, the explosive popularity of AngularJS and React turned Single Page Applications (SPAs) into the new industry standard. The backend became a mere data provider, serving pure JSON. This posed a serious challenge for monolithic Django: its built-in templates and forms suddenly became obsolete.
Tom Christie saved the situation by creating the Django REST Framework (DRF). For many years, this tool secured Django's status as the primary web API in the Python ecosystem. However, DRF's architecture was designed long before modern language standards emerged—leaving it without built-in integration for type hints.
Everything changed with the release of Python 3.5 in 2015. The language officially received native async support via async/await syntax (asyncio) and a type hinting standard. The rise of the mypy static analyzer permanently changed Python development culture. Missing type hints in large projects gradually became bad practice, as codebases without them are difficult to refactor.
Against this background, a major historical irony unfolded. The industry moved toward microservices, where Node.js and Go visibly outperformed Python in highly concurrent I/O operations. While Django Core developer Andrew Godwin tried to catch up with the trend by creating the ASGI async specification for Django, Tom Christie effectively laid a time bomb under his own creation. He founded Encode and released a new async ecosystem completely relying on fresh Python 3.5+ features: the Uvicorn server, the Starlette lightweight framework, and HTTPX.
Starlette soon became the foundation for FastAPI. It combined Tom Christie's async groundwork with strict typing and end-to-end validation via Pydantic. In this light, classic Django, along with the aging DRF, suddenly looked like a bulky tech stack from the past.
3. Technological Deadlock: What Is Wrong with the Old Stack Today?
Caught in the new reality, the Django + DRF combination began rapidly losing ground for modern API design. There are several compelling reasons for this:
- Low performance of DRF serializers. Pure Python validation with numerous internal calls and dynamic introspection runs slowly. Modern tools powered by Rust cores (like Pydantic v2) parse and validate data several times faster.
-
Violation of the Single Responsibility Principle (SRP). The
ModelSerializerclass is tightly coupled with the ORM. It simultaneously describes the request/response schema, validates business logic, and manages data persistence. In large projects, this often creates bloated "God Objects" spanning thousands of lines of code. -
Lack of native async support in DRF. The framework's architecture remains synchronous: serializer and view methods do not support the
awaitkeyword. When running a project via an ASGI server, Django's async core is forced to run DRF's synchronous code inside a thread pool, which completely negates the benefits of async. -
Difficulties with message broker integration. Django's architecture is isolated within the classic request-response lifecycle. There is no built-in mechanism to run long-lived processes. The
django.tasksmodule introduced in Django 6.0 only defines an interface but lacks a production-ready worker. To work with RabbitMQ or Kafka, developers still have to deploy Celery or write custom management commands.
4. Evolution in Spite of Obstacles: How django-modern-rest Changes the Game
The community quickly realized that waiting for a global overhaul of DRF was pointless and began creating alternative solutions. Following the popular Django Ninja, django-modern-rest (DMR) became the technological answer to modern challenges.
The main conceptual difference of DMR is the complete separation of the API layer from business models, thanks to a pluggable architecture. Instead of heavy DRF mechanisms, developers can choose their validation engine: the familiar Pydantic or the ultra-performant msgspec, which accelerates JSON processing significantly.
DMR generates accurate OpenAPI specifications directly from type hints and strictly validates data at runtime. This provides:
- Native async support (ASGI) without extra layers
- Out-of-the-box auto-documentation
- Advanced API testing (e.g., via integration with Schemathesis)
At the same time, standard Django Views remain under the hood. For developers, this means the best of both worlds: FastAPI-level speed and strict typing without losing the mature Django ecosystem.
5. The Burden of Backward Compatibility: Why You Can't Just Rewrite Everything
Why can't Django Core developers rebuild the system to match new standards overnight? The answer is simple: businesses value the framework precisely for its stability. Radical changes would break thousands of third-party packages. By breaking version continuity, Django risks repeating the painful, drawn-out experience the IT industry faced when moving from Python 2 to Python 3.
Consequently, async features are introduced evolutionarily—from release to release. In practice, however, this approach remains a compromise. Under the hood, the framework's async interfaces are still forced to rely on synchronous threads when interacting with legacy components. Additionally, a massive array of third-party plugins, the DRF ecosystem, and the built-in admin panel remain tightly bound to a synchronous architecture.
Conclusion: Will the Old Timer Keep Fighting?
Is Django dying? Definitely not. The framework is going through a prolonged and painful transformation. True, it is no longer the default choice for lightweight microservices. However, the emergence of tools like django-modern-rest clearly proves that the ecosystem can adapt to modern challenges despite the conservative limitations of its core.
Moreover, there is a distinct "SPA fatigue" visible in the industry today. Maintaining a bloated frontend just for simple interfaces costs businesses a lot of money. The industry is returning to Server-Side Rendering (SSR) and lightweight HTMX. In this new reality, Django's classic architecture is once again in high demand.
Ultimately, strict backward compatibility—which once seemed like a limitation—has turned into the framework's main commercial advantage. Projects written ten years ago continue to run stably, generate revenue, and upgrade smoothly to current versions without needing a complete rewrite.
Top comments (0)