The Revel Jobs module is for performing work asynchronously outside of the request flow.

The job is either:


The Jobs module is optional not enabled by default.

To activate add to the app.conf file: =

Additionally, in order to access the job monitoring page, you will need to add /@jobs to the conf/routes to browse to url:

    // url = /@jobs


There are some configuration settings that place some limitations job and its run, explained below with default values:

Implementing Jobs

To create a Job, implement the cron.Job interface. The Job interface has the following signature:

type Job interface {

For example:

type MyJob struct {}

func (j MyJob) Run() {
   // Do something

Startup jobs

To run a task on application startup, use revel.OnAppStart() to register a function. Revel runs these tasks serially, before starting the server. Note that this functionality does not actually use the jobs module, but it can be used to submit a job for execution that doesn’t block server startup.

func init() {
    revel.OnAppStart(func() { jobs.Now(populateCache{}) })

Recurring Jobs

Jobs may be scheduled to run on any schedule. There are two options for expressing the schedule:

  1. A cron specification
  2. A fixed interval

Revel uses the cron library to parse the schedule and run the jobs. The library’s README provides a detailed description of the format accepted.

Jobs are generally registered using the revel.OnAppStart() hook, but they may be registered at any later time as well.

Here are some examples:

import (

type ReminderEmails struct {
    // filtered

func (e ReminderEmails) Run() {
    // Queries the DB
    // Sends some email

func init() {
    revel.OnAppStart(func() {
        jobs.Schedule("0 0 0 * * ?",  ReminderEmails{})
        jobs.Schedule("@midnight",    ReminderEmails{})
        jobs.Schedule("@every 24h",   ReminderEmails{})
        jobs.Every(24 * time.Hour,    ReminderEmails{})

Named schedules

You can configure schedules in the app.conf file and reference them anywhere. This provides an easy way to reuse, and a useful description for crontab specs.

Here is an example named cron schedule, in an app.conf file:

cron.workhours_15m = 0 */15 9-17 ? * MON-FRI

Use the named schedule by referencing it anywhere you would have used a cron spec.

func init() {
    revel.OnAppStart(func() {
        jobs.Schedule("cron.workhours_15m", ReminderEmails{})
IMPORTANT: The cron schedule's name must begin with cron.

One-off Jobs

Sometimes it is necessary to do something in response to a user action. In these cases, the jobs module allows you to submit a job to be run a single time.

The only control offered is how long to wait until the job should be run.

type AppController struct { *revel.Controller }

func (c AppController) Action() revel.Result {
    // Handle the request.

    // Send them email asynchronously, right now.

    // Or, send them email asynchronously after a minute.
    jobs.In(time.Minute, SendConfirmationEmail{})

Registering functions

It is possible to register a func() as a job by wrapping it in the jobs.Func type. For example:

func sendReminderEmails() {
    // Query the DB
    // Send some email

func init() {
    revel.OnAppStart(func() {
        jobs.Schedule("@midnight", jobs.Func(sendReminderEmails))

Job Status

The jobs module provides a status page (/@jobs url) that shows:

  • a list of the scheduled jobs it knows about
  • the current status; IDLE or RUNNING
  • the previous and next run times
For security purposes, the status page is restricted to requests that originate from

Job Status Page

Constrained pool size

It is possible to configure the job module to limit the number of jobs that are allowed to run at the same time. This allows the developer to restrict the resources that could be potentially in use by asynchronous jobs – typically interactive responsiveness is valued above asynchronous processing. When a pool is full of running jobs, new jobs block to wait for running jobs to complete.

Implementation Note: The implementation blocks on a channel receive, which is implemented to be FIFO for waiting goroutines (but not specified/required to be so). See here for discussion.

Future areas for development

  • Allow access to the job status page with HTTP Basic Authentication credentials
  • Allow administrators to run scheduled jobs interactively from the status page
  • Provide more visibility into the job runner, e.g. the pool size, the job queue length, etc.
GitHub Labels