Django e Celery: Processamento Assíncrono de Tarefas e Perguntas de Entrevista 2026

Guia completo de Django e Celery com configuração, filas, Celery Beat, deploy em produção e perguntas de entrevista técnica para desenvolvedores Python em 2026.

Django e Celery processamento assíncrono de tarefas

Django e Celery representam uma das combinações mais poderosas do ecossistema Python para processamento assíncrono de tarefas. Em aplicações web modernas, operações como envio de e-mails, geração de relatórios e processamento de imagens não podem bloquear o ciclo de requisição-resposta sem comprometer a experiência do usuário. O Celery resolve esse problema ao permitir que tarefas demoradas sejam executadas em segundo plano, em workers dedicados, enquanto o servidor HTTP responde imediatamente ao cliente. Com a chegada do Django 6.0 e seu sistema nativo de tarefas em segundo plano, o cenário evolui — mas o Celery permanece como a solução mais robusta e completa para cenários de produção em larga escala.

Conceito fundamental

O Celery desacopla operações custosas do ciclo requisição-resposta. Uma view Django despacha uma tarefa para um message broker (Redis ou RabbitMQ), e um processo worker separado a executa de forma assíncrona. Esse padrão gerencia envio de e-mails, geração de relatórios, processamento de imagens e qualquer carga de trabalho que bloquearia o usuário.

Como o Celery se integra ao Django

A integração entre Django e Celery exige três componentes fundamentais: a instância da aplicação Celery, um message broker (geralmente Redis ou RabbitMQ) e a configuração no settings.py. O primeiro passo é criar o arquivo de configuração do Celery na raiz do projeto Django.

python
# myproject/celery.py
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

O método autodiscover_tasks() percorre todas as apps instaladas procurando módulos tasks.py, registrando automaticamente as tarefas encontradas. A configuração do broker e do backend de resultados fica no settings.py:

python
# myproject/settings.py
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'UTC'

O Redis é a escolha mais comum como broker por sua simplicidade e performance. O CELERY_RESULT_BACKEND permite armazenar o resultado das tarefas para consulta posterior — útil para tarefas que retornam dados processados. A separação entre dois bancos Redis (db 0 e db 1) evita colisões entre mensagens do broker e resultados armazenados.

Escrevendo e despachando tarefas

Uma tarefa Celery é uma função Python decorada com @shared_task. O decorator @shared_task é preferido em projetos Django porque não depende de uma instância específica da aplicação Celery, o que facilita reutilização e testes.

python
# orders/tasks.py
from celery import shared_task
from django.core.mail import send_mail
from orders.models import Order

@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_order_confirmation(self, order_id: int) -> str:
    """Send confirmation email for a completed order."""
    try:
        order = Order.objects.select_related('user').get(id=order_id)
        send_mail(
            subject=f'Order #{order.id} Confirmed',
            message=f'Your order totaling {order.total} has been confirmed.',
            from_email='noreply@example.com',
            recipient_list=[order.user.email],
        )
        return f'Email sent for order {order_id}'
    except Order.DoesNotExist:
        return f'Order {order_id} not found'
    except Exception as exc:
        # Retry on transient failures (SMTP timeout, etc.)
        raise self.retry(exc=exc)

Alguns padrões importantes aparecem nesse exemplo. O parâmetro bind=True torna a instância da tarefa acessível via self, permitindo chamadas como self.retry(). O max_retries=3 limita o número de tentativas, e o default_retry_delay=60 define um intervalo de 60 segundos entre cada tentativa. A tarefa recebe apenas o order_id (um inteiro), não o objeto completo — isso é fundamental porque os argumentos são serializados em JSON para transmissão via broker.

O despacho da tarefa na view é feito com o método .delay():

python
# orders/views.py
from orders.tasks import send_order_confirmation

def complete_order(request, order_id):
    # ... process payment, update order status ...
    send_order_confirmation.delay(order_id)
    return redirect('order_success', order_id=order_id)

A chamada .delay(order_id) envia a mensagem ao broker e retorna imediatamente, sem esperar a execução da tarefa. Para controle mais granular, pode-se usar .apply_async() com parâmetros como countdown, eta ou queue.

Roteamento de tarefas e gerenciamento de filas

Em aplicações de grande porte, misturar tarefas rápidas (notificações) com tarefas lentas (relatórios) em uma única fila causa gargalos. O roteamento de tarefas resolve isso direcionando cada tipo de tarefa para uma fila específica:

python
# myproject/settings.py
CELERY_TASK_ROUTES = {
    'orders.tasks.send_order_confirmation': {'queue': 'notifications'},
    'reports.tasks.generate_monthly_report': {'queue': 'reports'},
    'images.tasks.resize_upload': {'queue': 'media'},
}

Cada fila pode ter workers dedicados com configurações de concorrência adequadas ao tipo de trabalho:

bash
# Start notification worker (fast tasks, high concurrency)
celery -A myproject worker -Q notifications -c 8 --loglevel=info

# Start report worker (slow tasks, limited concurrency)
celery -A myproject worker -Q reports -c 2 --loglevel=info

# Start media worker (CPU-bound, prefork pool)
celery -A myproject worker -Q media -c 4 -P prefork --loglevel=info

A separação em filas oferece vantagens operacionais significativas: permite escalar workers independentemente, isolar falhas e ajustar a concorrência conforme a natureza da tarefa. Workers de notificação podem rodar com alta concorrência (I/O-bound), enquanto workers de processamento de mídia precisam de menos processos paralelos para evitar consumo excessivo de CPU.

Pronto para mandar bem nas entrevistas de Django?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Tarefas periódicas com Celery Beat

O Celery Beat é o agendador nativo do Celery, funcionando de forma análoga ao cron do Linux, mas integrado ao ecossistema Django. Ele permite definir tarefas que executam em intervalos regulares ou horários específicos:

python
# myproject/settings.py
from celery.schedules import crontab

CELERY_BEAT_SCHEDULE = {
    'cleanup-expired-sessions': {
        'task': 'accounts.tasks.cleanup_expired_sessions',
        'schedule': crontab(hour=3, minute=0),  # Daily at 3 AM UTC
    },
    'sync-inventory': {
        'task': 'inventory.tasks.sync_external_inventory',
        'schedule': 300.0,  # Every 5 minutes
    },
    'generate-weekly-digest': {
        'task': 'notifications.tasks.send_weekly_digest',
        'schedule': crontab(hour=9, minute=0, day_of_week='monday'),
    },
}

O Beat deve ser executado como um processo separado:

bash
celery -A myproject beat --loglevel=info

Um ponto crítico: o Celery Beat deve rodar em uma única instância. Em ambientes com múltiplos servidores, é necessário garantir que apenas um processo Beat esteja ativo para evitar duplicação de tarefas. Extensões como django-celery-beat permitem armazenar os schedules no banco de dados e gerenciá-los via Django Admin.

Monitoramento com Flower

Flower é a ferramenta padrão de monitoramento para clusters Celery. Fornece uma interface web em tempo real com informações sobre workers, tarefas ativas, histórico de execuções e métricas de performance.

bash
# Install and run Flower
pip install flower
celery -A myproject flower --port=5555

Através do Flower, é possível inspecionar o estado de cada worker, verificar tarefas pendentes em cada fila, analisar taxas de sucesso e falha, e até revogar tarefas em execução. Em produção, recomenda-se proteger o acesso ao Flower com autenticação e configurar alertas baseados em métricas como tamanho de fila e tempo médio de execução.

O Celery 5.6 também introduziu melhorias na journalização estruturada compatíveis com agregadores de logs JSON como Datadog ou stacks ELK, oferecendo eficiência de debug superior de 30% segundo as notas de lançamento.

Django 6.0: tarefas nativas vs Celery

O Django 6.0 introduziu o módulo django.tasks, oferecendo suporte nativo a tarefas em segundo plano sem dependências externas. A API é mais simples: basta decorar uma função e despachá-la. Para aplicações de menor complexidade, essa abordagem elimina a necessidade de configurar broker, workers e processos adicionais.

No entanto, o sistema nativo do Django ainda apresenta limitações importantes quando comparado ao Celery:

  • Processamento distribuído em múltiplas máquinas
  • Filas prioritárias e roteamento de tarefas
  • Limitação de taxa e políticas de retry avançadas
  • Agendamento periódico (Celery Beat)
  • Rastreamento de resultados com backends configuráveis
  • Workflows canvas (chains, groups, chords) para orquestração de tarefas complexas

A recomendação prática para 2026: utilizar django.tasks para operações simples e pontuais, e manter o Celery para pipelines complexas e cenários de alta disponibilidade.

Perguntas frequentes em entrevistas técnicas

As entrevistas para posições de backend Python em 2026 frequentemente abordam o processamento assíncrono com Django e Celery. As perguntas a seguir são extraídas de cenários reais de entrevistas Django em empresas de diversos portes.

P: O que acontece quando um worker Celery falha no meio de uma tarefa?

O comportamento depende da configuração de CELERY_TASK_ACKS_LATE. Com o valor padrão (False), a mensagem é confirmada (acknowledged) antes da execução — se o worker falhar, a tarefa é perdida. Com acks_late=True, a confirmação ocorre apenas após a conclusão, permitindo redelivery automático pelo broker.

P: Qual a diferença entre @shared_task e @app.task?

O @shared_task cria tarefas independentes de uma instância específica da aplicação Celery, sendo ideal para apps Django reutilizáveis. O @app.task vincula a tarefa diretamente à instância, o que pode causar problemas de importação circular em projetos Django.

P: Como garantir idempotência em tarefas Celery?

Tarefas devem ser projetadas para produzir o mesmo resultado mesmo quando executadas múltiplas vezes. Estratégias incluem: verificar o estado atual antes de modificar, usar chaves de deduplicação no banco de dados, e evitar efeitos colaterais não reversíveis.

P: Quando usar countdown vs eta no despacho de tarefas?

O countdown define um atraso relativo em segundos a partir do momento do despacho. O eta define um horário absoluto (datetime) para execução. Ambos são úteis para throttling e agendamento pontual.

P: Como o Celery lida com tarefas que demoram mais que o esperado?

Os parâmetros CELERY_TASK_TIME_LIMIT e CELERY_TASK_SOFT_TIME_LIMIT controlam isso. O soft limit levanta uma exceção SoftTimeLimitExceeded que pode ser tratada no código. O hard limit mata o processo incondicionalmente.

P: Qual a diferença entre o django.tasks do Django 6.0 e o Celery?

O django.tasks oferece uma API simplificada sem dependências externas, ideal para operações simples. O Celery oferece roteamento de filas, agendamento periódico, primitivas de workflow (chains, groups, chords) e um ecossistema maduro de monitoramento.

Checklist de deploy em produção

A configuração para ambientes de produção exige atenção a parâmetros de segurança, performance e resiliência:

python
# myproject/settings.py — Production configuration
CELERY_TASK_ALWAYS_EAGER = False  # Never True in production
CELERY_TASK_ACKS_LATE = True  # Redelivery on worker crash
CELERY_WORKER_PREFETCH_MULTIPLIER = 1  # Fair scheduling
CELERY_TASK_REJECT_ON_WORKER_LOST = True  # Reject on unexpected exit
CELERY_TASK_TIME_LIMIT = 300  # Hard kill after 5 minutes
CELERY_TASK_SOFT_TIME_LIMIT = 240  # SoftTimeLimitExceeded after 4 min
CELERY_WORKER_MAX_TASKS_PER_CHILD = 1000  # Prevent memory leaks
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True

O parâmetro WORKER_MAX_TASKS_PER_CHILD reinicia os processos workers após 1000 tarefas, prevenindo vazamentos de memória — um problema que o Celery 5.6 corrigiu de forma mais abrangente com seus patches de memory leak.

Os workers devem ser gerenciados como serviços do sistema para garantir reinício automático em caso de falha:

ini
# /etc/systemd/system/celery-worker.service
[Unit]
Description=Celery Worker
After=network.target redis.service

[Service]
Type=forking
User=django
Group=django
WorkingDirectory=/opt/myproject
ExecStart=/opt/myproject/venv/bin/celery -A myproject worker \
    --loglevel=info --concurrency=4 --pidfile=/var/run/celery/worker.pid
ExecStop=/bin/kill -s TERM $MAINPID
Restart=always

[Install]
WantedBy=multi-user.target

Itens essenciais do checklist de produção incluem: configurar CELERY_TASK_ACKS_LATE=True para evitar perda de tarefas, definir time limits para prevenir workers travados, habilitar MAX_TASKS_PER_CHILD para mitigar vazamentos de memória, utilizar supervisord ou systemd para gerenciamento de processos, configurar monitoramento com Flower ou Prometheus, e manter o Redis com persistência habilitada.

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Conclusão

  • Celery 5.6.3 (março 2026) traz correções de vazamentos de memória, journalização estruturada, suporte a filas de quórum e compatibilidade com psycopg3 — a atualização a partir de versões anteriores é fortemente recomendada.
  • Sempre passar chaves primárias para as tarefas, nunca objetos ORM. Isso previne erros de serialização e dados obsoletos.
  • Rotear tarefas para filas dedicadas com base nas características de carga. Notificações rápidas e relatórios lentos nunca devem competir pelos mesmos workers.
  • Usar acks_late=True combinado com design idempotente de tarefas para cargas críticas que devem sobreviver a falhas de workers.
  • Definir time_limit e soft_time_limit em cada tarefa para impedir que workers travados consumam recursos indefinidamente.
  • Django 6.0 gerencia tarefas simples em segundo plano nativamente; o Celery permanece necessário para processamento distribuído, agendamento e workflows canvas.
  • Monitorar a profundidade das filas e as taxas de retry com Flower ou agregação de logs estruturados para detectar problemas de capacidade antes que afetem os usuários.

Tags

#django
#celery
#python
#async
#interview

Compartilhar

Artigos relacionados