Django Signals vs Celery Tasks 2026: āđāļĄāļ·āđāļāđāļŦāļĢāđāļāļ§āļĢāđāļāđāļāļ°āđāļĢ
āđāļĢāļĩāļĒāļāļĢāļđāđāļ§āđāļēāđāļĄāļ·āđāļāđāļŦāļĢāđāļāļ§āļĢāđāļāđ Django signals āđāļāļĩāļĒāļāļāļąāļ Celery tasks āļāļĢāļāļāļāļĨāļļāļĄāļāļēāļĢāļāļąāļāļāļēāļĢ event āđāļāļ synchronous vs asynchronous āļāļĨāļāļĢāļ°āļāļāļāđāļēāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļ āđāļĨāļ°āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđāļŠāļģāļŦāļĢāļąāļāļāļąāļāļāļąāļāļāļē Django

Django signals āđāļĨāļ° Celery tasks āļāļąāđāļāļāļđāđāļāļąāļāļāļēāļĢ events āđāļāđāļāļāļāļĨāļīāđāļāļāļąāļ Django āđāļāđāļāļąāđāļāļŠāļāļāđāļāđāļāļąāļāļŦāļēāļāļĩāđāđāļāļāļāđāļēāļāļāļąāļ Signals āļāļģāļāļēāļāđāļāļ synchronous āļ āļēāļĒāđāļ request-response cycle āđāļāļāļāļ°āļāļĩāđ Celery āļŠāđāļāļāļēāļāđāļāļĒāļąāļ background workers āļāļēāļĢāđāļĨāļ·āļāļāđāļāļĢāļ·āđāļāļāļĄāļ·āļāļāļĩāđāļāļīāļāļāļģāđāļāļŠāļđāđ response āļāļĩāđāļāđāļē race conditions āļŦāļĢāļ·āļāļŠāļāļēāļāļąāļāļĒāļāļĢāļĢāļĄāļāļĩāđāļāļąāļāļāđāļāļāđāļāļīāļāđāļ
āđāļāđ Django signals āļŠāļģāļŦāļĢāļąāļ side effects āļāļĩāđāđāļāļēāđāļĨāļ° synchronous āļāļĩāđāļāđāļāļāđāļŠāļĢāđāļāļāđāļāļ response āđāļāđ Celery āļŠāļģāļŦāļĢāļąāļāļāļļāļāļāļĒāđāļēāļāļāļĩāđāđāļāđāđāļ§āļĨāļēāļĄāļēāļāļāļ§āđāļē 100ms āđāļāļĩāđāļĒāļ§āļāđāļāļāļāļąāļ external services āļŦāļĢāļ·āļāļŠāļēāļĄāļēāļĢāļāļĨāđāļĄāđāļŦāļĨāļ§āđāļāđāļāļĒāđāļēāļāļāļīāļŠāļĢāļ°āļāļēāļ request āļŦāļĨāļąāļ
āļ§āļīāļāļĩāļāļēāļĢāļāļģāļāļēāļāļāļāļ Django Signals āđāļāļ·āđāļāļāļŦāļĨāļąāļ
Django signals āđāļāđ observer pattern āđāļĄāļ·āđāļ model āļāļđāļ save āļĨāļ āļŦāļĢāļ·āļāđāļĄāļ·āđāļ request āđāļĢāļīāđāļĄāļāđāļāļŦāļĢāļ·āļāļŠāļīāđāļāļŠāļļāļ Django āļāļ°āļŠāđāļ signal āļāļāļāđāļ āļāļąāļāļāđāļāļąāļāđāļāđ āļāļĩāđāđāļāļ·āđāļāļĄāļāđāļāļāļąāļ signal āļāļąāđāļāļāļ°āļāļģāļāļēāļāļāļąāļāļāļĩ āđāļ database transaction āđāļāļĩāļĒāļ§āļāļąāļāđāļĨāļ° thread āđāļāļĩāļĒāļ§āļāļąāļ
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.cache import cache
from .models import Product
@receiver(post_save, sender=Product)
def invalidate_product_cache(sender, instance, **kwargs):
# āļāļģāļāļēāļāđāļāļ synchronous āļŦāļĨāļąāļāļāļēāļ Product.save() commit
cache_key = f"product:{instance.id}"
cache.delete(cache_key)
# āļĒāļąāļ invalidate category listing āļāđāļ§āļĒ
cache.delete(f"category:{instance.category_id}:products")Signal receiver āļāļģāļāļēāļāļ āļēāļĒāđāļ database transaction āđāļāļĩāļĒāļ§āļāļąāļ āļāđāļē transaction rollback āļāļĨāļāļāļ signal handler āļĒāļąāļāļāļāļāļĒāļđāđ āļŠāļīāđāļāļāļĩāđāļŠāļģāļāļąāļāļŠāļģāļŦāļĢāļąāļ cache invalidation: cache āļāļđāļāļĨāļ āđāļāđāļāļēāļĢāđāļāļĨāļĩāđāļĒāļāđāļāļĨāļ database āđāļĄāđāđāļāļĒāļāļđāļāļāļąāļāļāļķāļ āļāļĨāļĨāļąāļāļāđāļāļ·āļ cache miss āļāļĩāđāđāļŦāļĨāļāļāđāļāļĄāļđāļĨāđāļāđāļēāļāļĨāļąāļāļĄāļē
Django 5.2 āđāļāļ°āļāļģ transaction.on_commit() āđāļāļ·āđāļāđāļāđāļāļąāļāļŦāļēāļāļĩāđ āļāļēāļĢāļŦāđāļ logic āļāļāļ signal āđāļ on_commit āļĢāļąāļāļāļĢāļ°āļāļąāļāļāļēāļĢāļāļģāļāļēāļāļŦāļĨāļąāļāļāļēāļ commit āļŠāļģāđāļĢāđāļāđāļāđāļēāļāļąāđāļ:
# signals.py
from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Product
from .tasks import reindex_product
@receiver(post_save, sender=Product)
def handle_product_saved(sender, instance, **kwargs):
# āļĢāļāļāļāļāļ§āđāļē transaction āļāļ° commit āļŠāļģāđāļĢāđāļ
transaction.on_commit(
lambda: reindex_product.delay(instance.id)
)āļĢāļđāļāđāļāļāļāļĩāđāđāļāļ·āđāļāļĄāļāđāļ signals āđāļĨāļ° Celery: signal āļāļđāļāđāļĢāļĩāļĒāļāđāļāđāđāļāļ synchronous āđāļāđāļāļēāļāļāļĢāļīāļāđāļāļīāļāļāļķāđāļāđāļāļ asynchronous āļŦāļĨāļąāļāļāļēāļ transaction commit
āđāļĄāđāļāļĨāļāļēāļĢāļāļģāļāļēāļāļāļāļ Celery Task
Celery āļĢāļąāļ tasks āđāļāļāļĢāļ°āļāļ§āļāļāļēāļĢ worker āđāļĒāļāļāđāļēāļāļŦāļēāļ Django view āļāļ° enqueue task āđāļāļĒ serialize arguments āđāļāļĒāļąāļ message broker (Redis āļŦāļĢāļ·āļ RabbitMQ) Worker āļāļ°āļĢāļąāļ message āđāļĨāļ°āļāļģ task āđāļāļĒāđāļĄāđāļāļķāđāļāļāļąāļ HTTP request āđāļāļīāļĄ
# tasks.py
from celery import shared_task
from django.core.mail import send_mail
from .models import Order
@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_order_confirmation(self, order_id: int):
"""āļŠāđāļāļāļĩāđāļĄāļĨāļĒāļ·āļāļĒāļąāļāļŦāļĨāļąāļāļāļēāļāļŠāļąāđāļāļāļ·āđāļ"""
try:
order = Order.objects.select_related('user').get(id=order_id)
send_mail(
subject=f"āļāļģāļŠāļąāđāļāļāļ·āđāļ #{order.id} āđāļāđāļĢāļąāļāļāļēāļĢāļĒāļ·āļāļĒāļąāļ",
message=f"āļāļģāļŠāļąāđāļāļāļ·āđāļāļāļāļāļāļļāļāļĄāļđāļĨāļāđāļē {order.total} āđāļāđāļāļđāļāļ§āļēāļāđāļĨāđāļ§",
from_email="orders@example.com",
recipient_list=[order.user.email],
)
except Order.DoesNotExist:
# Order āļāļđāļāļĨāļāļāđāļāļāļāļĩāđ task āļāļ°āļāļģāļāļēāļ āļāđāļēāļĄāđāļ
return
except Exception as exc:
# Retry āđāļĄāļ·āđāļāđāļāļīāļāļāļ§āļēāļĄāļĨāđāļĄāđāļŦāļĨāļ§āļāļąāđāļ§āļāļĢāļēāļ§ (SMTP timeout āđāļāđāļāļāđāļ)
raise self.retry(exc=exc)Task āļāļģāļāļēāļāđāļāļāļĢāļ°āļāļ§āļāļāļēāļĢāļāļĩāđāđāļāļāļāđāļēāļ āļāļēāļāļāļ°āļāļĒāļđāđāļāļāđāļāļĢāļ·āđāļāļāļāļĩāđāđāļāļāļāđāļēāļ āļĄāļąāļāđāļĄāđāļĄāļĩāļŠāļīāļāļāļīāđāđāļāđāļēāļāļķāļ context āļāļāļ request āđāļāļīāļĄ āļāđāļē order āļāļđāļāļĨāļāļĢāļ°āļŦāļ§āđāļēāļ enqueue āđāļĨāļ°āļāļēāļĢāļāļģāļāļēāļ task āļāđāļāļāļāļąāļāļāļēāļĢāļŠāļīāđāļāļāļąāđāļāļāļĒāđāļēāļāđāļŦāļĄāļēāļ°āļŠāļĄ
Celery 5.4 (āđāļ§āļāļĢāđāļāļąāļāđāļŠāļāļĩāļĒāļĢāļāļąāļāļāļļāļāļąāļ āļ āļāļąāļāļĒāļēāļĒāļ 2026) āđāļāļīāđāļĄāļāļēāļĢāļāļĢāļąāļāļāļĢāļļāļ task typing āđāļĨāļ°āļāļēāļĢāļĢāļ§āļĄ Django āļāļĩāđāļāļĩāļāļķāđāļāļāđāļēāļ django-celery-results āļŠāļģāļŦāļĢāļąāļāđāļāđāļāļāļĨāļĨāļąāļāļāđ task āđāļ database
āđāļāļĢāļĩāļĒāļāđāļāļĩāļĒāļāļāļļāļāļĨāļąāļāļĐāļāļ°āļāđāļēāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļ
Signals āđāļāļīāđāļĄ latency āđāļŦāđāļāļąāļ request āļāļļāļ receiver āļāļĩāđāđāļāļ·āđāļāļĄāļāđāļāļāļ°āļāļģāļāļēāļāļāđāļāļāļāļĩāđ response āļāļ°āļāļđāļāļŠāđāļāļāļĨāļąāļ āļāđāļ§āļĒ receivers āļŠāļēāļĄāļāļąāļ§āļāļĩāđāđāļāļĨāļĩāđāļĒ 50ms āđāļāđāļĨāļ°āļāļąāļ§ request āļāļ°āđāļāđāđāļ§āļĨāļēāđāļāļīāđāļĄāļāļķāđāļ 150ms
Celery āđāļāļīāđāļĄ latency āļāđāļāļĒāļĄāļēāļ (āļāļāļāļī 1-5ms āļŠāļģāļŦāļĢāļąāļ enqueue) āđāļāđāđāļāļ°āļāļģ eventual consistency āļāļĩāđāļĄāļĨāļāļ°āļāļđāļāļŠāđāļ "āđāļāļāļĩāđāļŠāļļāļ" āđāļĄāđāđāļāđāļāđāļāļ response
| āļāļąāļāļāļąāļĒ | Django Signals | Celery Tasks |
|---|---|---|
| āļāļēāļĢāļāļģāļāļēāļ | Synchronous āļāļĢāļ°āļāļ§āļāļāļēāļĢāđāļāļĩāļĒāļ§ | Asynchronous āļāļĢāļ°āļāļ§āļāļāļēāļĢ worker |
| āļāļĨāļāļĢāļ°āļāļ latency | āđāļāļīāđāļĄāđāļ§āļĨāļē request | ~1-5ms overhead enqueue |
| āļāļēāļĢāļāļąāļāļāļēāļĢāļāļ§āļēāļĄāļĨāđāļĄāđāļŦāļĨāļ§ | āļāļģāļĨāļēāļĒ request | Retry āļāļĒāđāļēāļāļāļīāļŠāļĢāļ° |
| āļāļāļāđāļāļ transaction | āļ āļēāļĒāđāļ transaction | āļ āļēāļĒāļāļāļ transaction |
| āļāļēāļĢāđāļĢāļĩāļĒāļ external services | āļāļĨāđāļāļ response | āļāļģāļāļēāļāđāļ background |
| āļāļ§āļēāļĄāļāļąāļāļāđāļāļ | Setup āļāđāļāļĒāļāļĩāđāļŠāļļāļ | āļāđāļāļāļāļēāļĢ broker + workers |
āđāļĄāļ·āđāļāđāļŦāļĢāđāļāļĩāđ Signals āđāļāđāļāļāļēāļāđāļĨāļ·āļāļāļāļĩāđāļāļđāļāļāđāļāļ
Signals āđāļŦāļĄāļēāļ°āļāļąāļāļŠāļāļēāļāļāļēāļĢāļāđāļāļĩāđ side effect āļāđāļāļāđāļŠāļĢāđāļāļāđāļāļāļāļģāđāļāļīāļāļāļēāļĢāļāđāļ āđāļĨāļ°āđāļĄāļ·āđāļāļāļ§āļēāļĄāļĨāđāļĄāđāļŦāļĨāļ§āļāļ§āļĢāļĒāļāđāļĨāļīāļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢ
Cache invalidation āļāļģāļāļēāļāđāļāđāļāļĩāļāļąāļ signals āđāļĄāļ·āđāļ Product āļāļđāļāļāļąāļāđāļāļ āļāļēāļĢāđāļŠāļāļāļāļĩāđāļāļđāļ cache āļāđāļāļāļāļđāļ invalidate āļāļąāļāļāļĩ cache āļāļĩāđāđāļāđāļēāđāļĄāđāđāļāļĩāļĒāļāđāļĄāđāļāļĩāđāļ§āļīāļāļēāļāļĩāļāļģāđāļŦāđāđāļŠāļāļāļĢāļēāļāļēāļŦāļĢāļ·āļāļāļģāļāļ§āļāļŠāļīāļāļāđāļēāļāļāļāļĨāļąāļāļāļĩāđāđāļĄāđāļāļđāļāļāđāļāļ
# signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.core.cache import cache
from .models import Product
@receiver([post_save, post_delete], sender=Product)
def clear_product_cache(sender, instance, **kwargs):
cache.delete(f"product:{instance.id}")
cache.delete(f"product:{instance.slug}")
# āļĨāļ cache āļĢāļēāļĒāļāļēāļĢāđāļāđ āļāļĩāđāļāļēāļāļĢāļ§āļĄāļāļĨāļīāļāļ āļąāļāļāđāļāļĩāđ
cache.delete_pattern(f"products:category:{instance.category_id}:*")Audit logging āļāļĩāđ log āļāđāļāļāļĄāļĩāļāļĒāļđāđāļāđāļāļāļāļĩāđ response āļāļ°āļāļđāļāļŠāđāļāļāļĨāļąāļāļāđāđāļŦāļĄāļēāļ°āļāļąāļ signals āļāđāļē admin āļĨāļ user audit log āļāļ§āļĢāļāļąāļāļāļķāļāļāļēāļĢāļĨāļāļāļąāđāļāļāļĒāđāļēāļ atomic āļāļąāļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļĨāļ
Denormalization āļāļāļ fields āļāđāļēāļĄ models āļāļĩāđāđāļāļĩāđāļĒāļ§āļāđāļāļāđāļāđāļāļĢāļ°āđāļĒāļāļāđāļāļēāļ signals āđāļĄāļ·āđāļāļŠāļāļēāļāļ° Order āđāļāļĨāļĩāđāļĒāļāđāļāđāļ "shipped" āļāļēāļĢāļāļąāļāđāļāļ field denormalized last_shipped_at āļāļ Customer āđāļāļīāļāļāļķāđāļāļāļąāļāļāļĩ
āļāļĢāđāļāļĄāļāļĩāđāļāļ°āļāļīāļāļīāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđ Django āđāļĨāđāļ§āļŦāļĢāļ·āļāļĒāļąāļāļāļĢāļąāļ?
āļāļķāļāļāļāļāđāļ§āļĒāļāļąāļ§āļāļģāļĨāļāļāđāļāļāđāļāđāļāļāļ, flashcards āđāļĨāļ°āđāļāļāļāļāļŠāļāļāđāļāļāļāļīāļāļāļĢāļąāļ
āđāļĄāļ·āđāļāđāļŦāļĢāđāļāļĩāđ Celery Tasks āđāļāđāļāļāļēāļāđāļĨāļ·āļāļāļāļĩāđāļāļđāļāļāđāļāļ
Celery āđāļŦāļĄāļēāļ°āļāļąāļāļŠāļāļēāļāļāļēāļĢāļāđāļāļĩāđāđāļāļĩāđāļĒāļ§āļāđāļāļāļāļąāļ external services āļāļēāļĢāļāļģāļāļ§āļāļāļĩāđāđāļāđāđāļ§āļĨāļēāļāļēāļ āļŦāļĢāļ·āļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļāļĩāđāļŠāļēāļĄāļēāļĢāļāļĨāđāļĄāđāļŦāļĨāļ§āđāļĨāļ° retry āđāļāđāļāļĒāđāļēāļāļāļīāļŠāļĢāļ°
āļāļēāļĢāļŠāđāļāļāļĩāđāļĄāļĨ āđāļĄāđāļāļ§āļĢāļāļĨāđāļāļ requests āđāļāļīāļĢāđāļāđāļ§āļāļĢāđ SMTP āļĄāļĩ latency āļāļĩāđāđāļĄāđāļŠāļēāļĄāļēāļĢāļāļāļēāļāđāļāļēāđāļāđ āļāļēāļāļāļĢāļąāđāļ timeout āđāļĨāļ°āļāļģāļāļąāļ rate āļāļđāđāļŠāđāļ Celery task āļāļ° retry āļāļĩāđāļĄāļĨāļāļĩāđāļĨāđāļĄāđāļŦāļĨāļ§āđāļāļĒāđāļĄāđāļŠāđāļāļāļĨāļāļĢāļ°āļāļāļāđāļāļāļĢāļ°āļŠāļāļāļēāļĢāļāđāļāļđāđāđāļāđ
āļāļēāļĢāļŠāļĢāđāļēāļ PDF āļŠāļģāļŦāļĢāļąāļāđāļāđāļāđāļāļŦāļāļĩāđāļŦāļĢāļ·āļāļĢāļēāļĒāļāļēāļāđāļāđāđāļ§āļĨāļēāļŦāļĨāļēāļĒāļ§āļīāļāļēāļāļĩ āļāļēāļĢāļŠāļĢāđāļēāļāđāļāļ synchronous āļāļģāđāļŦāđ UI āļĢāļđāđāļŠāļķāļāđāļŠāļĩāļĒ Enqueue task āļāļ·āļāļŠāļāļēāļāļ° "processing" āđāļĨāļ°āđāļŦāđāļāļđāđāđāļāđāļāļēāļ§āļāđāđāļŦāļĨāļāđāļĄāļ·āđāļāļāļĢāđāļāļĄ
āļāļēāļĢāđāļĢāļĩāļĒāļ API āļāļļāļāļāļĨāļāļĩāđāļŠāļēāļĄ āļāļĒāļđāđāđāļ Celery āļāļēāļĢāđāļĢāļĩāļĒāļ Stripe Twilio āļŦāļĢāļ·āļ external service āđāļāđ āđāļāļ synchronous āđāļāļ·āđāļāļĄāđāļĒāļāđāļ§āļĨāļē response āļāļąāļāļāļāļāļāļ§āļāđāļāļē āđāļĄāļ·āđāļ API āļāļāļāļāļ§āļāđāļāļēāļāđāļēāļĨāļ āđāļāļāļāļĨāļīāđāļāļāļąāļāļāđāļāđāļēāļĨāļ
# tasks.py
from celery import shared_task
import stripe
from .models import Subscription
@shared_task(bind=True, max_retries=5, retry_backoff=True)
def sync_stripe_subscription(self, subscription_id: int):
"""āļāļīāļāļāđ subscription āđāļāđāļāļĢāļ·āđāļāļāļāļąāļāļŠāļāļēāļāļ° Stripe"""
try:
sub = Subscription.objects.get(id=subscription_id)
stripe_sub = stripe.Subscription.retrieve(sub.stripe_id)
sub.status = stripe_sub.status
sub.current_period_end = stripe_sub.current_period_end
sub.save(update_fields=['status', 'current_period_end'])
except stripe.error.RateLimitError as exc:
# Stripe āļāļģāļāļąāļ rate retry āļāđāļ§āļĒ exponential backoff
raise self.retry(exc=exc)
except Subscription.DoesNotExist:
return # Subscription āļāļđāļāļĨāļāđāļāđāļāļĢāļ·āđāļāļ āđāļĄāđāļĄāļĩāļāļ°āđāļĢāļāđāļāļāļāļīāļāļāđāļāļēāļĢāļēāļĄāļīāđāļāļāļĢāđ retry_backoff=True āđāļ Celery 5.x āđāļāļīāļāđāļāđāļāļēāļ exponential backoff: retry āđāļĢāļāļŦāļĨāļąāļāļāļēāļ 1 āļ§āļīāļāļēāļāļĩ āļāļēāļāļāļąāđāļ 2 āļāļēāļāļāļąāđāļ 4 āļāļāļāļķāļāļŠāļđāļāļŠāļļāļ āļŠāļīāđāļāļāļĩāđāļāđāļāļāļāļąāļāļāļēāļĢ hammering API āļāļĩāđāļāļđāļ rate-limited
āļĢāļđāļāđāļāļ Hybrid: Signals āļāļĢāļīāļāđāļāļāļĢāđ Tasks
āļŠāļāļēāļāļąāļāļĒāļāļĢāļĢāļĄāļāļĩāđāđāļāđāļāđāļāļĢāđāļāļāļĩāđāļŠāļļāļāđāļāđ signals āļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļāļĢāļ°āļŠāļēāļāļāļēāļāđāļāļēāđāļĨāļ°āļāļąāļāļāļĩ āđāļĨāļ° Celery āļŠāļģāļŦāļĢāļąāļāļāļēāļāļŦāļāļąāļāļāļĢāļīāļāđ
# signals.py
from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Order
from .tasks import (
send_order_confirmation,
notify_warehouse,
update_analytics,
)
@receiver(post_save, sender=Order)
def on_order_created(sender, instance, created, **kwargs):
if not created:
return # āļāļąāļāļāļēāļĢāđāļāļāļēāļ° orders āđāļŦāļĄāđāđāļāđāļēāļāļąāđāļ
# Enqueue āļāļēāļ async āļāļąāđāļāļŦāļĄāļāļŦāļĨāļąāļāļāļēāļ transaction commit
transaction.on_commit(lambda: (
send_order_confirmation.delay(instance.id),
notify_warehouse.delay(instance.id),
update_analytics.delay('order_created', instance.id),
))āļĢāļđāļāđāļāļāļāļĩāđāļĢāļąāļāļāļĢāļ°āļāļąāļ:
- Order āļĄāļĩāļāļĒāļđāđāđāļ database āļāđāļāļāļāļĩāđ tasks āļāļ°āļāļģāļāļēāļ (transaction commit āđāļĨāđāļ§)
- āđāļĄāđāļĄāļĩāļāļēāļ async āđāļāļīāļāļāļķāđāļāļāđāļē transaction rollback
- HTTP response āļāļđāļāļŠāđāļāļāļĨāļąāļāļāļąāļāļāļĩ
- āđāļāđāļĨāļ° task āļŠāļēāļĄāļēāļĢāļāļĨāđāļĄāđāļŦāļĨāļ§āđāļĨāļ° retry āđāļāđāļāļĒāđāļēāļāļāļīāļŠāļĢāļ°
āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđāđāļāļĩāđāļĒāļ§āļāļąāļ Django Signals vs Celery
āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđāļāļēāļāđāļāļāļāļīāļāļŠāļģāļŦāļĢāļąāļāļāļģāđāļŦāļāđāļ Django āļĄāļąāļāļŠāļģāļĢāļ§āļāļāļ§āļēāļĄāđāļāļāļāđāļēāļāļāļĩāđ āļāļĩāđāļāļ·āļāļāļģāļāļēāļĄāļāļĩāđāđāļĒāļāļāļđāđāļŠāļĄāļąāļāļĢāļāļĩāđāļĄāļĩāļāļĢāļ°āļŠāļāļāļēāļĢāļāđāļāļāļāļāļēāļāļāļđāđāļāļĩāđāđāļāđāļāđāļāļāļāļģāđāļāļāļŠāļēāļĢ
Q: Signal handler āļŠāđāļāļāļĩāđāļĄāļĨ Transaction database rollback āđāļāļīāļāļāļ°āđāļĢāļāļķāđāļ?
āļāļĩāđāļĄāļĨāļāļđāļāļŠāđāļāļāļĒāļđāđāļāļĩ Signal handlers āļāļģāļāļēāļāļĢāļ°āļŦāļ§āđāļēāļ transaction āđāļĄāđāđāļāđāļŦāļĨāļąāļāļāļēāļ commit āļāļĩāđāļĄāļĨāļāļāļāđāļ āđāļāđāļāļēāļĢāđāļāļĨāļĩāđāļĒāļāđāļāļĨāļ database āļāļĩāđāļāļĢāļīāļāđāļāļāļĢāđāļĄāļąāļāđāļĄāđāđāļāļĒāļāļđāļāļāļąāļāļāļķāļ āđāļāļ·āđāļāđāļāđāđāļāļŠāļīāđāļāļāļĩāđ āļŦāđāļāļāļēāļĢāđāļĢāļĩāļĒāļāļāļĩāđāļĄāļĨāđāļ transaction.on_commit() āļŦāļĢāļ·āļāļāļĩāļāļ§āđāļē enqueue Celery task āļ āļēāļĒāđāļ on_commit()
Q: āļāļ°āļāđāļāļāļāļąāļ signal āļāļēāļāļāļēāļĢ firing āļĢāļ°āļŦāļ§āđāļēāļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢ bulk āđāļāđāļāļĒāđāļēāļāđāļĢ?
bulk_create() bulk_update() āđāļĨāļ° QuerySet.update() āļāļāļ Django āđāļĄāđāļāļĢāļīāļāđāļāļāļĢāđ signals āļāļĩāđāđāļāđāļāļāļ§āļēāļĄāļāļąāđāļāđāļāđāļāļ·āđāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļ āļāđāļēāļāđāļāļāļāļēāļĢāļāļĪāļāļīāļāļĢāļĢāļĄ signal āđāļŦāđ iterate āđāļĨāļ° save āļāļĩāļĨāļ°āļāļąāļ§ (āļĒāļāļĄāļĢāļąāļāļāđāļāļāļļāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļ) āļŦāļĢāļ·āļ dispatch signal āļāđāļ§āļĒāļāļāđāļāļāļŦāļĨāļąāļāļāļēāļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢ bulk
Q: Celery task āļāđāļēāļāļāļīāļ request.user āļāļģāđāļĄāļĄāļąāļāļĨāđāļĄāđāļŦāļĨāļ§?
Celery tasks āļāļģāļāļēāļāđāļāļāļĢāļ°āļāļ§āļāļāļēāļĢāđāļĒāļāļāđāļēāļāļŦāļēāļāđāļāļĒāđāļĄāđāļĄāļĩāļŠāļīāļāļāļīāđāđāļāđāļēāļāļķāļ context āļāļāļ HTTP request āļŠāđāļ user ID āđāļāđāļ argument āļāļāļ task āđāļĨāļ°āļāļķāļ object User āļ āļēāļĒāđāļ task āļāļĒāđāļēāļŠāđāļ instance āļāļāļ Django model āđāļāļĒāļāļĢāļāđāļāđāļ arguments āļāļāļ task āđāļāļĢāļēāļ°āļāļēāļāļĨāđāļēāļŠāļĄāļąāļĒāļŦāļĢāļ·āļāđāļĄāđāļŠāļēāļĄāļēāļĢāļ serialize āđāļāđ
Q: āļāļ°āļāļāļŠāļāļ signal handlers āđāļāļāđāļĒāļāđāļāđāļāļĒāđāļēāļāđāļĢ?
Disconnect signal āđāļĢāļĩāļĒāļāļāļąāļāļāđāļāļąāļ handler āđāļāļĒāļāļĢāļāļāđāļ§āļĒ mock arguments āļāļēāļāļāļąāđāļ reconnect āđāļĄāļāļāļ Signal.disconnect() āđāļĨāļ° Signal.connect() āļāļāļ Django āļāļāļļāļāļēāļāļŠāļīāđāļāļāļĩāđ Decorator @factory.django.mute_signals āļāļēāļāđāļĨāļāļĢāļēāļĢāļĩ factory_boy āļāđāļāđāļ§āļĒāđāļāļĒāļāļēāļĢāļāļīāļāđāļŠāļĩāļĒāļ signals āļāļąāđāļ§āļāļĢāļēāļ§āļĢāļ°āļŦāļ§āđāļēāļ test setup
# tests.py
from django.test import TestCase
from django.db.models.signals import post_save
from unittest.mock import patch, MagicMock
from .models import Product
from .signals import invalidate_product_cache
class SignalTests(TestCase):
def test_cache_invalidation_called(self):
# Disconnect āđāļāļ·āđāļāļāđāļāļāļāļąāļāļāļēāļĢ firing āļāļąāļāđāļāļĄāļąāļāļī
post_save.disconnect(invalidate_product_cache, sender=Product)
try:
product = Product.objects.create(name="Test", price=100)
with patch('myapp.signals.cache') as mock_cache:
# āđāļĢāļĩāļĒāļ handler āđāļāļĒāļāļĢāļ
invalidate_product_cache(
sender=Product,
instance=product,
created=True
)
mock_cache.delete.assert_called()
finally:
# Reconnect āļŠāļģāļŦāļĢāļąāļ tests āļāļ·āđāļāđ
post_save.connect(invalidate_product_cache, sender=Product)Anti-Patterns āļāļąāđāļ§āđāļāļāļĩāđāļāļ§āļĢāļŦāļĨāļĩāļāđāļĨāļĩāđāļĒāļ
Circular signal chains āđāļāļīāļāļāļķāđāļāđāļĄāļ·āđāļ Signal A āļāļĢāļīāļāđāļāļāļĢāđ save āļāļ Model B āļāļķāđāļ signal āļāļāļāļĄāļąāļāļāļĢāļīāļāđāļāļāļĢāđ save āļāļ Model A recursion āļāļģāđāļāļīāļāļāđāļāđāļāļāļāļāļ§āđāļē stack āļāļ° overflow āļŦāļĢāļ·āļ recursion guard āļŦāļĒāļļāļāļĄāļąāļ āļāļāļāđāļāļ signals āđāļŦāđāđāļāđāļ terminal: āļāļ§āļāļĄāļąāļāļŠāļąāļāđāļāļāđāļĨāļ°āļāļāļāļŠāļāļāļ āđāļāđāđāļĄāđāļāļĢāļīāļāđāļāļāļĢāđāļāļēāļĢāđāļāļĨāļĩāđāļĒāļāđāļāļĨāļāļāļĩāđāļŠāļąāļāđāļāļāđāļāđāđāļāļīāđāļĄāđāļāļīāļĄ
āļāļēāļĢāļāļģāļāļ§āļāļŦāļāļąāļāđāļ signals āļāļĨāđāļāļāļāļļāļ request āļāļĩāđāļāļĢāļīāļāđāļāļāļĢāđ signal Signal āļāļĩāđ resize āļĢāļđāļāļ āļēāļ āļŠāļĢāđāļēāļ thumbnails āļŦāļĢāļ·āļāđāļĢāļĩāļĒāļ external APIs āļāļ§āļĢ enqueue Celery task āđāļāļ
āļāļ§āļēāļĄāļĨāđāļĄāđāļŦāļĨāļ§āļāļāļ signal āļāļĩāđāđāļāļĩāļĒāļ āļāđāļāļ bugs āđāļāļĒāļāđāļēāđāļĢāļīāđāļĄāļāđāļ Django āļāļąāļ exceptions āđāļ signal handlers āđāļĨāļ°āļāļąāļāļāļķāļāļāļ§āļāļĄāļąāļ āļāļāļļāļāļēāļāđāļŦāđ request āļāļģāđāļāļīāļāļāđāļ āļŠāļīāđāļāļāļĩāđāļāļāļāļīāļāļāđāļāļāļīāļāļāļĨāļēāļ āļāļīāļāļēāļĢāļāļēāļ§āđāļē handler āļāļĩāđāļĨāđāļĄāđāļŦāļĨāļ§āļāļ§āļĢāļĒāļāđāļĨāļīāļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļŦāļĢāļ·āļāđāļāđāļ best-effort āļāļĢāļīāļāđ
# settings.py
# āļāļģāđāļŦāđ exception āļāļāļ signal handler propagate (fail fast āđāļ development)
DEBUG = True # āđāļ dev exceptions āļāļ° propagate āđāļāļĒāļāļĢāļĢāļĄāļāļēāļāļī
# āđāļ production āđāļāđ Sentry āļŦāļĢāļ·āļāļāļĨāđāļēāļĒāļāļąāļāđāļāļ·āđāļāļāļąāļ signal errors
import sentry_sdk
sentry_sdk.init(dsn="...")āđāļĢāļīāđāļĄāļāļķāļāļāđāļāļĄāđāļĨāļĒ!
āļāļāļŠāļāļāļāļ§āļēāļĄāļĢāļđāđāļāļāļāļāļļāļāļāđāļ§āļĒāļāļąāļ§āļāļģāļĨāļāļāļŠāļąāļĄāļ āļēāļĐāļāđāđāļĨāļ°āđāļāļāļāļāļŠāļāļāđāļāļāļāļīāļāļāļĢāļąāļ
āļāļĢāļāļāļāļēāļĢāļāļąāļāļŠāļīāļāđāļāļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļāļąāļāļāļēāļĢ Event āļāļāļ Django
āļāļēāļĢāđāļĨāļ·āļāļāļĢāļ°āļŦāļ§āđāļēāļ signals āđāļĨāļ° Celery āļāļĨāļēāļĒāđāļāđāļāđāļĢāļ·āđāļāļāļāđāļēāļĒāļāđāļ§āļĒāđāļāļ§āļāļēāļāļāļĩāđāđāļāđāļāļĢāļ°āļāļ:
- āđāļāđ signals āđāļĄāļ·āđāļ: āļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļāđāļāļāđāļŠāļĢāđāļāļāđāļāļ response āđāļāđāđāļ§āļĨāļēāļāđāļāļĒāļāļ§āđāļē 50ms āđāļāļĩāđāļĒāļ§āļāđāļāļāđāļāļāļēāļ°āļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢ database āļŦāļĢāļ·āļ cache āđāļāđāļāļĢāļ·āđāļāļ āđāļĨāļ°āļāļ§āļēāļĄāļĨāđāļĄāđāļŦāļĨāļ§āļāļ§āļĢāļĒāļāđāļĨāļīāļāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļŦāļĨāļąāļ
- āđāļāđ Celery āđāļĄāļ·āđāļ: āļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļŠāļēāļĄāļēāļĢāļāđāļāļīāļāļāļķāđāļāđāļāļāļĩāđāļŠāļļāļ āđāļāļĩāđāļĒāļ§āļāđāļāļāļāļąāļ external services āđāļāđāđāļ§āļĨāļēāļĄāļēāļāļāļ§āđāļē 100ms āđāļāđāļāļĢāļ°āđāļĒāļāļāđāļāļēāļ retry logic āļŦāļĢāļ·āļāđāļĄāđāļāļ§āļĢāļāļĨāđāļāļāļāļđāđāđāļāđ
- āđāļāđ signals āļāļĩāđāļāļĢāļīāļāđāļāļāļĢāđ Celery āđāļĄāļ·āđāļ: āļāđāļāļāļāļēāļĢāļāļēāļĢāļĒāļ·āļāļĒāļąāļāļāļąāļāļāļĩāđāļāđāļāļēāļāļāļĢāļīāļāđāļāđāļ async āļŦāļĢāļ·āļāđāļĄāļ·āđāļ async tasks āļŦāļĨāļēāļĒāļāļąāļ§āļāļ§āļĢāļāļđāļ fire āļāļēāļ database event āđāļāļĩāļĒāļ§
- āļŦāļĨāļĩāļāđāļĨāļĩāđāļĒāļ signals āļāļąāđāļāļŦāļĄāļāđāļĄāļ·āđāļ: logic āļāļąāļāļāđāļāļāļāļāļāļĩāđāļāļ°āļĢāļąāļāļāļĢāļ°āļāļąāļāļāļēāļĢāđāļĢāļĩāļĒāļ service āļāļĩāđāļāļąāļāđāļāļ āđāļĄāļ·āđāļāļāļēāļĢ debugging signal chains āļāļĨāļēāļĒāđāļāđāļāđāļĢāļ·āđāļāļāļĒāļēāļ āļŦāļĢāļ·āļāđāļĄāļ·āđāļāļāļĨāđāļāļĩāļĒāļ§āļāļąāļāļŠāļēāļĄāļēāļĢāļāļāļģāđāļāđāļāđāļ§āļĒāļāļēāļĢāđāļĢāļĩāļĒāļ method āļāđāļēāļĒāđ
āļāļĩāđāļāļāļĢāđ background tasks āļāļāļ Django 6.0 āļĄāļāļāļāļēāļāđāļĨāļ·āļāļāļāļĨāļēāļ: āļĢāļāļāļĢāļąāļ async task āđāļāļāļąāļ§āđāļāļĒāđāļĄāđāļĄāļĩ overhead āļāļēāļĢāļāļģāđāļāļīāļāļāļēāļāļāļāļ Celery āļŠāļģāļŦāļĢāļąāļāđāļāļĢāđāļāđāļāļāđ greenfield āļāļĩāđāđāļĢāļīāđāļĄāļāđāļāđāļāļāļĨāļēāļĒāļāļĩ 2026 āđāļŦāđāļāļĢāļ°āđāļĄāļīāļāļ§āđāļē background tasks āļāļąāđāļāđāļāļīāļĄāļāļāļ Django āļāļĢāļāļāļēāļĄāļāđāļāļāļģāļŦāļāļāļŦāļĢāļ·āļāđāļĄāđāļāđāļāļāļāļĩāđāļāļ°āđāļāļīāđāļĄ Celery
āļāļļāļāļŦāļēāļāļąāđāļāđāļ Django āđāļāļāđāļŦāļĄ
āđāļāđāļāļāļĢāļīāļāļŦāļāļķāđāļāļāļīāđāļ āļāļąāđāļāļāļĩāđāļāđāļāļāļāļĒāļđāđāļŦāļāļķāđāļāļāļļāļ āļ§āļąāļāļĨāļ°āļŦāļāļķāđāļāļāļĢāļąāđāļ āļĨāļāļāđāļāđāđāļāļĒāđāļĄāđāļāđāļāļāļĄāļĩāļāļąāļāļāļĩ

āđāļāļĩāļĒāļāđāļāļĒ
Anthony Fillion-Mailletāļāļđāđāļāđāļāļāļąāđāļ SharpSkill
āđāļāđāļāļāļąāļāļāļąāļāļāļēāļāļđāļĨāļŠāđāļāļāļĄāļēāļāļ§āđāļē 10 āļāļĩ āļāļđāđāļĨ SharpSkill āđāļĨāļ°āļĢāļąāļāļāļīāļāļāļāļāļāļļāļāļŠāļīāđāļāļāļĩāđāđāļāļĒāđāļāļĢāđāļāļĩāđāļāļĩāđ
āļāļąāļāđāļāļāđāļĄāļ·āđāļ 2 āļāļąāļāļĒāļēāļĒāļ 2569
āđāļāđāļ
āđāļāļĢāđ
āļāļāļāļ§āļēāļĄāļāļĩāđāđāļāļĩāđāļĒāļ§āļāđāļāļ

Django āđāļĨāļ° Celery: āļāļēāļĢāļāļĢāļ°āļĄāļ§āļĨāļāļĨāļāļēāļāđāļāļāļāļ°āļāļīāļāđāļāļĢāļāļąāļŠāđāļĨāļ°āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđ 2026
āļāļđāđāļĄāļ·āļ Django Celery āļāļāļąāļāļŠāļĄāļāļđāļĢāļāđāļāļĢāđāļāļĄāļāļąāļ§āļāļĒāđāļēāļāđāļāđāļāļāļĢāļīāļ, task routing, āļāļēāļĢāļāļąāđāļāđāļ§āļĨāļē Celery Beat, āļāļēāļĢāļāļģāļŦāļāļāļāđāļē production āđāļĨāļ°āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđāļāļēāļāđāļāļāļāļīāļ 2026

Django Async Views āđāļĨāļ° ASGI āđāļāļāļĩ 2026: āļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļāđāļĨāļ°āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđ
āđāļāļēāļ°āļĨāļķāļ Django async view āđāļĨāļ° ASGI āđāļāļāļĩ 2026: āļāļĨāđāļāđāļāļ·āđāļāļāļŦāļĨāļąāļ, āđāļāļīāļĢāđāļāđāļ§āļāļĢāđāļāļĩāđāļāļ§āļĢāļāļĩāļāļĨāļāļĒ, async ORM āļāļąāļāļāļąāļāļāļąāļ SynchronousOnlyOperation āļāļĢāđāļāļĄāļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđ

Django 5.2 Custom Middleware āđāļĨāļ° Signal Handling: āļāļđāđāļĄāļ·āļāđāļāļĢāļĩāļĒāļĄāļŠāļąāļĄāļ āļēāļĐāļāđāđāļāļīāļāđāļāļāļāļīāļ
āļāļđāđāļĄāļ·āļāđāļāļīāļāļĨāļķāļ Django 5.2 custom middleware āđāļĨāļ° signal handling āļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđāđāļāļīāļāđāļāļāļāļīāļ āļāļĢāļāļāļāļĨāļļāļĄ request pipeline, async middleware, post_save, pre_save, custom signals āđāļĨāļ°āđāļāļ§āļāļēāļāļāļāļīāļāļąāļāļīāļāļĩāđāļāļĩāļŠāļģāļŦāļĢāļąāļ production