# Healthchecks self-hosted: cron job monitoring with Django and PostgreSQL

> Healthchecks is a cron job monitoring service written in Python and Django: your jobs ping an HTTP endpoint or an email address, and the server alerts you when a ping fails to arrive on time. This covers the mechanism, the development setup, the Docker path, and where it fits against Uptime Kuma or Cronitor.

**healthchecks/healthchecks** — Open-source cron job and background task monitoring service, written in Python & Django

- Repository: https://github.com/healthchecks/healthchecks
- Website: https://healthchecks.io
- Stars: 10,369 · Forks: 1,013
- Language: Python
- License: BSD-3-Clause
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/healthchecks-healthchecks

## The problem Healthchecks solves: silent cron failures

A cron job that exits with an error usually leaves a trace in a log or a mail spool. A cron job that never runs at all leaves nothing. That second case is what Healthchecks targets. The project describes itself as a service that listens for HTTP requests and email messages, called pings, from cron jobs and scheduled tasks, called checks. When a ping does not arrive on time, it sends alerts. So the monitoring is inverted: instead of watching a process, the server watches for the absence of a signal.

The audience is operations and backend engineers who already have a scheduler, whether that is cron, systemd timers, Celery beat or a CI pipeline, and who want an external record that the job reported in. Because the check is driven by an outbound request from your job, the job does not need an agent, an open port or a shared network with the monitoring host. A single curl call at the end of a script is enough to register a success. That low coupling is the main reason to pick this over an agent-based monitor.

Healthchecks ships a web dashboard, an API, more than 25 integrations for delivering notifications, monthly email reports, WebAuthn 2FA, and team features including projects, team members and read-only access. The hosted service runs at healthchecks.io, and the same codebase is what you self-host.

## How the ping, period and grace model works

Each check carries two timing parameters. Period is the expected time between pings. Grace Time is how long to wait before sending alerts when a job is running late. The check moves through states as time passes: a ping arrives and the check is up; the period elapses with no ping and the check is late; the grace window also elapses and the check is down and alerts fire. This is a simple state machine, and its practical consequence is that your alerting threshold is period plus grace, not period alone. Teams that set a short grace on a job with variable runtime will get noise.

Instead of a period, you can define the expected schedule with a cron expression. The README states that Healthchecks uses the cronsim library to parse and evaluate cron expressions, and cronsim appears in requirements.txt at version 2.7. That matters for jobs that run at irregular intervals, such as weekdays only or the first of the month, where a fixed period cannot express the schedule.

The server side is a Django application. The building blocks listed in the README are Python 3.12 or newer, Django 6.1, and PostgreSQL, MySQL or MariaDB. The dependency list confirms the shape of the stack: psycopg for PostgreSQL, PyJWT for API tokens, pyotp and fido2 for two-factor authentication, segno for QR codes, pycurl for outbound HTTP, aiosmtpd for the inbound mail listener, and statsd for metrics. Notifications are assembled through Django's MAILERS setting, which Healthchecks builds from environment variables. Status badges are served from public but hard-to-guess URLs, which the README suggests for READMEs, dashboards or status pages.

## Installing Healthchecks for development and sending a first ping

The README documents a development setup rather than a production deployment. On Debian or Ubuntu the first step installs the venv package, then you create a virtual environment and clone the repository.

```bash
sudo apt update
sudo apt install -y python3-venv
python3 -m venv .venv
source .venv/bin/activate
git clone https://github.com/healthchecks/healthchecks.git
```

Requirements go into that virtualenv. Note that the README installs both the runtime and the development requirement files.

```bash
pip install -r healthchecks/requirements.txt -r healthchecks/requirements-dev.txt
```

macOS users get a separate procedure for pycurl, which needs to be reinstalled against the Homebrew OpenSSL prefix. The README exports PYCURL_SSL_LIBRARY, LDFLAGS and CPPFLAGS, then uninstalls and reinstalls pycurl with the --compile and --no-cache-dir flags. If you skip this, pycurl will not build correctly on that platform.

Database tables and an admin account come next. With the default configuration, Healthchecks stores data in a SQLite file named hc.sqlite in the checkout directory.

```bash
cd ~/webapps/healthchecks
./manage.py migrate
./manage.py createsuperuser
./manage.py runserver
```

The site should then be running at http://localhost:8000, and the Django administration panel is at http://localhost:8000/admin/ after logging in as a superuser. For a first real use, create a check in the dashboard, copy its ping URL, and call it from the job you want to watch. The equivalent of a heartbeat from a shell script is a single request to that URL at the end of the run.

Email pings take a different route. Healthchecks ships a smtpd management command that starts an SMTP listener, so checks can be pinged by sending mail to your-uuid-here@my-monitoring-project.com. The README shows the command with port 2525.

```bash
./manage.py smtpd
```

For production, the README points at a Dockerfile in the docker/ directory and pre-built images on Docker Hub. Configuration comes from environment variables, with the full list in the self-hosted configuration documentation on healthchecks.io. Settings can also live in hc/local_settings.py, which you create by copying hc/local_settings.py.example. If a setting is specified both as an environment variable and in that file, the file wins.

## SMTP is a hard dependency, not an optional integration

The README is blunt about this: Healthchecks must be able to send email messages, so it can send out login links and alerts to users. That single sentence rules out a class of deployments. If your environment blocks outbound SMTP, or you have no relay credentials, you cannot complete a login, and you cannot receive alerts through the mail path. The 25-plus notification integrations cover alert delivery to other channels, but the login link path is email.

Configuration is split between implicit TLS on port 465 and explicit TLS on port 587. The README recommends implicit TLS and cites RFC8314 Section 3.3 for that preference, with the warning to use a TLS certificate and not an SSL one. The implicit variant sets EMAIL_USE_TLS to False and EMAIL_USE_SSL to True; the explicit variant sets EMAIL_USE_TLS to True and omits the SSL flag. Getting this pair backwards is a common source of a server that starts cleanly and then silently fails to deliver. Healthchecks builds the MAILERS dictionary from these variables, so the failure surfaces as a Django mail error rather than a startup error.

A second constraint is the database. The README lists PostgreSQL, MySQL or MariaDB as the building blocks, and the default development configuration uses SQLite. SQLite is presented in the context of a development checkout. The README does not state a supported production configuration for SQLite, so treat the development default as a convenience rather than a deployment target.

## Healthchecks against Uptime Kuma and Cronitor

The two comparisons that come up most often are Uptime Kuma and Cronitor, and they differ in what they watch. Uptime Kuma is aimed at uptime monitoring of endpoints and services: you point it at a URL or a port and it checks reachability on a schedule. Healthchecks is aimed at the opposite direction. It does not probe your job; it waits for your job to report in. A cron job that runs on a machine with no inbound access is invisible to a prober but perfectly visible to Healthchecks, because the ping travels outward. If you need to know whether an HTTP service answers, a prober is the right tool. If you need to know whether last night's backup script ran, a prober has nothing to check.

Cronitor occupies the same category as Healthchecks, heartbeat monitoring for scheduled jobs, but it is a commercial service rather than a codebase you run. The difference that matters for adoption is operational: with Healthchecks you own the database, the SMTP path and the upgrade cycle, and you can read the source when a check behaves unexpectedly. With a hosted monitor you trade that control for not having to run Django. The README points at healthchecks.io as the hosted instance of this same project, so the choice between them is a deployment decision rather than a feature decision.

One more distinction worth naming: Healthchecks is not a metrics system. The statsd dependency means it can emit its own metrics, but it does not scrape or store your application's time series. For that you want a metrics pipeline, and Healthchecks would sit alongside it.

## Maintenance, releases and licence

The repository is not archived. The last push was on 2026-09-21, and the most recent tagged release is v4.4 from 2026-08-31, preceded by v4.3 on 2026-07-14 and v4.2 on 2026-04-28. That cadence, roughly two to three months between tags, is what an operator should plan upgrades around. There is a CHANGELOG.md at the top level, which is where upgrade notes would appear; the README itself does not document a rollback procedure, so a migration that goes wrong has to be handled with your own database backups. The ./manage.py migrate step is the one to watch on every upgrade, because schema changes land there.

The licence is BSD 3-clause, and the LICENSE file sits at the repository root. For most self-hosted internal use the practical implication is that you can run and modify the code, but the licence text itself is the authority and this is not legal advice. If you plan to redistribute a modified version or offer it as a service, read the LICENSE file and the copyright notice rather than relying on a summary.

The maintenance cost beyond upgrades is the surrounding infrastructure: a database, an SMTP relay, and a process supervisor for the web application and, if you use email pings, the smtpd command. The Dockerfile and pre-built images reduce the build work but do not remove the database and mail dependencies.

## Conclusion

Adopt Healthchecks if you run scheduled jobs you cannot watch by hand and you want the server on your own infrastructure, with PostgreSQL, MySQL or MariaDB behind it. Do not adopt it if you need a monitoring system driven by an agent or by metrics scraping, or if you have no email path out, since login links and alerts both depend on SMTP. Before committing, verify three things: that your database choice is supported, that the SMTP variables produce working mail, and whether the hosted healthchecks.io service is a better fit than operating Django yourself. The repository also ships a Dockerfile and pre-built images, so the fastest way to judge it is to bring up one container and send a single ping to a check.

## FAQ

### Is Healthchecks.io open source?

Yes. The Healthchecks codebase is licensed under the BSD 3-clause license, with the LICENSE file at the repository root, and the hosted service at healthchecks.io runs that same project.

### Is Healthchecks.io free?

The software is BSD 3-clause licensed, so you can self-host it at no licence cost. The README also points to a hosted service at healthchecks.io, but it does not describe that service's pricing.

### How do I use Healthchecks.io?

You create a check in the dashboard, then have your cron job or scheduled task send an HTTP request or an email message to that check's address. Healthchecks records the ping, and if the next one does not arrive within the check's period plus grace time, it sends alerts.

### What is Healthchecks.io?

It is a cron job monitoring service that listens for pings from your scheduled tasks and alerts you when a ping does not arrive on time. The project ships a web dashboard, an API, notification integrations, WebAuthn 2FA and team management features.

### How does Healthchecks compare with Uptime Kuma?

Uptime Kuma checks whether an endpoint or service is reachable, while Healthchecks waits for your job to report in. A job with no inbound access can still ping Healthchecks, but a prober would have nothing to check.

### How does Healthchecks compare with Cronitor?

Both monitor scheduled jobs by expecting a heartbeat. Cronitor is a commercial service, while Healthchecks is a codebase you can run yourself, which means you own the database, the SMTP path and the upgrade cycle.

## Sources

- [healthchecks/healthchecks on GitHub](https://github.com/healthchecks/healthchecks)
- [License: BSD-3-Clause](https://github.com/healthchecks/healthchecks/blob/master/LICENSE)
- [Project website](https://healthchecks.io)
- [README](https://github.com/healthchecks/healthchecks/blob/master/README.md)
- [Releases](https://github.com/healthchecks/healthchecks/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/healthchecks-healthchecks
