CRON job not running on Plesk / Passenger hosting

System Information
  • Strapi Version 3.5.3:
  • Operating System Linux:
  • Database SQLite:
  • Node Version 12:
  • NPM Version 10:
  • Yarn Version:

I’ve deployed a strapi installation on Plesk Obsidian which runs via Passenger. Works great in all other respects, but the Cron jobs never fire?

They’re definitely configured correctly as they fire when the setup is used on my local machine, but they never get run when on the server.

Is there some additional setup i need to do to use Cron in this environment, or is there a URL that i can access externally using the main server Cron system? It would be fine if the events could just be fired from a URL.


Does anybody know if Cron is known to work in this environment? Could really use some pointers on it if possible.


Crons are entirely based on the systems time, which I’m guessing that server is running UTC as the system time. I’m not familiar with the environment, can you break it down a bit as to how it’s deployed and ran?

Yes of course.

The main difference is how the application is started. It’s run via a server.js file like this:

const strapi = require('strapi');
strapi(/* {...} */).start();

The actual cron job being run is just a basic command from an Instagram plugin that checks for new Instagram posts every 30 mins. This command never gets run in the live environment however. The actual cron task definitely works fine as I’ve tested this in my development environment without problems.

Should cron tasks still function as normal with this sort of setup?

It really depends on the server, certain services and hosts “kill” the server and spin it back up when a request is made (IE Heroku) AKA hot-loading. In hosts like this the Strapi server isn’t running so the cron-tasks don’t get fired.

To answer your sub-point, yes running Strapi with a server.js / app.js / anything.js should still fire the crons.

Thanks, I wonder if the passenger phusion spins up the server when required and prevents the cron jobs from being fired then.

I can watch any nodejs output on the server and set a test cron job perhaps, see what’s actually happening.

If it turns out that the server will not allow strapi to run cron jobs normally, would it be possible to activate them from a url, like a standard cron task? That would be an acceptable workaround I think

Yes @darkcherrycreative that method is commonly used when scaling Strapi servers as well (I use it in my personal projects) since if you have 12 Strapi instances running with a cron task configured, when the time comes to trigger the cron all 12 would fire.

Instead creating a custom endpoint, locking down it’s security to something like a pre-shared key, and creating a standard http get request (even on the same server) to run that function works extremely well.

Thanks, that sounds ideal, could you provide some sort of example of how this would look in practice?

The construction of the route, controller is fairly straight forward (we have some examples in the documentation) but I have a very poor example in one of my hobby projects.

This is simply put, a route that will bulk delete entries older than x months old that I run on a cron (protected by the users-permissions plugin and locked to an automation user). FYI my code is horrible but this was a quick and dirty solution.



The actual cron part is built into my horribly designed cron system (this could be much much simpler but I’m running quite a few cron scripts with complex logging needs, and a custom tailor made “SDK”)

The actual function making the request to Strapi:

And a small screenshot of that script running:

This is just simply running node-cron as a PM2 service that has a set crontab schedule to run every 4 hours, it calls the Strapi REST endpoint which fires off the bulk delete through a RAW Knex query (to keep it simple). Im doing some basic SQL injection validation, but realistically that isn’t terribly critical since that route is locked down to a specific automation role that is only used for cron-scripts. You could just as easily use our API Token guide instead to handle it with a preshared key/token: