Skip to content

Configuration

Everything django-absurd reads lives under Django's TASKS setting.

settings.py
TASKS = {
    "default": {
        "BACKEND": "django_absurd.backends.AbsurdBackend",
        "QUEUES": ["default"],  # optional
        "OPTIONS": {  # optional
            "DATABASE": "default",
        },
    },
}

Declaring queues

Declare queues in one place — never both.

QUEUES (list) — just the names. Use this when queues need no special policy:

"QUEUES": ["default", "reports", "emails"]

OPTIONS["QUEUES"] (map) — names → per-queue policy (absurd_sdk.CreateQueueOptions). Use this to set retention (cleanup_ttl / cleanup_limit):

"OPTIONS": {"QUEUES": {
    "default": {},
    "reports": {"cleanup_ttl": "7 days"},
}}

Declared queues are provisioned at migrate, by manage.py absurd_sync_queues, and by dj_absurd.sync_queues() in tests — nothing else creates one. enqueue and a starting worker both refuse an unprovisioned queue.

  • Setting both forms is a configuration error (absurd.E002). Undeclared queue names are rejected, never silently created.
  • storage_mode="partitioned" is refused as a configuration error (absurd.E015), and so are its partition-only policy keys (partition_lookahead, partition_lookback, detach_mode, detach_min_age). Support is tracked at https://github.com/lincolnloop/django-absurd/issues/216.

Absurd: storage (queue types, partitioning, retention).

Backend OPTIONS

All optional:

Option Default What it does
DATABASE "default" Which DATABASES alias to use.
DEFAULT_MAX_ATTEMPTS 5 Retry ceiling per task; must be an integer >= 1 (override per task/call — see Tasks).
QUEUES Map of queue name → policy (above). Mutually exclusive with the top-level list.
CLEANUP Map {"schedule": "<cron>"} to run cleanup on cadence (beat: in-process; pg_cron: native job). Omit to skip. See Cleanup.
SCHEDULE Recurring task schedules (beat or pg_cron). See Cron Jobs.
SYNC_SCHEDULES_ON_MIGRATE True (pg_cron) Reconcile SCHEDULE into pg_cron on migrate. See Cron Jobs.
SYNC_SCHEDULES_ON_TEST_DB False (pg_cron) Allow that migrate-time sync on a test database. See Cron Jobs.
PG_CRON_ON_TEST_DB False (pg_cron) Opt in to real cron.* writes on a test database / active test run — otherwise every such write is a no-op. See Cron Jobs.
ENABLE_ADMIN True Register the read-only Absurd models in the Django admin.
ADMIN_SITE ("django.contrib.admin.site",) Dotted paths to the AdminSite(s) to register on.

Non-default database

settings.py
DATABASE_ROUTERS = ["django_absurd.routers.AbsurdRouter"]

Only when DATABASE names an alias other than "default". The router sends django-absurd's schema and queries there.

Validate it

python manage.py check django_absurd

Verifies the configuration. Fix what it reports rather than silencing it, unless a check's own hint says otherwise:

ID Means
absurd.E001 Backend / database misconfiguration.
absurd.E002 QUEUES declared in both the top level and OPTIONS.
absurd.E003 Invalid per-queue policy options.
absurd.E004 More than one Absurd backend is configured. django-absurd supports exactly one per project.
absurd.E005 AbsurdRouter missing from DATABASE_ROUTERS.
absurd.E006 ENABLE_ADMIN isn't a bool, or ADMIN_SITE doesn't resolve to AdminSites.
absurd.E007 Invalid SCHEDULE entry (see Cron Jobs).
absurd.E009 OPTIONS["DEFAULT_MAX_ATTEMPTS"] is not an integer >= 1.
absurd.E010 Invalid CLEANUP configuration (not a {"schedule": …} map, unknown keys, or a cron expression the configured scheduler cannot run) (see Cleanup).
absurd.E011 SYNC_SCHEDULES_ON_TEST_DB is True without PG_CRON_ON_TEST_DB (see Cron Jobs).
absurd.E012 The central cron.database_name database is unreachable or missing the pg_cron extension — a deploy-time check, quiet under a test suite unless PG_CRON_ON_TEST_DB (see Cron Jobs).
absurd.E013 "django_absurd.pg_cron" is installed but no AbsurdBackend is configured — schedules would save and never fire (see Cron Jobs).
absurd.E014 OPTIONS["QUEUES"] is not a mapping of queue name to policy options — the bare name list belongs at the top level, as QUEUES.
absurd.E015 storage_mode="partitioned" or a partition-only policy key (partition_lookahead, partition_lookback, detach_mode, detach_min_age) is declared — partitioned queues are not supported. Track at https://github.com/lincolnloop/django-absurd/issues/216.
absurd.W003 (Warning) django_absurd.pg_cron is ordered before django_absurd in INSTALLED_APPS (see Cron Jobs).

Exceptions

from django_absurd.exceptions import DjangoAbsurdError

try:
    emit_event("warehouse.packed:42", queue="reports")
except DjangoAbsurdError:
    ...

Typed errors under DjangoAbsurdError: QueueNotDeclaredError (never declared) and QueueNotProvisionedError (declared, no table yet — run manage.py absurd_sync_queues), raised by enqueue, by a starting worker, by emit_event and by the test fixture's drain() and get_result(); and SchemaNotInstalledError (the Absurd schema itself isn't installed — run manage.py migrate).

  • enqueue raises QueueNotDeclaredError only when QUEUES is empty or unset. With QUEUES configured, a typo is rejected earlier as Django's own InvalidTask.
  • Every absurd_* management command turns a fixed set of configuration failures — ImproperlyConfigured, BackendNotConfiguredError, MultipleBackendsConfiguredError, SchemaNotInstalledError, QueueNotDeclaredError, QueueNotProvisionedError — into a CommandError; --traceback still shows the original. Every other error, including any other DjangoAbsurdError subclass, keeps its own type and full traceback.
  • The hierarchy isn't total — other failures still raise plain ImproperlyConfigured / RuntimeError / TypeError.