WSGI
ASGI
Django
server architecture
sync async

WSGI vs ASGI server with hybrid sync/async Django app

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Modern Django can run both synchronous and asynchronous views, which leads many teams to ask whether a hybrid app should still use WSGI or move to ASGI. The short answer is that WSGI is fine for fully synchronous workloads, but ASGI is the correct server interface if you want first-class async views, WebSockets, or long-lived connections.

What WSGI and ASGI Actually Mean

WSGI is the older Python web-server interface built around synchronous request handling. It works well with classic Django deployments and mature tooling such as Gunicorn with sync workers.

ASGI is the newer asynchronous interface. It supports HTTP too, but it also supports protocols and execution patterns that WSGI does not handle well, such as:

  • async request handling
  • WebSockets
  • long polling
  • background connection management

The important detail is that Django can adapt between sync and async code internally, but the outer server interface still affects performance characteristics and feature support.

What Happens in a Hybrid Django App

A hybrid Django app may contain both sync and async views. For example, a traditional database-backed HTML page may remain synchronous, while an endpoint that calls multiple external APIs concurrently may be asynchronous.

Under ASGI, Django can run both kinds of views. Sync views are executed in a thread-sensitive adapter, and async views run natively.

Under WSGI, Django can still expose async views, but they are adapted through a synchronous boundary. That means you lose many of the reasons for writing async code in the first place.

Example of Sync and Async Views

python
1from django.http import JsonResponse
2import asyncio
3
4
5def sync_view(request):
6    return JsonResponse({"mode": "sync"})
7
8
9async def async_view(request):
10    await asyncio.sleep(0.1)
11    return JsonResponse({"mode": "async"})

Django can route both views. The difference is how effectively the surrounding server stack can execute them.

When WSGI Is Still Fine

WSGI remains a solid choice when the application is mostly synchronous and you do not need WebSockets or other async-native behavior. Examples include:

  • classic server-rendered apps
  • admin dashboards
  • CRUD-heavy internal tools
  • codebases where the database and middleware stack are mostly synchronous anyway

In that scenario, forcing an ASGI migration may not buy much. A well-tuned WSGI deployment is still operationally simple and mature.

When ASGI Is the Better Choice

If the application genuinely benefits from asynchronous I/O, ASGI is the right interface. That includes cases where you want to:

  • serve WebSockets through Django Channels or a similar stack
  • await multiple external API calls efficiently
  • handle long-lived responses without tying up sync workers
  • grow into a more async-heavy architecture over time

A typical ASGI entry point in Django looks like this:

python
1import os
2from django.core.asgi import get_asgi_application
3
4os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
5application = get_asgi_application()

That application can then be served by an ASGI server such as Uvicorn or Daphne.

Deployment Tradeoffs

For WSGI, a common deployment is Gunicorn with sync workers. For ASGI, a common deployment is Uvicorn or Gunicorn using Uvicorn workers. The right choice is not about fashion. It is about whether your runtime behavior is mostly blocking or mostly non-blocking.

A mistake teams make is writing a few async views and expecting large performance gains while the rest of the stack still uses blocking database calls, blocking HTTP clients, or synchronous middleware. Async only helps where the underlying work is also non-blocking.

Common Pitfalls

  • Choosing ASGI only because Django supports async can add deployment complexity without meaningful benefit when the app is still mostly synchronous. Match the server model to the workload.
  • Expecting WSGI to provide the real advantages of async Django defeats the purpose of writing async views. WSGI forces the app back through a synchronous boundary.
  • Writing async def views while still calling blocking libraries inside them can hurt performance rather than improve it. Async code must use non-blocking dependencies to pay off.
  • Assuming sync and async middleware behave identically can lead to unexpected adaptation overhead. Review middleware compatibility during a migration.
  • Treating WebSockets as just another HTTP route is incorrect. If you need WebSockets, ASGI is the practical requirement.

Summary

  • WSGI is still a strong option for mostly synchronous Django apps.
  • ASGI is the correct choice when you need native async handling or WebSockets.
  • Hybrid Django apps can run under either interface, but only ASGI preserves the full benefit of async views.
  • Async code helps only when the underlying libraries and I/O paths are also non-blocking.
  • Pick the server model based on actual runtime behavior, not on framework trend alone.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.