Schedule publications

Scheduled publication

This guide will help you set a publication date for an “Article” content-type, and at this date, toggle the draft state to published.


Set up the admin panel and prepare the content

By default, when using the Draft & Publish feature, entries have a publishedAt field whose value is null as long as the entry is in the draft state.

We will add another field, named publish_at, to the “Article” content-type, to be able to define the date and time at which the article should be published. To achieve this:

  1. Click on the Content-type Builder link in the left menu.
  2. Select the “Article” collection type.
  3. Add another field to the “Article” collection type: choose the date type, name the field publish_at and choose the datetime type.

Then, from the Content Manager, create some new entries for the “Article” content-type with different publish_at values and Draft & Publish states to be able to see the publication happen.
:exclamation:Make sure to create some entries with a draft state and a publish_at that is before the current date.

The goal of the CRON task we’ll create next will be to check every minute if there are draft articles that have a publish_at field value lower than the current date.

Create a CRON task

To execute a function every minute, we will use a CRON task.

To run a CRON task on the Strapi server, you need to:

  • enable CRON tasks in the ./config/server.js file by setting cron.enabled to true (see documentation)
  • declare the CRON tasks. In our example, we will declare it within a dedicated file, but you could also declare it directly within the cron.tasks parameter of the ./config/server.js file.

Please note that Strapi’s built-in CRON feature will not work if you plan to use pm2 or node-based clustering. You will need to execute these CRON tasks outside of Strapi.

The publishing logic will fetch all draft entries from the “Article” content-type with a publish_at value that is before the current date, then update the value of the published_at of all these articles:

// path: ./config/cron-tasks.js

module.exports = {
   * Scheduled publication workflow.
   * Checks every minute if there are draft articles to publish.

  '*/1 * * * *': async () => {
    // fetch articles to publish;
    const draftArticleToPublish = await strapi.entityService.findMany('api::article.article', {
      publicationState: 'preview', // preview returns both draft and published entries
      filters: {
        publishedAt: {
          $null: true, // so we add another condition here to filter entries that have not been published
        publish_at: {
          $lt: new Date() // and we keep only articles with a 'publish_at' datetime value that is lower than the current datetime
    // update the publish_at of articles previously fetched
    await Promise.all( => {
      return strapi.entityService.update('api::article.article',, {
        data: {
          publishedAt: new Date(),

And tada!