Drizzle

Drizzle is a Elixir application to schedule repeated tasks.

Characteristics

Configuration

This basic example tells Drizzle to output "hello" every second:

config :drizzle,
records: [%{
crontab: "* * * * * *",
time_zone: :utc,
module: IO,
function: :puts,
args: ["hello"]
}]

Each record consist of different fields:

Here is a more involved example:

config :elixir, :time_zone_database, Tz.TimeZoneDatabase
config :drizzle,
records: [%{
crontab: "0 20 * * Sat",
time_zone: "Australia/Adelaide",
module: IO,
function: :puts,
args: ["cheers from down under"]
}],
last_evaluation: (case File.read("/tmp/drizzle_time") do {:error, _} -> nil; {:ok, time} -> String.to_integer(time) end),
evaluation_time_fun: fn(time) -> File.write!("/tmp/drizzle_time", inspect(time)) end

Here we are greeting every Saturday at 8pm Australian Central Standard Time. Please note that you need to configure a time zone DB to do this.

These keys are optional:

Drizzle counts time in Gregorian seconds (as in DateTime.utc_now |> DateTime.to_gregorian_seconds |> elem(0)). The problem is that when the application is stopped for restarts or upgrades, some seconds might not be observed. If you use evaluation_time_fun to capture and store this time, you can later pass it to last_evaluation so Drizzle can catch up and potentially trigger jobs that where scheduled while it was out.

evaluation_time_fun will be called whenever a job is executed and every 30 seconds.

Updating cron tab

You can update the cron tab at runtime: Drizzle.update([%{ crontab: "* * * * * *", time_zone: :utc, module: IO, function: :puts, args: ["olleh"] }])

Performance

Drizzle evaluates the cron tab for each second. On a modern machine evaluating one year (31536000 seconds) for one cron tab line takes about 30 CPU seconds.

Accuracy

Drizzle tries to trigger jobs as early during the corresponding second as possible but there are no guarantees. Under heavy load, triggering might be delayed due to how scheduling works in the BEAM.

Here are typical times for triggers between 0.8ms and 16ms after the second:

~U[2026-06-01 06:10:18.003031Z]
~U[2026-06-01 06:10:19.001435Z]
~U[2026-06-01 06:10:20.001111Z]
~U[2026-06-01 06:10:21.004924Z]
~U[2026-06-01 06:10:22.000842Z]
~U[2026-06-01 06:10:23.001319Z]
~U[2026-06-01 06:10:24.016850Z]
~U[2026-06-01 06:10:25.001041Z]
~U[2026-06-01 06:10:26.000944Z]
~U[2026-06-01 06:10:27.001133Z]
~U[2026-06-01 06:10:28.001860Z]
~U[2026-06-01 06:10:29.000957Z]
~U[2026-06-01 06:10:30.000943Z]
~U[2026-06-01 06:10:31.000732Z]

Installation

If available in Hex, the package can be installed by adding drizzle to your list of dependencies in mix.exs:

def deps do
[
{:drizzle, "~> 0.1.0"}
]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/drizzle.