NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #3017 most downloaded on PyPI
Postgres-based distributed task processing library
Last release 11 days ago
23 Sep 2026
Ships fairly regularly
a new release about every 6 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
4 versions withdrawn
withdrawn after publishing
7 years old
106 releases · first in 2019
feat: add external connection support for job cancellation and status by @atteahma in #1560
Full Changelog: 3.9.0...3.10.0
One column per quarter.
Replace deprecated migra with results by @EdwardBetts in #1511
Full Changelog: 3.8.1...3.9.0
Provide a stronger type hint for App.open_async() by @aolieman in #1536
feat: add external connection support for atomic job deferral by @psontag in #1508
Fix schema.sql to bypass privilage issues on initial schema migration by @nithinjp1997 in #1527
Full Changelog: 3.7.2...3.7.3
fix: Add missing mandatory 'packaging' dependency introduced by 9866efa by @ducdetronquito in #1496
Full Changelog: 3.7.1...3.7.2
Following 3.7.0 release, remove deprecated code by @ewjoachim in #1489
Full Changelog: 3.7.0...3.7.1
Drop support for py3.9, add support for py3.14 by @ewjoachim in #1487
Full Changelog: 3.6.0...3.7.0
Stop worker when side task fails by @woolfred in #1463
Clamp datetime_from_timedelta_params instead of crashing. by @jakajancar in #1465
datetime_from_timedelta_params instead of crashing. by @jakajancar in #1465Full Changelog: 3.5.2...3.5.3
Make migration compatible with non-public schemas ( 03.04.00_50_post_add_retry_failed_job_procedure.sql ) by @ozamosi in #1441
03.04.00_50_post_add_retry_failed_job_procedure.sql) by @ozamosi in #1441Full Changelog: 3.5.1...3.5.2
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.5.0...3.5.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.4.0...3.5.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Pre (launch before upgrading):
Post (launch after upgrading):
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.3.0...3.4.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Pre (launch before upgrading):
Post (launch after upgrading):
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.2.2...3.3.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.2.1...3.2.2
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.2.0...3.2.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Pre (launch before upgrading):
Post (launch after upgrading):
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.0.2...3.1.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
v by @ewjoachim in https://github.com/procrastinate-org/procrastinate/pull/1312Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/3.0.1...3.0.2
Support for Python 3.8 was removed following its deprecation.
A long, complex, necessary and highly appreciated work from @onlyann who has been quite active this year: rewriting most of the main job processing loop of the Procrastinate Worker (#1114) as discussed in #933. It was followed by quite a few improvements we wanted to make for a long time and took the opportunity of a breaking release to do, as described below.
Changes include:
X.Y.Z before upgrading the code to X.Y.Z with complex procedures around minor/major versions. The new way is that migrations are noted as pre or post, you apply the pre migrations before deploying the accompagnying new version of Procrastinate, and you apply the post migrations after deploying the said code. If you are several versions late, you'll have to repeat these for every intermediate release that comes with migrations. See the Migration documentation.asyncio's cancel method, which can be handled gracefully by users using shielding, as explained in the Cancel documentation. Synchronous jobs will not be cancelled, but job_context.should_abort() will return True so that you can handle the abortion request in your code.shutdown_graceful_timeout. During shutdown, jobs (both synchronous and asynchronous) get an abort request as described in the previous bullet point. See all details in the Shutdown documentation.ABORTING). It's now an independent field (Job.abort_requested). This has implications if you introspect job states, such as with the Job objects or via the Django integration.timeout worker option was renamed to fetch_job_polling_interval to better reflect its purpose. It's accompanied by a new setting abort_job_polling_interval. Both regulate how often the worker contacts the database to request new jobs or cancellation requests, in case they don't receive notifications from the LISTEN/NOTIFY mechanism. This is explained in the Polling documentation. Note that the work from @onlyann led to workers making significantly less SQL queries, especially for workers with high concurrency settings.JobContext object that your tasks receive if the task decorator was passed with pass_context=True:
job_context.job_result was removed. The only relevant information it contained was the start timestamp, which is now accessible via job_context.start_timestampapp and job had static typing, mentioning that those attributes could be None while they actually were always set. They are now properly typed.job_context.should_abort_async() was removed. Knowing whether the job should abort or not, is not doing I/Os anymore, so both sync and async code can now use job_context.should_abort(). job_context.abort_reason tells you whether a job is being aborted because the user requested an abortion, or because the worker is stopping.job_context.task attribute is now a read-only property. Not that it wasn't a good idea to modify it before, but in the very surprising case that one would do, that's now not possible anymore.builtin_tasks.remove_old_jobs(), remove_error was renamed to remove_failed for consistency. Similarly, in JobManager.delete_old_jobs(), include_error was renamed include_failed.Pre (launch before upgrading):
Post (launch after upgrading):
We'd love for you to share your thoughts about this release to us:
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.14.0...3.0.0
Support for Python 3.8 was removed following its deprecation.
<!-- Release notes generated using configuration in .github/release.yml at v3 -->
A long, complex, necessary and highly appreciated work from @onlyann who has been quite active this year: rewriting most of the main job processing loop of the Procrastinate Worker (#1114) as discussed in #933. It was followed by quite a few improvements we wanted to make for a long time and took the opportunity of a breaking release to do, as described below.
Changes include:
X.Y.Z before upgrading the code to X.Y.Z with complex procedures around minor/major versions. The new way is that migrations are noted as pre or post, you apply the pre migrations before deploying the accompagnying new version of Procrastinate, and you apply the post migrations after deploying the said code. If you are several versions late, you'll have to repeat these for every intermediate release that comes with migrations. See the Migration documentation.asyncio's cancel method, which can be handled gracefully by users using shielding, as explained in the Cancel documentation. Synchronous jobs will not be cancelled, but job_context.should_abort() will return True so that you can handle the abortion request in your code.shutdown_graceful_timeout. During shutdown, jobs (both synchronous and asynchronous) get an abort request as described in the previous bullet point. See all details in the Shutdown documentation.ABORTING). It's now an independent field (Job.abort_requested). This has implications if you introspect job states, such as with the Job objects or via the Django integration.timeout worker option was renamed to fetch_job_polling_interval to better reflect its purpose. It's accompanied by a new setting abort_job_polling_interval. Both regulate how often the worker contacts the database to request new jobs or cancellation requests, in case they don't receive notifications from the LISTEN/NOTIFY mechanism. This is explained in the Polling documentation. Note that the work from @onlyann led to workers making significantly less SQL queries, especially for workers with high concurrency settings.JobContext object that your tasks receive if the task decorator was passed with pass_context=True:
job_context.job_result was removed. The only relevant information it contained was the start timestamp, which is now accessible via job_context.start_timestampapp and job had static typing, mentioning that those attributes could be None while they actually were always set. They are now properly typed.job_context.should_abort_async() was removed. Knowing whether the job should abort or not, is not doing I/Os anymore, so both sync and async code can now use job_context.should_abort(). job_context.abort_reason tells you whether a job is being aborted because the user requested an abortion, or because the worker is stopping.job_context.task attribute is now a read-only property. Not that it wasn't a good idea to modify it before, but in the very surprising case that one would do, that's now not possible anymore.builtin_tasks.remove_old_jobs(), remove_error was renamed to remove_failed for consistency. Similarly, in JobManager.delete_old_jobs(), include_error was renamed include_failed.We'd love for you to share your thoughts about this release to us:
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.14.0...3.0.0b1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.15.0...2.15.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
02.14.01_01_add_indexes_for_fetch_job.sql
[!NOTE] The new indexes will block the table while they are being built. Unless you have millions of jobs in the table, it should not be a problem, but you may want to create the index concurrently if you can. Note that you cant create an index concurrently in a transaction, which is why the migration code we suggested doesn't use the
CONCURRENTLYkeyword. To create the index concurrently, replaceCREATE INDEXin the migration code withCREATE INDEX CONCURRENTLY.
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.14.1...2.15.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.14.0...2.14.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.13.2...2.14.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.13.1...2.13.2
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.13.0...2.13.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.12.0...2.13.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
If you want to document tasks with Sphinx's Autodoc, check the new doc! Following a report from @JacobCoffee in https://github.com/procrastinate-org/procrastinate/pull/1152
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.11.0...2.12.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.10.0...2.11.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.9.2...2.10.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.9.1...2.9.2
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
procrastinate shell <command> by @ewjoachim (found by @linspw who contributed a first fix) in https://github.com/procrastinate-org/procrastinate/pull/1121Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.9.0...2.9.1
If you have implemented your own RetryStrategy, get_schedule_in is now deprecated (but still maintained) and should be replaced with get_retry_decisio…
<!-- Release notes generated using configuration in .github/release.yml at main -->
get_schedule_in is now deprecated (but still maintained) and should be replaced with get_retry_decision. get_schedule_in support will probably be removed in the next major release, though there's no guarantee that this might happen anytime soon.Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.8.0...2.9.0
Remove deprecated file static_migrations.py by @ewjoachim in https://github.com/procrastinate-org/procrastinate/pull/1091
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.7.0...2.8.0
As part of this release, we're delighted to announce the addition of @medihack among the procrastinate maintainers! Congratulations and happy maintainance to them and everyone! The project is still welcoming contributors and potentially maintainers, so feel free to have a look at the repo activity if you want to help! Thank you!
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
02.06.00_01_add_cancel_states.sql
This is a new feature that will only impact you if you decide to use it, apart from one minor change: in the procrastinate shell CLI, the new cancelled, aborting, aborted states are exposed and calling cancel on a job used to set is as failed and will now set it as either cancelled or aborting (see the doc for details)
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.6.0...2.7.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
02.05.00_01_add_periodic_job_priority.sql
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.5.0...2.6.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
02.00.03_01_add_job_priority.sql ( :warning: the name of the migration doesn't match the name of the version)
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.4.0...2.5.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.3.0...2.4.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.2.0...2.3.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
procrastinate shell <subcommand> for non-interactive lookups by @indrat in https://github.com/procrastinate-org/procrastinate/pull/1038Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.1.0...2.2.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.3...2.1.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
IntegrityErrors with the Django connector by @ewjoachim in https://github.com/procrastinate-org/procrastinate/pull/1014Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.2...2.0.3
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.1...2.0.2
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0...2.0.1
…smoothest ride as possible considering there are breaking changes, but should you find yourself completely lost, feel free to open an issue in the rep…
<!-- Release notes generated using configuration in .github/release.yml at main -->
This release refactors the Django integration completely. Head to the Django section in the doc to discover how it works.
Here's a summary of the changes:
INSTALLED_APPS, you can use procrastinate.contrib.django.app. This special app uses the Django connection and doesn't need opening or closing.tasks submodule of any app in INSTALLED_APPS are loaded by default. This is configurable (you can add paths to load, or change the name of the module containing your tasks in every app)PROCRASTINATE_* in your Django settings. See the complete doc for details (but there are no mandatory settings)./manage.py procrastinate (you won't have to configure an App either)ModelAdmins in your Django Admin. Those models are read-only. The Admin panels are very very basic for now.We've done some effort in bringing this version to completion and ensuring that it's the smoothest ride as possible considering there are breaking changes, but should you find yourself completely lost, feel free to open an issue in the repository.
Thank you @paulzakin for the help in testing out this release!
No SQL migrations. There's a Django migration, which you can run safely as it doesn't contain any actual SQL code (you can also run it with --fake for the same result)
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/1.1.2...2.0.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
manage.py procrastinate healthchecks by @ewjoachim in https://github.com/procrastinate-org/procrastinate/pull/976Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b8...2.0.0b9
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b7...2.0.0b8
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b6...2.0.0b7
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b5...2.0.0b6
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b4...2.0.0b5
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b3...2.0.0b4
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated. Contact us through here.
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b2...2.0.0b3
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
We're still in the process of evaluating changes to the Django integration. For stability it's advised to wait for a stable release (...duh). Of course, volunteers for testing in the beta are highly appreciated.
No SQL migrations. There's a Django migration, which you can run safely as it doesn't contain any actual SQL code (you can also run it with --fake for the same result)
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/2.0.0b1...2.0.0b2
This release refactors the Django integration completely. Head to the Django section in the doc to discover how it works.
This release refactors the Django integration completely. Head to the Django section in the doc to discover how it works.
Here's a summary of the changes:
INSTALLED_APPS, you can use procrastinate.contrib.django.app. This special app uses the Django connection and doesn't need opening or closing.tasks submodule of any app in INSTALLED_APPS are loaded by default. This is configurable (you can add paths to load, or change the name of the module containing your tasks in every app)PROCRASTINATE_* in your Django settings. See the complete doc for details (but there are no mandatory settings)./manage.py procrastinate (if you use that, you won't have to configure an App either)ModelAdmins in your Django Admin. Those models are read-only. The Admin panels are very very basic for now.While Procrastinate is mainly developed by myself, multiple contributors helped shaping this release over the last 2 years that it's been slowly boiling:
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/1.1.2...2.0.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Migrations:
integer to bigint in procedure signatures (useful if you have more than 2B tasks)job_id elements to bigint, reported by @Vladimir-Filimonov via https://github.com/procrastinate-org/procrastinate/pull/902Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/1.1.1...1.1.2
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/1.1.0...1.1.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
Yes ! For the first time in a while, there are migrations. They're mainly dropping old functions now that we're in 1.0, following our migration doc. As a reminder, you should apply the migrations listed for 1.0 (such as the one below) before you upgrade to 1.1.
Full Changelog: https://github.com/procrastinate-org/procrastinate/compare/1.0.3...1.1.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
None
## Migrations None ## Documentation - Doc with Furo
None
Your coding agent can read these notes before it upgrades. Set up the MCP server →