Back to Blog
Platform8 min read

Heroku Cron Jobs: Heroku Scheduler, Cron To Go & Alternatives

Heroku does not have built-in cron support. Instead, you use add-ons or external services to schedule recurring tasks. The most common option — Heroku Scheduler — is free but famously unreliable. This guide covers all four approaches to scheduling on Heroku, their trade-offs, and which one to choose based on how critical your cron jobs are.

Heroku Scheduler (Free but Unreliable)

Heroku Scheduler is a free add-on that runs one-off dynos on a fixed schedule. It is the most popular option because it costs nothing to install and takes seconds to set up. However, its limitations are significant.

Setup

# Install the add-on
heroku addons:create scheduler:standard

# Open the scheduler dashboard
heroku addons:open scheduler

In the dashboard, you add jobs with a command and select one of three fixed intervals: every 10 minutes, every hour, or every day at a specific time (UTC).

Example Commands

# Node.js
node scripts/cleanup-expired-sessions.js

# Python
python manage.py send_digest_emails

# Ruby
rake db:cleanup_old_records

# PHP
php artisan schedule:run

Critical limitation

Heroku Scheduler is officially described as “best effort”. Jobs can be skipped without notice during platform maintenance, incidents, or high load. There is no retry mechanism, no failure notification, and no execution log. Do not use it for billing, data pipelines, or anything where a missed execution has real consequences.

Key Limitations

  • Only 3 intervals: every 10 minutes, hourly, or daily
  • No standard cron expression syntax
  • Best-effort execution — jobs can be silently skipped
  • UTC only — no timezone configuration
  • No execution history, logs, or monitoring
  • No failure notifications

Cron To Go (Paid, More Features)

Cron To Go is a third-party Heroku add-on that provides proper cron functionality. It supports full cron expression syntax, timezone configuration, execution logs, and failure notifications.

Setup

# Install Cron To Go
heroku addons:create crontogo:bronze

# Open the dashboard
heroku addons:open crontogo

Features

  • Full cron expression syntax (1-minute granularity)
  • Timezone support (any IANA timezone)
  • Execution logs with stdout/stderr capture
  • Failure notifications via email and webhooks
  • Retry policies on failure
  • Job grouping and tagging

Pricing

Plans start at $7/month (Bronze: 5 jobs, 100 executions/day) and go up to $249/month (Platinum: unlimited jobs and executions). You still pay for the dyno time each execution uses. For teams with many scheduled tasks, costs can add up.

Custom Worker Dyno Approach

Instead of using an add-on, you can run a dedicated worker dyno that handles scheduling internally. This gives you full control but costs a full dyno 24/7.

Node.js Example with node-cron

// worker.js
const cron = require('node-cron');

// Run cleanup every hour
cron.schedule('0 * * * *', async () => {
  console.log('Running hourly cleanup...');
  try {
    await cleanupExpiredSessions();
    console.log('Cleanup completed');
  } catch (err) {
    console.error('Cleanup failed:', err.message);
  }
});

// Run report every day at 9 AM UTC
cron.schedule('0 9 * * *', async () => {
  console.log('Generating daily report...');
  await generateDailyReport();
});

console.log('Worker started, waiting for scheduled tasks...');

Procfile

web: node server.js
worker: node worker.js
# Scale up the worker dyno
heroku ps:scale worker=1

Cost consideration

A worker dyno runs 24/7 regardless of how often your jobs execute. A Basic dyno costs $7/month, a Standard-1X costs $25/month. If your jobs only run a few times per day, you are paying for idle compute. An external HTTP-based scheduler avoids this cost entirely.

Using CronJobPro (External, Reliable)

The most flexible approach is to expose an HTTP endpoint in your Heroku app and let an external cron-as-a-service call it on schedule. CronJobPro handles the scheduling, monitoring, and alerting while your app just responds to HTTP requests.

Step 1: Create a Secured Endpoint

// Express.js example
const express = require('express');
const app = express();

// Middleware to verify cron secret
function verifyCronSecret(req, res, next) {
  const secret = req.headers['x-cron-secret'];
  if (secret !== process.env.CRON_SECRET) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  next();
}

app.post('/api/cron/cleanup', verifyCronSecret, async (req, res) => {
  try {
    const deleted = await cleanupExpiredSessions();
    res.json({ success: true, deleted });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/cron/daily-report', verifyCronSecret, async (req, res) => {
  try {
    await generateDailyReport();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

Step 2: Configure CronJobPro

In the CronJobPro dashboard, create a monitor for each endpoint:

  • URL: https://your-app.herokuapp.com/api/cron/cleanup
  • Method: POST
  • Header: X-Cron-Secret: your-secret-value
  • Schedule: 0 * * * * (every hour)
  • Timezone: Your preferred timezone

CronJobPro calls the endpoint on schedule and tracks every execution. If the endpoint returns a non-2xx status code or does not respond within the timeout, you get an alert via email, Slack, or webhook.

Bonus: Eco dyno wake-up

If you are on Heroku's Eco plan, dynos sleep after 30 minutes of inactivity. CronJobPro's HTTP call wakes the dyno automatically. The first request takes a few extra seconds (cold start), but subsequent requests within the window are fast.

Comparison Table

FeatureHeroku SchedulerCron To GoWorker DynoCronJobPro
PriceFree (+ dyno time)$7-249/mo (+ dyno)$7-25/mo (always-on)Free (5 monitors)
Cron syntaxNo (3 fixed intervals)Yes (full)Yes (in code)Yes (full)
ReliabilityBest effortGuaranteedHigh (dyno uptime)Guaranteed
Timezone supportUTC onlyYesIn codeYes
MonitoringNoneExecution logsManual (app logs)Full dashboard + alerts
Failure alertsNoEmail, webhooksManualEmail, Slack, webhook
Heroku lock-inYesYesYes (dyno code)No (any HTTP endpoint)

For non-critical tasks where missing an occasional execution is acceptable, Heroku Scheduler works. For everything else, use Cron To Go if you want to stay within the Heroku ecosystem, or CronJobPro if you want monitoring and alerting with the flexibility to work across any platform.

Frequently Asked Questions

Is Heroku Scheduler free?

The add-on itself is free to install. However, it spins up a one-off dyno for each job execution, and you pay for the dyno time at your plan's rate. On the Eco plan ($5/month for 1000 dyno-hours), short tasks use minimal hours. On Basic or higher plans, each execution is billed per second of dyno time.

Why did my Heroku Scheduler job not run?

Heroku Scheduler is described as “best effort” in the official documentation. It does not guarantee execution. Jobs can be skipped during platform incidents, maintenance windows, or high load. There is no retry mechanism and no alerting when a job is missed. For critical tasks, use a more reliable solution.

Can I run a Heroku cron job every minute?

Not with Heroku Scheduler, which only supports 10-minute, hourly, and daily intervals. Cron To Go supports standard cron expressions with 1-minute granularity. Alternatively, use an external service like CronJobPro to call an HTTP endpoint on your Heroku app every minute.

What is the difference between Heroku Scheduler and Cron To Go?

Heroku Scheduler is free but limited: only 3 interval options, no cron syntax, best-effort execution, and no monitoring. Cron To Go ($7+/month) supports full cron expressions, guaranteed execution, timezone support, retry policies, execution logs, and failure notifications.

Can I use an external cron service with Heroku?

Yes. Create an HTTP endpoint in your Heroku app (e.g., /api/cron/cleanup) secured with an API key, then use CronJobPro to call that endpoint on your desired schedule. This gives you full cron syntax, monitoring, alerting, and works even if you migrate away from Heroku.

Related Articles

Reliable Cron for Heroku Apps

Stop worrying about missed Heroku Scheduler jobs. CronJobPro calls your endpoint on schedule with built-in monitoring and alerts. Free for up to 5 monitors.

Start Monitoring Free