Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/msolli/proletarian/llms.txt

Use this file to discover all available pages before exploring further.

Proletarian supports delayed job execution natively through two options on job/enqueue!. You can schedule a job for a specific point in time, or specify a duration to wait before the job becomes eligible for processing.

The :process-at option

Pass :process-at with a java.time.Instant to schedule a job for a specific moment in time. The queue worker will not pick up the job before that instant:
(require '[proletarian.job :as job])

;; Schedule for a specific UTC timestamp
(job/enqueue! tx ::send-reminder
  {:user-id 42}
  {:process-at (java.time.Instant/parse "2025-06-01T09:00:00Z")})
If the Instant you provide is already in the past, the job is scheduled for immediate processing.

The :process-in option

Pass :process-in with a java.time.Duration to delay execution relative to the current time. Proletarian adds the duration to the current clock time to compute the effective process-at value:
;; Schedule 30 minutes from now
(job/enqueue! tx ::send-reminder
  {:user-id 42}
  {:process-in (java.time.Duration/ofMinutes 30)})

;; Schedule 24 hours from now
(job/enqueue! tx ::send-follow-up
  {:user-id 42}
  {:process-in (java.time.Duration/ofHours 24)})
If the duration is negative, the job is scheduled for immediate processing.

Precedence and defaults

  • If both :process-at and :process-in are provided, :process-at takes precedence and :process-in is ignored.
  • If neither is provided, the job is enqueued for immediate processing (its process-at is set to the current time).
;; process-at wins — job is scheduled for 2025-06-01T09:00:00Z
(job/enqueue! tx ::send-reminder {:user-id 42}
  {:process-at (java.time.Instant/parse "2025-06-01T09:00:00Z")
   :process-in (java.time.Duration/ofHours 1)})

Complete examples

(ns your-app.scheduling
  (:require [next.jdbc :as jdbc]
            [proletarian.job :as job])
  (:import (java.time Instant Duration)))

(defn schedule-reminder! [db user-id remind-at]
  (jdbc/with-transaction [tx db]
    ;; Schedule for a specific time
    (job/enqueue! tx ::send-reminder
      {:user-id user-id}
      {:process-at remind-at})))

(defn schedule-follow-up! [db user-id]
  (jdbc/with-transaction [tx db]
    ;; Schedule 30 minutes from now
    (job/enqueue! tx ::send-follow-up
      {:user-id user-id}
      {:process-in (Duration/ofMinutes 30)})))

(defn schedule-nightly-report! [db]
  (jdbc/with-transaction [tx db]
    ;; Schedule for a fixed time tomorrow night
    (job/enqueue! tx ::generate-nightly-report
      {}
      {:process-at (Instant/parse "2025-01-02T02:00:00Z")})))
The :process-at time is a minimum delay, not a guarantee. A job scheduled for time T will not be picked up before T, but the actual execution time may be later depending on the queue worker’s polling interval, the number of jobs ahead in the queue, and available worker threads.
:process-in is a lightweight alternative to a full retry mechanism when you need to defer work by a known amount of time. For example, if a downstream API asks you to back off for 60 seconds, you can enqueue a new job with {:process-in (Duration/ofSeconds 60)} instead of building retry logic into your handler.

Build docs developers (and LLMs) love