Subjects

All subjects Django Java Python React Spring Boot JavaScript PHP
Sign Up Free
Question 5 of 10 · Django Signals & Decorators
Interview question

Are Django signal handlers executed synchronously or asynchronously? How do you handle this? Django signal handlers synchronously या asynchronously execute होते हैं? इसे कैसे handle करते हैं?

Answer

Signal handlers are executed synchronously in the same process, blocking the request. For long-running operations, use Celery tasks to execute asynchronously and avoid blocking.

ApproachWhenPros/Cons
Synchronous (default)Quick operations (cache updates)Fast, but blocks request
Async with CeleryLong operations (emails, API calls)Non-blocking, but complex
ThreadingBackground tasksSimple but risky with ORM
// ❌ SYNCHRONOUS - Blocks request
@receiver(post_save, sender=Book)
def send_email_on_save(sender, instance, created, **kwargs):
    if created:
        # This BLOCKS the request until email is sent
        send_notification_email(instance.author_email)
        print("Email sent")  # Delays user response

// ✅ ASYNCHRONOUS - Celery Queue
from celery import shared_task
from django.db.models.signals import post_save

@receiver(post_save, sender=Book)
def trigger_email_task(sender, instance, created, **kwargs):
    if created:
        # Queue task for async execution
        send_email_task.delay(instance.id)

@shared_task
def send_email_task(book_id):
    book = Book.objects.get(id=book_id)
    send_notification_email(book.author_email)

// ✅ SEMI-SYNC - Threading (light workload)
import threading

@receiver(post_save, sender=Book)
def async_logging(sender, instance, created, **kwargs):
    def log_in_background():
        AuditLog.objects.create(
            action="created" if created else "updated",
            model="Book",
            instance_id=instance.id
        )
    
    thread = threading.Thread(target=log_in_background)
    thread.daemon = True
    thread.start()

// Signal Handler Timing Example
import time

@receiver(post_save, sender=Book)
def slow_handler(sender, instance, created, **kwargs):
    start = time.time()
    time.sleep(5)  # Simulates slow operation
    duration = time.time() - start
    print(f"Handler took {duration} seconds - USER WAITED THIS LONG!")

// Measure Impact
from django.test import TestCase
import time

class SignalPerformanceTest(TestCase):
    def test_save_speed(self):
        start = time.time()
        Book.objects.create(title="Test", author="Test")
        duration = time.time() - start
        print(f"Save took {duration} seconds")
        # With async: ~0.01 seconds
        # With sync email: ~2 seconds (blocked)

// Best Practice - Use Celery for Heavy Operations
from celery import shared_task

@receiver(post_save, sender=Book)
def handle_book_creation(sender, instance, created, **kwargs):
    if created:
        # Quick operations in signal
        cache.set(f"book_{instance.id}", instance)
        
        # Heavy operations to Celery
        process_book_async.delay(instance.id)

@shared_task
def process_book_async(book_id):
    book = Book.objects.get(id=book_id)
    # Send notifications
    send_email_task(book)
    # Process images
    generate_thumbnails(book)
    # Update search index
    update_search_index(book)

Signal handlers synchronously execute होते हैं - request को block करते हैं। Heavy operations के लिए Celery use करो।

ApproachकबPros/Cons
SynchronousQuick operationsFast, blocks request
Celery AsyncHeavy operationsNon-blocking, complex
// ❌ Synchronous - blocks
@receiver(post_save, sender=Book)
def send_email(sender, instance, created, **kwargs):
    if created:
        send_notification(instance.email)
        # User इंतज़ार करता है

// ✅ Async with Celery
from celery import shared_task

@receiver(post_save, sender=Book)
def trigger_email(sender, instance, created, **kwargs):
    if created:
        send_email_async.delay(instance.id)

@shared_task
def send_email_async(book_id):
    book = Book.objects.get(id=book_id)
    send_notification(book.email)

Was this answer clear?