Django Signals vs Celery Tasks 2026: āđ€āļĄāļ·āđˆāļ­āđ„āļŦāļĢāđˆāļ„āļ§āļĢāđƒāļŠāđ‰āļ­āļ°āđ„āļĢ

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āļ§āđˆāļēāđ€āļĄāļ·āđˆāļ­āđ„āļŦāļĢāđˆāļ„āļ§āļĢāđƒāļŠāđ‰ Django signals āđ€āļ—āļĩāļĒāļšāļāļąāļš Celery tasks āļ„āļĢāļ­āļšāļ„āļĨāļļāļĄāļāļēāļĢāļˆāļąāļ”āļāļēāļĢ event āđāļšāļš synchronous vs asynchronous āļœāļĨāļāļĢāļ°āļ—āļšāļ”āđ‰āļēāļ™āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž āđāļĨāļ°āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļŠāļģāļŦāļĢāļąāļšāļ™āļąāļāļžāļąāļ’āļ™āļē Django

āđ„āļ”āļ­āļ°āđāļāļĢāļĄāļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄ Django signals vs Celery tasks āđāļŠāļ”āļ‡āļĢāļđāļ›āđāļšāļšāļāļēāļĢāļˆāļąāļ”āļāļēāļĢ event āđāļšāļš synchronous āđāļĨāļ° asynchronous

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 āđ€āļ”āļĩāļĒāļ§āļāļąāļ™

python
# 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 āļŠāļģāđ€āļĢāđ‡āļˆāđ€āļ—āđˆāļēāļ™āļąāđ‰āļ™:

python
# 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 āđ€āļ”āļīāļĄ

python
# 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 SignalsCelery Tasks
āļāļēāļĢāļ—āļģāļ‡āļēāļ™Synchronous āļāļĢāļ°āļšāļ§āļ™āļāļēāļĢāđ€āļ”āļĩāļĒāļ§Asynchronous āļāļĢāļ°āļšāļ§āļ™āļāļēāļĢ worker
āļœāļĨāļāļĢāļ°āļ—āļš latencyāđ€āļžāļīāđˆāļĄāđ€āļ§āļĨāļē request~1-5ms overhead enqueue
āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļ„āļ§āļēāļĄāļĨāđ‰āļĄāđ€āļŦāļĨāļ§āļ—āļģāļĨāļēāļĒ requestRetry āļ­āļĒāđˆāļēāļ‡āļ­āļīāļŠāļĢāļ°
āļ‚āļ­āļšāđ€āļ‚āļ• transactionāļ āļēāļĒāđƒāļ™ transactionāļ āļēāļĒāļ™āļ­āļ transaction
āļāļēāļĢāđ€āļĢāļĩāļĒāļ external servicesāļšāļĨāđ‡āļ­āļ responseāļ—āļģāļ‡āļēāļ™āđƒāļ™ background
āļ„āļ§āļēāļĄāļ‹āļąāļšāļ‹āđ‰āļ­āļ™Setup āļ™āđ‰āļ­āļĒāļ—āļĩāđˆāļŠāļļāļ”āļ•āđ‰āļ­āļ‡āļāļēāļĢ broker + workers

āđ€āļĄāļ·āđˆāļ­āđ„āļŦāļĢāđˆāļ—āļĩāđˆ Signals āđ€āļ›āđ‡āļ™āļ—āļēāļ‡āđ€āļĨāļ·āļ­āļāļ—āļĩāđˆāļ–āļđāļāļ•āđ‰āļ­āļ‡

Signals āđ€āļŦāļĄāļēāļ°āļāļąāļšāļŠāļ–āļēāļ™āļāļēāļĢāļ“āđŒāļ—āļĩāđˆ side effect āļ•āđ‰āļ­āļ‡āđ€āļŠāļĢāđ‡āļˆāļāđˆāļ­āļ™āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāļ•āđˆāļ­ āđāļĨāļ°āđ€āļĄāļ·āđˆāļ­āļ„āļ§āļēāļĄāļĨāđ‰āļĄāđ€āļŦāļĨāļ§āļ„āļ§āļĢāļĒāļāđ€āļĨāļīāļāļāļēāļĢāļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢ

Cache invalidation āļ—āļģāļ‡āļēāļ™āđ„āļ”āđ‰āļ”āļĩāļāļąāļš signals āđ€āļĄāļ·āđˆāļ­ Product āļ–āļđāļāļ­āļąāļžāđ€āļ”āļ— āļāļēāļĢāđāļŠāļ”āļ‡āļ—āļĩāđˆāļ–āļđāļ cache āļ•āđ‰āļ­āļ‡āļ–āļđāļ invalidate āļ—āļąāļ™āļ—āļĩ cache āļ—āļĩāđˆāđ€āļāđˆāļēāđāļĄāđ‰āđ€āļžāļĩāļĒāļ‡āđ„āļĄāđˆāļāļĩāđˆāļ§āļīāļ™āļēāļ—āļĩāļ—āļģāđƒāļŦāđ‰āđāļŠāļ”āļ‡āļĢāļēāļ„āļēāļŦāļĢāļ·āļ­āļˆāļģāļ™āļ§āļ™āļŠāļīāļ™āļ„āđ‰āļēāļ„āļ‡āļ„āļĨāļąāļ‡āļ—āļĩāđˆāđ„āļĄāđˆāļ–āļđāļāļ•āđ‰āļ­āļ‡

python
# 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 āļ‚āļ­āļ‡āļžāļ§āļāđ€āļ‚āļēāļŠāđ‰āļēāļĨāļ‡ āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™āļāđ‡āļŠāđ‰āļēāļĨāļ‡

python
# 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 āļŠāļģāļŦāļĢāļąāļšāļ‡āļēāļ™āļŦāļ™āļąāļāļˆāļĢāļīāļ‡āđ†

python
# 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

python
# 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 āļˆāļĢāļīāļ‡āđ†

python
# 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

āđ€āļ‚āļĩāļĒāļ™āđ‚āļ”āļĒ

Anthony Fillion-Maillet

āļœāļđāđ‰āļāđˆāļ­āļ•āļąāđ‰āļ‡ SharpSkill

āđ€āļ›āđ‡āļ™āļ™āļąāļāļžāļąāļ’āļ™āļēāļŸāļđāļĨāļŠāđāļ•āļāļĄāļēāļāļ§āđˆāļē 10 āļ›āļĩ āļ”āļđāđāļĨ SharpSkill āđāļĨāļ°āļĢāļąāļšāļœāļīāļ”āļŠāļ­āļšāļ—āļļāļāļŠāļīāđˆāļ‡āļ—āļĩāđˆāđ€āļœāļĒāđāļžāļĢāđˆāļ—āļĩāđˆāļ™āļĩāđˆ

āļ­āļąāļ›āđ€āļ”āļ•āđ€āļĄāļ·āđˆāļ­ 2 āļāļąāļ™āļĒāļēāļĒāļ™ 2569

āđāļ—āđ‡āļ

#django
#celery
#signals
#async
#python
#best-practices

āđāļŠāļĢāđŒ

āļšāļ—āļ„āļ§āļēāļĄāļ—āļĩāđˆāđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡

Django āđāļĨāļ° Celery āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāļ‡āļēāļ™āđāļšāļšāļ­āļ°āļ‹āļīāļ‡āđ‚āļ„āļĢāļ™āļąāļŠ

Django āđāļĨāļ° Celery: āļāļēāļĢāļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāļ‡āļēāļ™āđāļšāļšāļ­āļ°āļ‹āļīāļ‡āđ‚āļ„āļĢāļ™āļąāļŠāđāļĨāļ°āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ 2026

āļ„āļđāđˆāļĄāļ·āļ­ Django Celery āļ‰āļšāļąāļšāļŠāļĄāļšāļđāļĢāļ“āđŒāļžāļĢāđ‰āļ­āļĄāļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āđ‚āļ„āđ‰āļ”āļˆāļĢāļīāļ‡, task routing, āļāļēāļĢāļ•āļąāđ‰āļ‡āđ€āļ§āļĨāļē Celery Beat, āļāļēāļĢāļāļģāļŦāļ™āļ”āļ„āđˆāļē production āđāļĨāļ°āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāļ—āļēāļ‡āđ€āļ—āļ„āļ™āļīāļ„ 2026

āļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄ Django async view āđāļĨāļ° ASGI āļ—āļĩāđˆāļˆāļąāļ”āļāļēāļĢāļ„āļģāļ‚āļ­āļžāļĢāđ‰āļ­āļĄāļāļąāļ™āļŦāļĨāļēāļĒāļ„āļģāļ‚āļ­

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: āļ„āļđāđˆāļĄāļ·āļ­āđ€āļ•āļĢāļĩāļĒāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāđ€āļŠāļīāļ‡āđ€āļ—āļ„āļ™āļīāļ„

āļ„āļđāđˆāļĄāļ·āļ­āđ€āļŠāļīāļ‡āļĨāļķāļ Django 5.2 custom middleware āđāļĨāļ° signal handling āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļ“āđŒāđ€āļŠāļīāļ‡āđ€āļ—āļ„āļ™āļīāļ„ āļ„āļĢāļ­āļšāļ„āļĨāļļāļĄ request pipeline, async middleware, post_save, pre_save, custom signals āđāļĨāļ°āđāļ™āļ§āļ—āļēāļ‡āļ›āļāļīāļšāļąāļ•āļīāļ—āļĩāđˆāļ”āļĩāļŠāļģāļŦāļĢāļąāļš production