Worker never establishes LISTEN subscription for task queue — all tasks stuck in "queued" indefinitely (reproduces on 2026.8.0 and 2026.8.2)
Describe the bug
After upgrading to 2026.8.0, all background tasks began sitting permanently in state=queued and never executing. This is not specific to one task type — it affects LDAP sync, outpost config updates (outpost_send_update, outpost_controller), blueprint discovery, and certificate discovery equally. The worker process itself is healthy throughout (health endpoint returns 200 consistently, sockets present, threads spawned correctly), but nothing is ever consumed from the queue.
Root cause appears to be that the worker never registers a Postgres LISTEN subscription on the channel the enqueue trigger notifies on, even though the trigger itself fires correctly every time.
The pgtrigger function pgtrigger_notify_enqueueing_ is present, enabled (tgenabled='O'), and its source correctly calls:
PERFORM pg_notify('authentik.tasks.' || NEW.queue_name || '.enqueue', NEW.message_id::text);So the notify side is firing correctly on every insert. The problem is on the listen side.
Checked pg_stat_activity for active listeners:
SELECT pid, application_name, query FROM pg_stat_activity WHERE query ILIKE '%LISTEN%';Only LISTEN "channels_messages" is present (Django Channels, unrelated). No listener matching authentik.tasks.<queue_name>.enqueue ever appears, regardless of how many worker processes are running.
Confirmed the worker container is otherwise fully healthy:
- /dev/shm/authentik.sock and /dev/shm/authentik-worker-*.sock present
- /proc//task shows the expected thread pool
- health endpoint (/-/health/live/) returns 200 continuously throughout, including while tasks sit stuck
Tried scaling AUTHENTIK_WORKER__PROCESSES and AUTHENTIK_WORKER__THREADS up to 4/4 (from unset defaults) — new worker processes spin up cleanly ("ready for action" logged for each), but none of them establish the LISTEN subscription either. Backlog does not drain regardless of process count.
Full docker compose down && docker compose up -d (not just the worker service) does not clear it either.
Upgraded from 2026.8.0 to 2026.8.2 specifically because the changelog mentions a fix for "the Dramatiq consumer-thread crash" — bug still fully reproduces on 2026.8.2, confirmed via both docker inspect (image tag) and the admin UI's own version footer.
Task backlog accumulated to 1361 stuck queued rows across all task types over the course of testing before being manually bulk-cleared as cleanup:
Task.objects.filter(state="queued").update(state="done")This clears the symptom in the UI but does not address the underlying issue — any newly enqueued task immediately starts piling up again the same way.
How to reproduce
- Fresh
docker compose up -d --force-recreate worker(or a full stack restart withdocker compose down && docker compose up -d) - Enqueue any task, via any of these three independent paths:
- UI: click "Sync LDAP source" / "Send update to outpost" / any scheduled task's play button
- ak shell: direct dramatiq send, e.g. from authentik.sources.ldap.tasks import ldap_sync from authentik.sources.ldap.models import LDAPSource source = LDAPSource.objects.get(slug="") ldap_sync.send(source.pk)
- CLI:
ak ldap_sync <source_slug> -v 2(also fails — this path calls schedule.send().get_result() internally and raises dramatiq.results.errors.ResultMissing after timing out, since nothing ever consumes the message)
- Task row is created correctly in authentik_tasks_task with state=queued and the correct queue_name
- Check active listeners on Postgres (query above)
- Task remains state=queued indefinitely — mtime never advances past creation time, even minutes/hours later
Expected behavior
The worker's Dramatiq consumer should register a LISTEN subscription on authentik.tasks.<queue_name>.enqueue on startup, so that tasks enqueued via the Postgres-native broker (django-dramatiq-postgres) are picked up and executed shortly after creation, as documented. Scaling AUTHENTIK_WORKER__PROCESSES/THREADS should also result in at least one of the worker processes successfully subscribing and draining the queue — in this case none of them ever do, regardless of count.
Screenshots
No response
Additional context
- authentik 2026.8.0 → 2026.8.2 (both reproduce identically)
- Deployment: Docker Compose, single host
- postgresql: docker.io/library/postgres:16-alpine
- worker image: ghcr.io/goauthentik/server:2026.8.2
- Tested at both default AUTHENTIK_WORKER__PROCESSES/THREADS (unset) and explicitly set to 4/4
- Broker: django-dramatiq-postgres (Postgres-native, no Redis in this deployment)
Deployment Method
Docker
Version
2026.8.2
Relevant log output
worker-1 | {"domain_url": null, "event": "Sent 0 scheduled tasks", "level": "info", "logger": "django_dramatiq_postgres.scheduler", ...}
^ This line repeats on every scheduler tick across every worker process (worker_id 1000-1003 when scaled to 4 processes), even while dozens/hundreds of tasks sit in state=queued in the database. The scheduler is running and ticking, but never dispatches anything to the workers.
Sample of the enqueue side working correctly (from the trigger firing on task creation):
worker-1 | {"domain_url": null, "event": "Task enqueued", "level": "info", "logger": "authentik.tasks.middleware", "pid": 40, "schema_name": "public", "task_id": "ffe5748d-d3f4-40d8-9233-870faf7278e4", "task_name": "authentik.outposts.tasks.outpost_controller", "timestamp": "2026-09-17T12:07:09.484156"}
Direct CLI reproduction (ak ldap_sync), showing the consumer-side timeout:
Traceback (most recent call last):
File "/authentik/tenants/management/__init__.py", line 38, in handle
self.handle_per_tenant(*args, **options)
File "/authentik/sources/ldap/management/commands/ldap_sync.py", line 24, in handle_per_tenant
schedule.send().get_result()
File "/ak-root/.venv/lib/python3.14/site-packages/dramatiq/message.py", line 167, in get_result
return backend.get_result(self, block=block, timeout=timeout)
File "/ak-root/.venv/lib/python3.14/site-packages/dramatiq/results/backend.py", line 122, in get_result
raise ResultMissing(message)
dramatiq.results.errors.ResultMissing: authentik.sources.ldap.tasks.ldap_sync(UUID('7133d810-2b3f-471e-afed-5245b8e4498e'))
pg_stat_activity output showing the missing subscription (only Django Channels' own listener present, nothing for tasks):
pid | application_name | query
---------+------------------+-----------------------------------------
2781511 | | LISTEN "channels_messages"
2783242 | | LISTEN "channels_messages"Source: goauthentik/authentik