{"id":6777,"library":"procrastinate","title":"Procrastinate","description":"Procrastinate is an open-source Python 3.10+ distributed task processing library that leverages PostgreSQL 13+ to store task definitions, manage locks, and dispatch tasks. It integrates with both synchronous and asynchronous code, offers Django integration, and is compatible with ASGI frameworks, supporting features like periodic tasks, retries, and arbitrary task locks.","status":"active","version":"3.8.1","language":"en","source_language":"en","source_url":"https://github.com/procrastinate-org/procrastinate","tags":["task queue","distributed tasks","postgresql","async","background jobs","django","fastapi"],"install":[{"cmd":"pip install procrastinate psycopg[binary]","lang":"bash","label":"Basic Installation with Psycopg"},{"cmd":"pip install procrastinate aiopg","lang":"bash","label":"Alternative Installation with Aiopg"}],"dependencies":[{"reason":"Required as the backend for job storage, locks, and task dispatch. Version 13+ is recommended.","package":"PostgreSQL","optional":false},{"reason":"Python adapter for PostgreSQL, typically used with PsycopgConnector. 'psycopg[binary]' is often used for easier installation.","package":"psycopg","optional":true},{"reason":"Alternative asynchronous PostgreSQL adapter, can be used with AiopgConnector.","package":"aiopg","optional":true}],"imports":[{"note":"The main entry point for defining and managing tasks.","symbol":"App","correct":"from procrastinate import App"},{"note":"Used to configure the connection to a PostgreSQL database.","symbol":"PsycopgConnector","correct":"from procrastinate import PsycopgConnector"}],"quickstart":{"code":"import random\nimport time\nimport os\n\nfrom procrastinate import App, PsycopgConnector\n\n# Configure your PostgreSQL connection string\n# Example: 'postgresql://user:password@host:port/database'\n# Use os.environ.get for production readiness\nPOSTGRES_DSN = os.environ.get('POSTGRES_DSN', 'postgresql://postgres:password@localhost:5432/postgres')\n\napp = App(\n    connector=PsycopgConnector(\n        dsn=POSTGRES_DSN\n    )\n)\n\n@app.task(name=\"sum_task\")\ndef sum_task(a, b):\n    time.sleep(random.random() * 0.5) # Simulate work\n    result = a + b\n    print(f\"Task sum_task({a}, {b}) finished with result: {result}\")\n    return result\n\nasync def main():\n    print(\"Applying schema...\")\n    await app.open_async()\n    await app.get_connector().check()\n    await app.get_connector().execute_query_one(\"SELECT 1 FROM procrastinate_jobs LIMIT 1\")\n    print(\"Schema applied and checked.\")\n\n    print(\"Deferring a job...\")\n    job = await sum_task.defer_async(a=3, b=5)\n    print(f\"Job deferred with ID: {job.id}\")\n    await app.close_async()\n\nif __name__ == \"__main__\":\n    import asyncio\n    asyncio.run(main())\n\n# To run the worker, save the above as e.g., 'my_tasks.py' and execute in a separate terminal:\n# export POSTGRES_DSN='postgresql://postgres:password@localhost:5432/postgres' # (or your actual DSN)\n# procrastinate --app=my_tasks.app worker","lang":"python","description":"This quickstart demonstrates how to define a Procrastinate application, declare a task, and defer a job. It assumes a PostgreSQL database is running and accessible via `POSTGRES_DSN`. To run the worker that executes deferred tasks, a separate CLI command is provided."},"warnings":[{"fix":"Review the official 'Migration documentation' for your specific version upgrade. Apply 'pre' migrations before deployment and 'post' migrations after.","message":"The database migration process has significantly changed in major versions (e.g., around v1.0). Migrations are now categorized as 'pre' and 'post', requiring specific application before and after deploying new Procrastinate code. Ensure you consult the migration documentation for your upgrade path.","severity":"breaking","affected_versions":"1.0.0+"},{"fix":"Upgrade your Python environment to version 3.10 or later. Check the official documentation for the latest supported Python versions.","message":"Python 3.9 support has been dropped in recent versions (e.g., 3.7.0), while support for Python 3.14 has been added. Ensure your environment uses a supported Python version (3.10+).","severity":"breaking","affected_versions":"3.7.0+"},{"fix":"Explicitly list all modules containing task definitions in the `import_paths` parameter when initializing your `App` instance, or ensure they are imported as a side effect when the `App` is instantiated.","message":"Workers must be aware of all task definitions. If tasks are in modules not directly imported by your `App` object or not specified in `App(import_paths=...)`, the worker will fail with a `TaskNotFound` error when attempting to execute such tasks.","severity":"gotcha","affected_versions":"All"},{"fix":"Understand the implications of async/sync boundaries. For synchronous task functions, be aware they run in a thread pool. For I/O-bound tasks, this is often fine. For CPU-bound tasks, consider making them `async` if possible or using other multiprocessing approaches if true parallelism is needed.","message":"Procrastinate is asynchronous at its core. While it offers synchronous deferral methods, running workers or interacting with the CLI requires an asynchronous context. Synchronous task functions executed by an async worker run in a thread, impacting parallelism for CPU-bound tasks due to the GIL.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}