{"id":13513451,"url":"https://github.com/citusdata/pg_cron","last_synced_at":"2025-04-09T01:23:01.521Z","repository":{"id":10903958,"uuid":"67372977","full_name":"citusdata/pg_cron","owner":"citusdata","description":"Run periodic jobs in PostgreSQL","archived":false,"fork":false,"pushed_at":"2024-08-22T15:10:56.000Z","size":357,"stargazers_count":2865,"open_issues_count":111,"forks_count":192,"subscribers_count":74,"default_branch":"main","last_synced_at":"2024-10-29T14:56:16.859Z","etag":null,"topics":["cron","periodic-jobs","postgresql","scheduler"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"postgresql","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/citusdata.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-04T23:12:31.000Z","updated_at":"2024-10-29T10:48:50.000Z","dependencies_parsed_at":"2023-02-19T16:16:09.775Z","dependency_job_id":"c2f5ba46-3123-4a6b-961a-96091264b1d5","html_url":"https://github.com/citusdata/pg_cron","commit_stats":{"total_commits":183,"total_committers":41,"mean_commits":4.463414634146342,"dds":0.6229508196721312,"last_synced_commit":"b8d8f4bb467cf0b86281351977522707cda0bc1a"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citusdata%2Fpg_cron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citusdata%2Fpg_cron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citusdata%2Fpg_cron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citusdata%2Fpg_cron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/citusdata","download_url":"https://codeload.github.com/citusdata/pg_cron/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247953867,"owners_count":21024102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cron","periodic-jobs","postgresql","scheduler"],"created_at":"2024-08-01T05:00:25.970Z","updated_at":"2025-04-09T01:23:01.497Z","avatar_url":"https://github.com/citusdata.png","language":"C","readme":"[![Citus Banner](/github-banner.png)](https://www.citusdata.com/)\n\n## What is pg_cron?\n\npg_cron is a simple cron-based job scheduler for PostgreSQL (10 or higher) that runs inside the database as an extension. It uses the same syntax as regular cron, but it allows you to schedule PostgreSQL commands directly from the database. You can also use '[1-59] seconds' to schedule a job based on an interval.\n\npg_cron also allows you using '$' to indicate last day of the month.\n\n```sql\n-- Delete old data on Saturday at 3:30am (GMT)\nSELECT cron.schedule('30 3 * * 6', $$DELETE FROM events WHERE event_time \u003c now() - interval '1 week'$$);\n schedule\n----------\n       42\n\n-- Vacuum every day at 10:00am (GMT)\nSELECT cron.schedule('nightly-vacuum', '0 10 * * *', 'VACUUM');\n schedule\n----------\n       43\n\n-- Change to vacuum at 3:00am (GMT)\nSELECT cron.schedule('nightly-vacuum', '0 3 * * *', 'VACUUM');\n schedule\n----------\n       43\n\n-- Stop scheduling jobs\nSELECT cron.unschedule('nightly-vacuum' );\n unschedule \n------------\n t\n\nSELECT cron.unschedule(42);\n unschedule\n------------\n          t\n\n-- Vacuum every Sunday at 4:00am (GMT) in a database other than the one pg_cron is installed in\nSELECT cron.schedule_in_database('weekly-vacuum', '0 4 * * 0', 'VACUUM', 'some_other_database');\n schedule\n----------\n       44\n\n-- Call a stored procedure every 5 seconds\nSELECT cron.schedule('process-updates', '5 seconds', 'CALL process_updates()');\n\n-- Process payroll at 12:00 of the last day of each month\nSELECT cron.schedule('process-payroll', '0 12 $ * *', 'CALL process_payroll()');\n```\n\npg_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, then the second run is queued and started as soon as the first run completes.\n\nThe schedule uses the standard cron syntax, in which * means \"run every time period\", and a specific number means \"but only at this time\":\n\n```\n ┌───────────── min (0 - 59)\n │ ┌────────────── hour (0 - 23)\n │ │ ┌─────────────── day of month (1 - 31) or last day of the month ($)\n │ │ │ ┌──────────────── month (1 - 12)\n │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to\n │ │ │ │ │                  Saturday, or use names; 7 is also Sunday)\n │ │ │ │ │\n │ │ │ │ │\n * * * * *\n```\n\nAn easy way to create a cron schedule is: [crontab.guru](http://crontab.guru/).\n\nThe code in pg_cron that handles parsing and scheduling comes directly from the cron source code by Paul Vixie, hence the same options are supported.\n\n## Installing pg_cron\n\nInstall on Red Hat, CentOS, Fedora, Amazon Linux with PostgreSQL 16 using [PGDG](https://yum.postgresql.org/repopackages/):\n\n```bash\n# Install the pg_cron extension\nsudo yum install -y pg_cron_16\n```\n\nInstall on Debian, Ubuntu with PostgreSQL 16 using [apt.postgresql.org](https://wiki.postgresql.org/wiki/Apt):\n\n```bash\n# Install the pg_cron extension\nsudo apt-get -y install postgresql-16-cron\n```\n\nYou can also install pg_cron by building it from source:\n\n```bash\ngit clone https://github.com/citusdata/pg_cron.git\ncd pg_cron\n# Ensure pg_config is in your path, e.g.\nexport PATH=/usr/pgsql-16/bin:$PATH\nmake \u0026\u0026 sudo PATH=$PATH make install\n```\n\n## Setting up pg_cron\n\nTo start the pg_cron background worker when PostgreSQL starts, you need to add pg_cron to `shared_preload_libraries` in postgresql.conf. Note that pg_cron does not run any jobs as a long a server is in [hot standby](https://www.postgresql.org/docs/current/static/hot-standby.html) mode, but it automatically starts when the server is promoted.\n\n```\n# add to postgresql.conf\n\n# required to load pg_cron background worker on start-up\nshared_preload_libraries = 'pg_cron'\n```\n\nBy default, the pg_cron background worker expects its metadata tables to be created in the \"postgres\" database. However, you can configure this by setting the `cron.database_name` configuration parameter in postgresql.conf.\n```\n# add to postgresql.conf\n\n# optionally, specify the database in which the pg_cron background worker should run (defaults to postgres)\ncron.database_name = 'postgres'\n```\n`pg_cron` may only be installed to one database in a cluster. If you need to run jobs in multiple databases, use `cron.schedule_in_database()`.\n\nPreviously pg_cron could only use GMT time, but now you can adapt your time by setting `cron.timezone` in postgresql.conf.\n```\n# add to postgresql.conf\n\n# optionally, specify the timezone in which the pg_cron background worker should run (defaults to GMT). E.g:\ncron.timezone = 'PRC'\n```\n\nAfter restarting PostgreSQL, you can create the pg_cron functions and metadata tables using `CREATE EXTENSION pg_cron`.\n\n```sql\n-- run as superuser:\nCREATE EXTENSION pg_cron;\n\n-- optionally, grant usage to regular users:\nGRANT USAGE ON SCHEMA cron TO marco;\n```\n\n### Ensuring pg_cron can start jobs\n\n**Important**: By default, pg_cron uses libpq to open a new connection to the local database, which needs to be allowed by [pg_hba.conf](https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html). \nIt may be necessary to enable `trust` authentication for connections coming from localhost in  for the user running the cron job, or you can add the password to a [.pgpass file](https://www.postgresql.org/docs/current/static/libpq-pgpass.html), which libpq will use when opening a connection. \n\nYou can also use a unix domain socket directory as the hostname and enable `trust` authentication for local connections in [pg_hba.conf](https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html), which is normally safe:\n```\n# Connect via a unix domain socket:\ncron.host = '/tmp'\n\n# Can also be an empty string to look for the default directory:\ncron.host = ''\n```\n\nAlternatively, pg_cron can be configured to use background workers. In that case, the number of concurrent jobs is limited by the `max_worker_processes` setting, so you may need to raise that.\n\n```\n# Schedule jobs via background workers instead of localhost connections\ncron.use_background_workers = on\n# Increase the number of available background workers from the default of 8\nmax_worker_processes = 20\n```\n\nFor security, jobs are executed in the database in which the `cron.schedule` function is called with the same permissions as the current user. In addition, users are only able to see their own jobs in the `cron.job` table.\n\n```sql\n-- View active jobs\nselect * from cron.job;\n```\n\n## Viewing job run details\n\nYou can view the status of running and recently completed job runs in the `cron.job_run_details`:\n\n```sql\nselect * from cron.job_run_details order by start_time desc limit 5;\n┌───────┬───────┬─────────┬──────────┬──────────┬───────────────────┬───────────┬──────────────────┬───────────────────────────────┬───────────────────────────────┐\n│ jobid │ runid │ job_pid │ database │ username │      command      │  status   │  return_message  │          start_time           │           end_time            │\n├───────┼───────┼─────────┼──────────┼──────────┼───────────────────┼───────────┼──────────────────┼───────────────────────────────┼───────────────────────────────┤\n│    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 │\n│    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 │\n│    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 │\n│    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  │\n│     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  │\n└───────┴───────┴─────────┴──────────┴──────────┴───────────────────┴───────────┴──────────────────┴───────────────────────────────┴───────────────────────────────┘\n(10 rows)\n```\n\nThe records in `cron.job_run_details` are not cleaned automatically, but every user that can schedule cron jobs also has permission to delete their own `cron.job_run_details` records. \n\nEspecially when you have jobs that run every few seconds, it can be a good idea to clean up regularly, which can easily be done using pg_cron itself:\n\n```sql\n-- Delete old cron.job_run_details records of the current user every day at noon\nSELECT  cron.schedule('delete-job-run-details', '0 12 * * *', $$DELETE FROM cron.job_run_details WHERE end_time \u003c now() - interval '7 days'$$);\n```\n\nIf you do not want to use `cron.job_run_details` at all, then you can add `cron.log_run = off` to `postgresql.conf`.\n\n## Extension settings\n\nThe pg_cron extension supports the following configuration parameters:\n\n| Setting                          | Default     | Description                                                                              |\n| ---------------------------------| ----------- | ---------------------------------------------------------------------------------------- |\n| `cron.database_name`             | `postgres`  | Database in which the pg_cron background worker should run.                              |\n| `cron.enable_superuser_jobs`     | `on`        | Allow jobs to be scheduled as superusers.                                                |\n| `cron.host`                      | `localhost` | Hostname to connect to postgres.                                                         |\n| `cron.launch_active_jobs`        | `on`        | When off, disables all active jobs without requiring a server restart                    |\n| `cron.log_min_messages`          | `WARNING`   | log_min_messages for the launcher bgworker.                                              |\n| `cron.log_run`                   | `on`        | Log all run details in the`cron.job_run_details` table.                                  |\n| `cron.log_statement`             | `on`        | Log all cron statements prior to execution.                                              |\n| `cron.max_running_jobs`          | `32`        | Maximum number of jobs that can be running at the same time.                             |\n| `cron.timezone`                  | `GMT`       | Timezone in which the pg_cron background worker should run.                              |\n| `cron.use_background_workers`    | `off`       | Use background workers instead of client connections.                                    |\n\n### Changing settings\n\nTo view setting configurations, run:\n\n```sql\nSELECT * FROM pg_settings WHERE name LIKE 'cron.%';\n```\n\nSetting can be changed in the postgresql.conf file or with the below command:\n\n```sql\nALTER SYSTEM SET cron.\u003cparameter\u003e TO '\u003cvalue\u003e';\n```\n\n`cron.log_min_messages` and `cron.launch_active_jobs` have a [setting context](https://www.postgresql.org/docs/current/view-pg-settings.html#VIEW-PG-SETTINGS) of `sighup`. They can be finalized by executing `SELECT pg_reload_conf();`.\n\nAll the other settings have a postmaster context and only take effect after a server restart.\n\n## Example use cases\n\nArticles showing possible ways of using pg_cron:\n\n* [Auto-partitioning using pg_partman](https://www.citusdata.com/blog/2018/01/24/citus-and-pg-partman-creating-a-scalable-time-series-database-on-postgresql/)\n* [Computing rollups in an analytical dashboard](https://www.citusdata.com/blog/2017/12/27/real-time-analytics-dashboards-with-citus/)\n* [Deleting old data, vacuum](https://www.citusdata.com/blog/2016/09/09/pgcron-run-periodic-jobs-in-postgres/)\n* [Feeding cats](http://bonesmoses.org/2016/09/09/pg-phriday-irrelevant-inclinations/)\n* [Routinely invoking a function](https://fluca1978.github.io/2019/05/21/pgcron.html)\n* [Postgres as a cron server](https://supabase.io/blog/2021/03/05/postgres-as-a-cron-server)\n\n## Managed services\n\nThe following table keeps track of which of the major managed Postgres services support pg_cron.\n\n| Service       | Supported     |\n| ------------- |:-------------:|\n| [Aiven](https://aiven.io/postgresql) | :heavy_check_mark: |\n| [Alibaba Cloud](https://www.alibabacloud.com/help/doc-detail/150355.htm) | :heavy_check_mark: |\n| [Amazon RDS](https://aws.amazon.com/rds/postgresql/)     | :heavy_check_mark:      |          |\n| [Azure](https://azure.microsoft.com/en-us/services/postgresql/) | :heavy_check_mark:  |\n| [Crunchy Bridge](https://www.crunchydata.com/products/crunchy-bridge/?ref=producthunt) | :heavy_check_mark: |\n| [DigitalOcean](https://www.digitalocean.com/products/managed-databases/) | :heavy_check_mark: |\n| [Google Cloud](https://cloud.google.com/sql/postgresql/) | :heavy_check_mark: |\n| [Heroku](https://elements.heroku.com/addons/heroku-postgresql) | :x: | \n| [Instaclustr](https://instaclustr.com) | :heavy_check_mark:  |\n| [Neon](https://neon.tech/docs/extensions/extensions-intro#tooling-admin) | :heavy_check_mark: | \n| [ScaleGrid](https://scalegrid.io/postgresql.html) | :heavy_check_mark:  |\n| [Scaleway](https://www.scaleway.com/en/database/) | :heavy_check_mark:  |\n| [Supabase](https://supabase.io/docs/guides/database) | :heavy_check_mark:  |\n| [Tembo](https://tembo.io) | :heavy_check_mark:  |\n| [YugabyteDB](https://www.yugabyte.com/) | :heavy_check_mark:  |\n\n## Code of Conduct\n\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.\n","funding_links":[],"categories":["C","Compiled list","Extensions"],"sub_categories":["plv8:"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcitusdata%2Fpg_cron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcitusdata%2Fpg_cron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcitusdata%2Fpg_cron/lists"}