Install & Compatibility
Where this runs
tested against v0.28.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.466s · 26.5MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.7s · import 0.404s · 27MB
25MB installed
● package 25MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
create_pool
✓ from arq import create_pool
RedisSettings
✓ from arq.connections import RedisSettings
WorkerSettings
✓ from arq.worker import WorkerSettings
func
✓ from arq.worker import func
Used to wrap job functions for more advanced settings (e.g., `keep_result`, `timeout`).
cron
✓ from arq.cron import cron
Used to define recurring jobs with cron-like schedules.
This quickstart demonstrates how to enqueue jobs using `arq` and how to define `WorkerSettings` for processing them. It includes a `download_content` job, along with `startup` and `shutdown` hooks for resource management (e.g., an `httpx.AsyncClient` session). The script can be run to enqueue jobs, and a separate worker process (using the `arq` CLI) can be started to consume them from Redis. Ensure a Redis server is running and accessible via `ARQ_REDIS_DSN` environment variable or the default `redis://localhost:6379`.
import asyncio
import os
from arq import create_pool
from arq.connections import RedisSettings
from arq.worker import WorkerSettings
# For demonstration, typically use an AsyncClient from httpx or aiohttp
# Install 'httpx' for this example: pip install httpx
import httpx
REDIS_DSN = os.environ.get('ARQ_REDIS_DSN', 'redis://localhost:6379')
REDIS_SETTINGS = RedisSettings.from_dsn(REDIS_DSN)
async def download_content(ctx, url: str) -> int:
"""An example job function that downloads content from a URL."""
session: httpx.AsyncClient = ctx['session']
response = await session.get(url, timeout=5) # Added timeout for robustness
response.raise_for_status()
print(f"Worker: Downloaded {len(response.text)} bytes from {url[:50]}...")
return len(response.text)
async def startup(ctx):
"""Worker startup hook to initialize shared resources."""
print("Worker: Starting up - creating httpx.AsyncClient session.")
ctx['session'] = httpx.AsyncClient()
async def shutdown(ctx):
"""Worker shutdown hook to clean up shared resources."""
if 'session' in ctx:
await ctx['session'].aclose()
print("Worker: Shutting down - closing httpx.AsyncClient session.")
class MyWorkerSettings(WorkerSettings):
"""Worker settings for arq CLI."""
functions = [download_content]
on_startup = startup
on_shutdown = shutdown
redis_settings = REDIS_SETTINGS
keep_result = 60 * 60 # Keep job results for 1 hour
async def main():
"""Producer: Enqueues jobs."""
print(f"Producer: Connecting to Redis at {REDIS_DSN}")
redis = await create_pool(REDIS_SETTINGS)
urls = [
'https://www.google.com',
'https://www.bing.com',
'https://www.yahoo.com',
]
for url in urls:
job = await redis.enqueue_job('download_content', url)
print(f"Producer: Enqueued job {job.job_id} for {url}")
# Optional: Wait for a job result (for demonstration)
# first_job_id = (await redis.queued_jobs())[0].job_id if await redis.queued_jobs() else None
# if first_job_id:
# job = await redis.job(first_job_id)
# print(f"Producer: Waiting for job {job.job_id} result...")
# result = await job.result(timeout=10) # Wait up to 10 seconds
# print(f"Producer: Job {job.job_id} finished with result: {result}")
redis.close()
await redis.wait_closed()
print("Producer: Redis connection closed.")
if __name__ == '__main__':
# To run the producer (enqueue jobs):
# python your_script_name.py
asyncio.run(main())
# To run the worker (in a separate terminal):
# ARQ_REDIS_DSN='redis://localhost:6379' arq your_script_name.MyWorkerSettings --burst
# (Remove --burst to run continuously)
arq --version
Debug
Known issues
breakingarq underwent a complete rewrite in v0.16, fundamentally changing how workers are registered, and jobs are enqueued and processed. Code written for v0.15 or earlier is incompatible.fixUsers migrating from v0.15 or older must entirely rewrite their arq integration following the new API. Refer to the v0.16 documentation for the new patterns.
affects: <=0.15 to >=0.16
breakingSupport for Python 3.8 was officially removed, while support for Python 3.13 was added.fixEnsure your project runs on Python 3.9 or newer. Upgrade your Python environment if currently using 3.8.
affects: 0.27.0
gotchaAll job functions defined for arq workers must accept `ctx` as their first argument, which is a dictionary for passing shared resources (e.g., database connections, HTTP sessions) to jobs.fixModify your job function signatures to `async def my_job(ctx, *args, **kwargs):`. Access shared resources via `ctx['key']`.
affects: All versions >=0.16
gotchaarq uses 'pessimistic execution': jobs are only removed from the queue upon successful completion or final failure. If a worker process shuts down unexpectedly, in-progress jobs will remain in the queue to be rerun by another worker or when the worker restarts.fixDesign your jobs to be idempotent or handle potential duplicate executions gracefully. Be aware that job execution might not be 'exactly once' in failure scenarios.
affects: All versions >=0.16
gotchaFor Python 3.14 and newer, `asyncio.get_event_loop()` no longer implicitly creates an event loop and will raise a `RuntimeError` if no loop is running. While `arq` v0.27.1+ includes internal fixes, custom asyncio setups might be affected.fixEnsure you are using `arq` v0.27.1 or newer for Python 3.14+ compatibility. If manually managing event loops, use `asyncio.new_event_loop()` explicitly or ensure a loop is set before calling `arq` components.
affects: 0.27.0 and older versions when used with Python 3.14+
gotchaThe `ArqRedis` methods `get_all_job_results()` and `queued_jobs()` use inefficient Redis commands (`KEYS` or multiple `GET` operations) internally, making them unsuitable for production environments with a large number of keys or jobs.fixAvoid using these methods for retrieving large sets of job data in production. If you need to monitor or manage many jobs, consider designing custom Redis queries or using `arq`'s built-in monitoring tools if available for specific use cases.
affects: All versions
Upgrade
Version history
0.28.0latest on PyPI · released Apr 16, 2026
Audit
Dependencies
redisrequiredarq uses Redis as its sole message broker and state backend.
httpxoptionalCommonly used for HTTP requests within async jobs, as shown in quickstart examples.