Scheduled Heroku Scheduler jobs execute at unexpected times after changing app region
0 reputation · 28 Jun 2023, 05:48 UTC
0 reputation · 28 Jun 2023, 05:48 UTC
Developers expect Heroku Scheduler to trigger jobs according to a local time zone that matches the application’s intended audience, especially after moving the app to a different geographic region. The platform does not automatically adjust the scheduler’s execution time based on the dyno’s region, leaving the timing dependent on the TZ configuration variable.
Because the TZ var must be set explicitly and only takes effect after a dyno restart, any change in region or desired local time requires manual coordination. Add‑ons such as Heroku Postgres continue to store timestamps in UTC, so the application must still perform zone conversion for display purposes. This creates a gap between the configured region and the actual runtime behavior of scheduled tasks.
What is the recommended workflow for updating the TZ variable when an app is migrated to a new Heroku region without causing missed or duplicate Scheduler runs?
How can teams verify that Scheduler jobs are honoring the new TZ setting after a dyno restart without introducing additional logging or metric overhead?
35775 reputation · 28 Jun 2023, 17:13 UTC
Heroku Scheduler evaluates cron expressions in UTC unless the app-level TZ config var is set. Changing the app's region does not modify this variable, so scheduled jobs continue to fire at the original UTC offsets. To migrate cleanly:
TZ value (e.g., America/Los_Angeles) via the dashboard or CLI: heroku config:set TZ=America/Los_Angeles -a your-app.heroku restart -a your-app. This restarts web, worker, and the one-off scheduler dynos.If you cannot guarantee a quiet window, scale the scheduler formation to zero (heroku ps:scale scheduler=0), apply the TZ change, restart, then scale back up. This eliminates any chance of a job firing during the transition.
After the restart, use one of these lightweight checks:
TZ setting.heroku run bash -c 'date' -a your-app. The output shows the dyno’s current time in the configured zone, confirming the variable is active.This guidance assumes the Common Runtime (not Private Spaces) and Heroku Scheduler Standard. Private Spaces may use a different scheduler implementation. Add-ons such as Heroku Postgres continue to store timestamps in UTC; application-level conversion remains necessary for display.
One diagnostic detail that would change the recommendation: Are you using Heroku Scheduler Standard or the newer Heroku Scheduler (beta) with custom clock processes? The beta version can run on a dedicated clock dyno that may require a separate restart.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.