Skip to main content

Use the PostgreSQL® pg_cron extension

The pg_cron extension is a cron-based job scheduler for PostgreSQL (10 or higher) that runs inside the database.

pg_cron can run multiple jobs in parallel, but it runs at most one instance of a job at a time. If a second run is supposed to start before the first one finishes, the second run is queued and started as soon as the first run completes.

CRON syntax

The schedule uses the standard cron syntax, where an asterisk (*) means execute at every time interval, and a specific number means execute exclusively at this specific time:

┌───────────── min (0 - 59)
│ ┌────────────── hour (0 - 23)
│ │ ┌─────────────── day of month (1 - 31)
│ │ │ ┌──────────────── month (1 - 12)
│ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
│ │ │ │ │ Saturday, or use names; 7 is also Sunday)
│ │ │ │ │
│ │ │ │ │
* * * * *

You can also use [1-59] seconds to schedule a job based on an interval.

Enable pg_cron for specific users

To use the pg_cron extension:

  1. Connect to the database as avnadmin user and make sure to use the defaultdb database:

    CREATE EXTENSION pg_cron;
  2. Optional: Grant usage permission to regular users:

    GRANT USAGE ON SCHEMA cron TO janedoe;

Set up the cron job

List all the jobs

To view the full list of existing jobs, run:

SELECT * FROM cron.job;

jobid | schedule | command | nodename | nodeport | database | username | active | jobname
------+-------------+--------------------------------+-----------+----------+----------+-----------+--------+-------------------------
106 | 29 03 * * * | vacuum freeze test_table | localhost | 8192 | database1| adminuser | t | database1 manual vacuum
1 | 59 23 * * * | vacuum freeze pgbench_accounts | localhost | 8192 | postgres | adminuser | t | manual vacuum
(2 rows)

Schedule a job

To schedule a new job, run:

Vacuum every day at 10:00am (GMT)
SELECT cron.schedule('nightly-vacuum', '0 10 * * *', 'VACUUM');

Unschedule a job

To unschedule a job, you have two options:

  • By using the jobname:

    Unschedule jobs using jobname
    SELECT cron.unschedule('nightly-vacuum' );
  • By using the jobid:

    Unschedule jobs using jobid
    SELECT cron.unschedule(1);

View completed jobs

To list all completed job runs, run:

select * from cron.job_run_details order by start_time desc limit 5;

+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
¦ jobid ¦ runid ¦ job_pid ¦ database ¦ username ¦ command ¦ status ¦ return_message ¦ start_time ¦ end_time ¦
+-------+-------+---------+----------+----------+-------------------+-----------+------------------+-------------------------------+-------------------------------¦
¦ 10 ¦ 4328 ¦ 2610 ¦ postgres ¦ marco ¦ select process() ¦ succeeded ¦ SELECT 1 ¦ 2023-02-07 09:30:00.098164+01 ¦ 2023-02-07 09:30:00.130729+01 ¦
¦ 10 ¦ 4327 ¦ 2609 ¦ postgres ¦ marco ¦ select process() ¦ succeeded ¦ SELECT 1 ¦ 2023-02-07 09:29:00.015168+01 ¦ 2023-02-07 09:29:00.832308+01 ¦
¦ 10 ¦ 4321 ¦ 2603 ¦ postgres ¦ marco ¦ select process() ¦ succeeded ¦ SELECT 1 ¦ 2023-02-07 09:28:00.011965+01 ¦ 2023-02-07 09:28:01.420901+01 ¦
¦ 10 ¦ 4320 ¦ 2602 ¦ postgres ¦ marco ¦ select process() ¦ failed ¦ server restarted ¦ 2023-02-07 09:27:00.011833+01 ¦ 2023-02-07 09:27:00.72121+01 ¦
¦ 9 ¦ 4320 ¦ 2602 ¦ postgres ¦ marco ¦ select do_stuff() ¦ failed ¦ job canceled ¦ 2023-02-07 09:26:00.011833+01 ¦ 2023-02-07 09:26:00.22121+01 ¦
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(10 rows)