# Scheduling Tasks with Celery Beat

**Celery Beat** is a scheduler that kicks off tasks at regular intervals, which are then executed by available worker nodes in the cluster. It is a robust alternative to system-level cron jobs because the schedule is defined in your Python code, making it version-controllable and easier to deploy across different environments.

## Why use Celery Beat over Cron?

*   **Centralized Configuration:** Your schedule lives with your code, not in a separate `crontab` file on the server.
*   **Distributed Execution:** The scheduler just sends a message. Any available worker on any server can pick up the task.
*   **Dynamic:** You can change schedules dynamically if you store them in a database (using `django-celery-beat`, for example).

## Step 1: Define the Schedule

You define the schedule in your Celery configuration.

Assuming you have a file named `tasks.py` with a Celery app instance:

```python
from celery import Celery
from celery.schedules import crontab

app = Celery('tasks', broker='redis://localhost:6379/0')

@app.task
def print_hello():
    print("Hello from Celery Beat!")

# Configure the schedule
app.conf.beat_schedule = {
    # Name of the schedule entry
    'say-hello-every-30-seconds': {
        'task': 'tasks.print_hello',
        'schedule': 30.0, # Run every 30 seconds
        'args': (),
    },
    # Using crontab syntax
    'run-every-morning': {
        'task': 'tasks.print_hello',
        'schedule': crontab(hour=7, minute=30), # Run daily at 7:30 AM
        'args': (),
    },
}

# Set timezone (Important for crontab schedules!)
app.conf.timezone = 'UTC'
```

## Step 2: Understanding Schedules

### Interval
Simple float/integer values represent seconds.
`'schedule': 10.0` -> Every 10 seconds.

### Crontab
The `crontab` class allows for complex schedules similar to Unix cron.

```python
from celery.schedules import crontab

# Every minute
crontab(minute='*')

# Every hour at minute 0 (e.g., 1:00, 2:00)
crontab(minute=0, hour='*')

# Every Monday at 8:00 AM
crontab(hour=8, minute=0, day_of_week=1)
```

## Step 3: Running the Services

Celery Beat requires two processes to run:

1.  **The Worker:** Executes the tasks.
2.  **The Beat Scheduler:** Triggers the tasks.

You can run them in separate terminals.

**Terminal 1 (Worker):**
```bash
celery -A tasks worker --loglevel=INFO
```

**Terminal 2 (Beat):**
```bash
celery -A tasks beat --loglevel=INFO
```

*Note: In development, you can run them together using the `-B` flag, but this is not recommended for production.*
```bash
celery -A tasks worker --loglevel=INFO -B
```

## Production Considerations

*   **Single Instance:** You must ensure only **one** instance of Celery Beat is running at a time, otherwise tasks will be duplicated.
*   **Persistence:** By default, Beat creates a local file named `celerybeat-schedule` to keep track of the last run times. Ensure the process has write access to the current directory or configure a specific path.

[[programming/python/celery]]