# Background Tasks

> Background Tasks

- Skill: `ffsshhttiikk/background-tasks` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ffsshhttiikk/background-tasks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ffsshhttiikk/background-tasks/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ffsshhttiikk (https://skillmd.com/u/ffsshhttiikk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ffsshhttiikk/background-tasks

---

# Background Tasks

**Category:** Backend Development  
**Skill Level:** Intermediate  
**Domain:** Asynchronous Processing, Task Queues, Distributed Systems

## Overview

Background Tasks are asynchronous operations that execute independently of the main request-response cycle, enabling applications to handle long-running processes, scheduled jobs, and event-driven workflows without blocking user-facing operations or degrading performance.

## Description

Background task processing is essential for building responsive applications that can handle computationally intensive operations, external API calls, batch processing, and scheduled maintenance without impacting user experience. By offloading work to asynchronous workers, applications can accept requests quickly, process them in the background, and optionally notify users upon completion through webhooks, polling, or websocket connections.

Task queue systems provide the infrastructure for distributing work across multiple workers, managing retries for failed tasks, and ensuring at-least-once or exactly-once delivery semantics. Celery remains a dominant choice for Python applications, offering robust support for scheduled tasks (beat), task routing, and result storage. For cloud-native environments, managed services like AWS SQS, Google Cloud Tasks, and Azure Queue Storage provide fully-managed queue infrastructure, while serverless platforms enable event-driven task execution through AWS Lambda, Google Cloud Functions, or Azure Functions.

Message brokers serve as the backbone of reliable task queue systems, providing persistence, ordering guarantees, and delivery semantics. RabbitMQ offers flexible routing with exchanges and queues, while Redis provides lightweight in-memory queuing with pub/sub capabilities. Apache Kafka excels at high-throughput event streaming with durability guarantees, making it suitable for event-sourced architectures and real-time data pipelines.

Error handling and retry strategies are critical for production-grade background task systems. Exponential backoff with jitter prevents thundering herd problems during outages, while dead letter queues capture failed tasks for later analysis and replay. Monitoring task latency, throughput, failure rates, and queue depths through metrics and alerts enables proactive identification of bottlenecks and failures before they impact users.

## Prerequisites

- Understanding of asynchronous programming concepts
- Familiarity with message queue patterns and broker technologies
- Knowledge of distributed systems challenges (idempotency, consistency)
- Experience with monitoring and observability practices

## Core Competencies

- Designing task schemas with idempotency and retry handling
- Implementing task queues using Celery, RQ, or similar frameworks
- Configuring scheduled tasks and cron-like execution
- Setting up dead letter queues and error handling workflows
- Monitoring task health, latency, and throughput
- Scaling worker processes for varying workloads

## Implementation

```python
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from enum import Enum
from typing import Any, Callable, Dict, Optional, List
import json
import uuid
import time
from concurrent.futures import ThreadPoolExecutor

class TaskStatus(Enum):
    PENDING = "pending"
    QUEUED = "queued"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    RETRYING = "retrying"

@dataclass
class Task:
    id: str
    name: str
    payload: Dict[str, Any]
    status: TaskStatus = TaskStatus.PENDING
    max_retries: int = 3
    retry_count: int = 0
    retry_delay: int = 60
    created_at: datetime = field(default_factory=datetime.now)
    started_at: Optional[datetime] = None
    completed_at: Optional[datetime] = None
    result: Any = None
    error: Optional[str] = None

class TaskHandler:
    def get_task_name(self) -> str:
        return self.__class__.__name__.lower().replace("handler", "")
    
    def execute(self, payload: Dict[str, Any]) -> Any:
        raise NotImplementedError

class BackgroundTask:
    def __init__(self, max_workers: int = 4):
        self.max_workers = max_workers
        self.task_queue: List[Task] = []
        self.executor = ThreadPoolExecutor(max_workers=max_workers)
        self.handlers: Dict[str, TaskHandler] = {}
        self.results: Dict[str, Task] = {}
    
    def register_handler(self, handler: TaskHandler):
        self.handlers[handler.get_task_name()] = handler
    
    def enqueue(
        self,
        task_name: str,
        payload: Dict[str, Any],
        priority: int = 0,
        max_retries: Optional[int] = None
    ) -> str:
        task = Task(
            id=str(uuid.uuid4()),
            name=task_name,
            payload=payload,
            max_retries=max_retries or 3
        )
        self.task_queue.append(task)
        return task.id
    
    def process_queue(self):
        while self.task_queue:
            priority, task = self.task_queue.pop(0)
            self._execute_task(task)
    
    def _execute_task(self, task: Task):
        task.status = TaskStatus.RUNNING
        task.started_at = datetime.now()
        self.results[task.id] = task
        
        handler = self.handlers.get(task.name)
        if not handler:
            task.status = TaskStatus.FAILED
            task.error = f"No handler for: {task.name}"
            return
        
        try:
            task.result = handler.execute(task.payload)
            task.status = TaskStatus.COMPLETED
            task.completed_at = datetime.now()
        except Exception as e:
            task.error = str(e)
            task.retry_count += 1
            if task.retry_count >= task.max_retries:
                task.status = TaskStatus.FAILED
            else:
                task.status = TaskStatus.RETRYING
    
    def get_task_status(self, task_id: str) -> Optional[Task]:
        return self.results.get(task_id)

class EmailHandler(TaskHandler):
    def execute(self, payload: Dict[str, Any]) -> Any:
        to = payload.get("to")
        subject = payload.get("subject")
        return {"status": "sent", "to": to, "subject": subject}

task_system = BackgroundTask(max_workers=4)
task_system.register_handler(EmailHandler())
task_id = task_system.enqueue("email", {"to": "user@example.com", "subject": "Welcome!"})
```

## Use Cases

- Sending welcome emails and notifications after user registration
- Processing file uploads, image resizing, and video transcoding
- Aggregating analytics data and generating reports on schedules
- Syncing data with external systems through batch operations
- Running health checks and monitoring probes on schedules
- Cleaning up expired sessions and temporary data

## Artifacts

- Celery task configurations and beat schedules
- AWS Lambda functions for serverless task processing
- Kubernetes CronJob manifests
- Task monitoring dashboards (Prometheus/Grafana)
- Dead letter queue handlers and replay scripts

## Related Skills

- Message Queues
- Celery
- Scheduled Jobs
- Distributed Systems
- Retry Patterns

