Open-source project
quantum-elixir/quantum-core avatar
quantum-elixir/quantum-core

Quantum for Elixir: a cron-like scheduler that lives in your supervision tree

:watch: Cron-like job scheduler for Elixir

2,416 stars154 forksElixirApache-2.0

At a glance

What is it?
Quantum is an Elixir library that runs cron-style jobs inside a supervised process, configured in your app's config files. It suits Elixir teams that want scheduled work to start with the application and be observed through the standard logger.
Who is it for?
Adopt Quantum when your scheduled work already belongs to an Elixir application and you want the scheduler started by the supervision tree rather than by an external crontab. Do not adopt it when the job must run even if the BEAM application is down, or when you need the scheduler to persist and replay missed runs; the README and configuration documentation do not describe catch-up behaviour or durable job state.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Elixir, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap Quantum fills for Elixir applications

System cron runs commands on a host. Quantum runs functions inside an Elixir application. That distinction matters when the work needs application state: a database connection pool, a GenServer, configuration loaded at boot. The README frames it plainly as a "Cron-like job scheduler for Elixir", and the examples show job entries pointing at module, function, argument tuples such as {Heartbeat, :send, []} or at anonymous functions.

The audience is Elixir teams already running a supervised application. If your deployment is a release started by a release script, adding a scheduler module to the children list means scheduled work starts and stops with the application, and crashes are handled by the same supervisor strategy as the rest of the tree. Teams that only need to run a shell command on a fixed host schedule get nothing extra from this, and pay for a dependency they do not need.

How the scheduler is wired into the supervision tree

There is no separate daemon and no external process to manage. You define a module with use Quantum, otp_app: :your_app, and that module becomes a child in your application's supervisor. The README shows Acme.Scheduler added to the children list alongside other workers, with the standard opts = [strategy: :one_for_one, name: Acme.Supervisor] passed to Supervisor.start_link.

Job definitions live in configuration, not in the scheduler module. The README's usage section puts them under config :acme, Acme.Scheduler, jobs: [...], which means the schedule is read from the application environment at start time. Each entry is a two-element tuple: a cron expression or a shorthand such as @daily, and a function to execute. The function can be an MFA tuple or an anonymous function, and the README shows both, including a fn -> System.cmd("rm", ["/tmp/tmp_"]) end form.

The expression syntax follows familiar cron conventions. The README comments its examples: "* * * * *" is every minute, "*/15 * * * *" is every 15 minutes, and "0 18-6/2 * * *" runs on 18, 20, 22, 0, 2, 4, 6. Range with step inside a field is supported, which is more than some minimal schedulers offer. The repository also carries a timezone topic, and the configuration documentation is the place the README points to for the details beyond these examples.

Installing Quantum and running a first job

Quantum is distributed on Hex as the quantum package. The README's setup section gives three steps, and the first is the dependency entry in mix.exs:

elixir
defp deps do
  [
    {:quantum, "~> 3.0"}
  ]
end

After fetching dependencies, the second step is a scheduler module. The README's example names it Acme.Scheduler and passes the OTP application name, which is how Quantum knows which application environment to read jobs from:

elixir
defmodule Acme.Scheduler do
  use Quantum, otp_app: :your_app
end

The third step is the supervision tree. The scheduler must be started, or nothing runs:

elixir
defmodule Acme.Application do
  use Application

  def start(_type, _args) do
    children = [
      Acme.Scheduler
    ]

    opts = [strategy: :one_for_one, name: Acme.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

With those three pieces in place, jobs go in config/config.exs. The README's example mixes MFA tuples and anonymous functions in one list:

elixir
config :acme, Acme.Scheduler,
  jobs: [
    {"* * * * *",      {Heartbeat, :send, []}},
    {"*/15 * * * *",   fn -> System.cmd("rm", ["/tmp/tmp_"]) end},
    {"0 18-6/2 * * *", fn -> :mnesia.backup('/var/backup/mnesia') end},
    {"@daily",         {Backup, :backup, []}}
  ]

What you should see after starting the application is the scheduler process in your supervision tree and the jobs firing on their schedules. To confirm that, the troubleshooting section recommends raising the logger level to debug:

elixir
config :logger, level: :debug

If that is too noisy for the rest of the application, the README gives a per-scheduler switch instead, so Quantum's own messages stay quiet while other debug output continues:

elixir
config :acme, Acme.Scheduler,
  debug_logging: false

Where Quantum is the wrong tool

The scheduler is an in-process component. If the application is not running, no job runs. That is a deliberate consequence of the design, but it means Quantum does not replace host-level cron for tasks that must survive an application restart, a failed deploy or a node that is down for maintenance. The README does not document catch-up behaviour for missed runs, and it does not describe a durable store for job state. Treat a missed window as missed.

Multi-node deployments need thought before adoption. Nothing in the README describes leader election or distributed locking, so a job configured on an application that runs on several nodes is a job you have configured on several nodes. The README is silent on this, and the configuration documentation is where you would look before assuming otherwise.

There is also a version caveat the README states directly: it "follows main, which may not be the currently published version", and it links to the docs for the latest published release. If you read the README on the repository front page and then install from Hex, you may be reading about behaviour that is not in the version you get. The published releases listed for the project are v3.5.3, v3.5.2 and v3.5.1, all from February 2024.

Quantum against the system crontab approach

The obvious alternative is the crontab on the host, invoking a release task or an escript. The difference is where the schedule lives and what happens when the process fails. With crontab, the schedule is part of machine provisioning and the command is a fresh OS process each time; state has to be reloaded on every invocation, and the application's supervision tree has no visibility into the run. With Quantum, the schedule is part of the application configuration, the job runs inside the running BEAM, and a crash is handled by the supervisor that owns the scheduler.

That trade cuts both ways. Configuration-driven schedules can be changed by editing config files and redeploying, which fits teams that already treat configuration as part of the release. Crontab entries can be changed on a host without touching the application at all, which fits teams that want scheduling decoupled from deploys. Neither is universally better; they answer different questions about ownership.

Maintenance, releases and the Apache-2.0 licence

The repository is not archived, and the last push was on 2026-09-22. The most recent tagged releases listed are v3.5.3, v3.5.2 and v3.5.1, all from February 2024, so the release cadence and the commit activity are not the same thing. Upgrading within the 3.x line is what the README's dependency example implies: {:quantum, "~> 3.0"} accepts any 3.x version, which means patch and minor updates arrive on a normal mix deps.update run without a constraint change.

Quantum is licensed under Apache-2.0, and the README carries the full Apache License, Version 2.0 text with the copyright line for Constantin Rack. Apache-2.0 is a permissive licence that includes an explicit patent grant and requires attribution and retention of notices. It is not a copyleft licence, so it does not force your application's source to be published. This is a description of the licence text, not legal advice; if the patent or notice terms matter to your organisation, have counsel read the LICENSE file rather than a summary.

Editorial conclusion

Adopt Quantum when your scheduled work already belongs to an Elixir application and you want the scheduler started by the supervision tree rather than by an external crontab. Do not adopt it when the job must run even if the BEAM application is down, or when you need the scheduler to persist and replay missed runs; the README and configuration documentation do not describe catch-up behaviour or durable job state. Verify first that your OTP release starts the scheduler module you added to the children list, and that debug logging is set the way you want, either globally with config :logger, level: :debug or per scheduler with debug_logging: false.

Frequently asked questions

How do I install Quantum in an Elixir project?

Add {:quantum, "~> 3.0"} to the deps list in mix.exs, fetch dependencies, then create a scheduler module with use Quantum, otp_app: :your_app and add that module to your application's children list. Jobs are then declared under config :your_app, YourApp.Scheduler, jobs: [...].

Does Quantum run jobs if the Elixir application is not running?

No. The scheduler is a child in the application's supervision tree, so jobs only fire while the application is up. The README does not document catch-up for runs missed while the application was down.

How can I see what Quantum is doing?

The troubleshooting section recommends setting the logger to debug level, config :logger, level: :debug. If that is too noisy, the README shows a per-scheduler option, config :acme, Acme.Scheduler, debug_logging: false, to suppress Quantum's own debug messages.

What cron expression formats does Quantum accept?

The README's examples use five-field expressions such as "* * * * *" and "*/15 * * * *", ranges with steps like "0 18-6/2 * * *", and the shorthand "@daily". The README points to the configuration documentation for details beyond these examples.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. quantum-elixir/quantum-core on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/quantum-elixir-quantum-core.svg)](https://hysenlabs.com/projects/quantum-elixir-quantum-core)