Tech Digest

Monitoring

Uptime Kuma

Uptime checks, alerting and status pages in one container, no separate database

MonitoringMITMaturearm64 builds
Last reviewed Profile maintained against the project's own documentation
Operational load
2 / 5
Light
Idle memory
120 MB
typical use ~250 MB
Moving parts
1
containers in a normal deployment
Backup shape
SQLite backup
needs a dump or a stop

Uptime Kuma polls HTTP endpoints, TCP ports, DNS records, containers, MQTT topics and push heartbeats on a schedule, then notifies through Apprise and around 90 built-in providers. It covers what people rent UptimeRobot or Pingdom for, plus public status pages, on hardware you already own.

Our verdict on Uptime Kuma#

The default answer for "is my stuff up" if you want a UI rather than a config file. Version 2 is out of beta and current: 2.5.3 shipped in August 2026, and 2.x is the tag the project publishes as louislam/uptime-kuma:2. The big v2 change is storage. v1 wrote one heartbeat row per check forever, so 50 monitors at 60 seconds meant roughly 72,000 rows a day and multi GB SQLite files; v2 keeps 24 hours of raw beats and rolls the rest into minute, hour and day tables, with a 365 day default retention. MariaDB is supported in v2, but the project explicitly does not support migrating an existing SQLite database into it, so treat that as a new install decision. The honest limit: one instance is one vantage point, and it cannot tell you it went down itself. Pair it with an external ping or a second instance elsewhere.

Who Uptime Kuma is for#

Choose it if

  • Someone running 10 to 100 self-hosted services who wants alerts in Telegram or ntfy without writing YAML
  • A small business that needs a public status page mapped to its own domain
  • Anyone replacing a paid uptime checker whose free tier caps intervals at five minutes
  • Homelabbers who want certificate expiry and domain expiry warnings alongside uptime

Look elsewhere if

  • You want your monitoring defined in git and reviewed like code; Gatus fits that shape and Uptime Kuma does not
  • You need metrics, not up or down: it does not store CPU, memory or disk series
  • You need highly available checks from multiple regions, which the project has no clustering story for

What running it actually looks like#

One container, one volume at /app/data, port 3001, and nothing else to stand up. First run creates the admin account in the browser; there is no seed password to rotate. The README warns that NFS is not supported for the data volume, and it means it: SQLite locking over NFS or CIFS corrupts the database. A rootless image tag exists if you do not want the default root entrypoint. The image is large for what it does (around 600 MB compressed) because it bundles Apprise, cloudflared and nscd. The upgrade that bites is v1 to v2: on first start it aggregates the heartbeat table, which the migration guide says took about 7 minutes for 20 monitors and 90 days of data, and can run for hours on slower hardware. Interrupt it and you restore from backup.

Resource profile#

Memory
120 MB idle, around 250 MB in ordinary use. A single Node process. Heap tracks the number of monitors and open dashboard sockets, not the length of history.
CPU and acceleration
Flat between checks, with spikes when many monitors land on the same second. The one real CPU event is the v1 to v2 heartbeat aggregation, which runs once and can hold a core for minutes or hours.
Storage growth
v2 keeps only 24 hours of raw heartbeats per monitor plus minute, hour and day aggregates, so a 50 monitor instance settles in the low hundreds of MB; v1 databases that were never pruned commonly arrive at several GB.
Operational load
2 of 5, Light. One container, one SQLite file, upgrades inside 2.x are pull and restart. It is a 2 rather than a 1 because the v1 to v2 upgrade is a one way data migration you must not interrupt, and because the database needs an occasional manual shrink.

Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.

Data and backup surface#

Everything lives in /app/data: kuma.db (SQLite in WAL mode), plus uploads and screenshots. A live cp of the file alone is not safe because the WAL may hold recent commits; either stop the container and copy the whole directory, or run sqlite3 kuma.db ".backup out.db" against a copy. Nothing in there is regenerable, including notification credentials and status page config. If you moved to MariaDB, back it up with mysqldump and keep /app/data as well, since uploads still live on disk.

Derived backup shape

SQLite backup. sqlite3 <db> ".backup out.db" while running, or stop the container and copy. A live cp of a WAL-mode SQLite file can restore corrupt.

Traps and surprises#

The v1 to v2 migration is one way

Upgrading rewrites heartbeat history into aggregate tables. There is no downgrade path, and the wiki is explicit that an interrupted migration means restoring from backup and starting again. Snapshot /app/data first, pin the old image tag so you can roll back the container, and give the migration an uninterrupted window rather than starting it before you leave the house.

Deleting old data does not free disk

Retention defaults to 365 days and the cleanup job deletes rows, but SQLite returns those pages to its own free list rather than to the filesystem. The database file keeps its size until you use Shrink Database in Settings, which runs VACUUM. Expect the shrink to need free space roughly equal to the current database size while it runs.

SQLite on network storage corrupts

The README explicitly lists NFS as unsupported for the data volume, and CIFS behaves the same way: SQLite's locking assumptions do not survive it. Symptoms are 'database is locked' errors and, eventually, a database that will not open. Keep /app/data on local disk or a local Docker volume, and back up to the NAS instead of running from it.

Reverse proxies must pass WebSockets

The dashboard is socket.io. A proxy configured for plain HTTP gives you a page that loads, then spins forever with no monitors and no error. In nginx that means proxy_set_header Upgrade $http_upgrade and Connection "upgrade"; in Caddy and Traefik it works by default. The same applies to status pages behind Cloudflare with WebSockets disabled.

MariaDB is not a migration target

v2 can run on MariaDB, but the project does not support converting an existing SQLite install and warns that third party converters miss indexes, which wrecks query performance. If you want MariaDB, decide at install time. Most single-operator instances with fewer than a few hundred monitors have no reason to leave SQLite.

Specifications#

Category
Monitoring and observability
Licence
MIT (Permissive)
Written in
JavaScript / Node.js
First release
2021
Maturity
Mature
Datastore
SQLite by default, MariaDB optional in v2
Default ports
3001
Ships as
docker, node.js + pm2
arm64 builds
Yes
Identity
Local accounts only. Local accounts with optional TOTP only; the OAuth support in the codebase authenticates monitored endpoints, not people logging in.
Replaces
UptimeRobot, Pingdom, StatusCake, Better Stack Uptime
Project site
uptime.kuma.pet
Source
github.com/louislam/uptime-kuma
Documentation
github.com/louislam/uptime-kuma/wiki

Alternatives to Uptime Kuma#

Everything else in monitoring and observability, closest in operational weight first.

ToolOps loadIdle RAMLicence
Grafana2, Light150 MBAGPL-3.0-only
Netdata2, Light150 MBGPL-3.0-or-later (agent); dashboard UI under NCUL1
Beszel1, Set and forget40 MBMIT
Dozzle1, Set and forget15 MBMIT
Gatus1, Set and forget25 MBApache-2.0
Prometheus3, Moderate150 MBApache-2.0

Where Uptime Kuma comes up elsewhere#

Sources#

Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.

  1. Project repository and install instructions
  2. Releases, current 2.5.3
  3. Migration from v1 to v2 wiki page
  4. Official site
  5. Retention job source, 365 day default

Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.