Setup & operations · Updated October 12, 2026

Self-hosted cron with Docker and PostgreSQL

CronLite moves recurring HTTP work out of server crontabs and into a service you operate. A Go binary schedules and delivers webhooks; PostgreSQL stores jobs, executions, API keys, and delivery history. Your application receives HTTP callbacks without an SDK.

Start CronLite with Docker Compose

Install Git, Docker, and Docker Compose. Clone the repository and start the supplied Compose stack. It includes CronLite and PostgreSQL; a fresh database applies the numbered schema migrations during initialization.

git clone https://github.com/djlord-it/cronlite.git
cd cronlite
docker compose up -d

Create your first namespace-scoped API key

Run the create-key command inside the service container. Save the printed token: CronLite stores a hash and only reveals the plaintext once. The namespace determines which jobs and executions the key can access.

docker compose exec cronlite cronlite create-key default local-dev
export CRONLITE_API_KEY="ec_<paste-the-printed-token>"

Register a recurring webhook

Send a cron expression, IANA timezone, and public webhook URL to POST /jobs. Choose a private signing secret that your receiver also knows. This example calls the receiver every five minutes in UTC.

curl -X POST http://localhost:8080/jobs \
  -H "Authorization: Bearer $CRONLITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"ping","cron_expression":"*/5 * * * *","timezone":"UTC","webhook_url":"https://httpbin.org/post","webhook_secret":"replace-with-your-signing-secret"}'

Choose single-instance or database dispatch

Channel dispatch is the default for a single process. For horizontal scaling, set DISPATCH_MODE=db and run instances against the same PostgreSQL database. A PostgreSQL advisory lock selects one scheduling leader; dispatcher workers on all instances claim different executions using SKIP LOCKED.

Leader failover depends on database connection detection and the retry interval. Delivery remains at least once, so your receiver must deduplicate by execution ID.

  • Persist PostgreSQL data and establish backups.
  • Apply all required migrations when upgrading an existing database.
  • Serve the API and optional Admin UI behind HTTPS in production.
  • Review configuration, connection limits, metrics authentication, and shutdown settings before scaling.
Read the upstream reference ↗