Push numbers in. Watch them on the wall.

upcheckr is one self-contained binary (SQLite inside). Apps authenticate with an API key and POST metrics; the wall renders them live. No exporters, no scraping, no agents.

Quickstart

1. Download & run the binary, open http://localhost:8080, set a password.

# macOS / Linux UPCHECKR_ADMIN_PASSWORD=secret ./upcheckr-macos-arm64

2. On the API keys screen, create a key. It's shown once — keys look like acme_prod_… (derived from your instance + source name).

3. Push a value from anywhere:

curl -X POST http://localhost:8080/api/v1/metrics \ -H "X-API-Key: acme_prod_…" \ -d '{"name":"active_users","value":52,"instance":"web-1"}'

The tile appears on the wall instantly and updates live as more values arrive.

The push API

POST /api/v1/metrics with header X-API-Key: <key>. The body is a batch of points (up to 1000). Content-Type is optional — a bare curl -d works.

{ "metrics": [ { "name": "active_users", "value": 52, "instance": "web-1", "type": "gauge", "labels": {"region":"eu"}, "ts": 1730000000000 } ] }
fieldrequirednotes
nameyes1–120 chars; letters, digits, spaces, _ . : -. Auto-registers on first push.
valueyesfinite number (NaN/±Inf rejected).
instancenowhich server/stream reported it; aggregations roll up across instances.
typenogauge | counter, set on first push.
labelsnoJSON object of dimensions.
tsnoepoch ms; defaults to server time.

Each request is validated synchronously and returns immediately — { "accepted": N, "rejected": [...] } — then persisted by a background writer (so your app is never blocked on the database). Invalid items are skipped; the good ones still land.

Node

await fetch("http://localhost:8080/api/v1/metrics", { method: "POST", headers: { "X-API-Key": "acme_prod_…", "Content-Type": "application/json" }, body: JSON.stringify({ metrics: [{ name: "active_users", value: 52, instance: "web-1" }] }), });

Python

import requests requests.post("http://localhost:8080/api/v1/metrics", headers={"X-API-Key": "acme_prod_…"}, json={"metrics": [{"name": "active_users", "value": 52, "instance": "web-1"}]})

Aggregations

Each tile rolls a metric up across the instances reporting in. Pick one per metric:

aggwhat it shows
lastthe single most-recent value
sumtotal across instances
avgaverage across instances
min / maxlowest / highest
countnumber of samples in the window
ratesummed increments ÷ window seconds
p9595th-percentile of the raw samples

Set a threshold per metric to color the bars (green → amber → red) and flag warning/over — free on every tier. The metric detail page adds Combined / Stacked / Overlaid per-instance views.

Self-host

One binary, no dependencies. Download for your platform (or use the JVM jar on Intel Macs).

env vardefaultwhat
UPCHECKR_ADMIN_PASSWORDgeneratedadmin login password (printed once if unset).
UPCHECKR_DB~/.upcheckr/upcheckr.dbSQLite file path.
UPCHECKR_INSTANCE_NAMEacmeshown in the UI; seeds the key prefix.
UPCHECKR_RETENTION_DAYS7rolling datapoint window.
UPCHECKR_HOSTpublic domain used in push examples.

Point a display at it and hit Wall mode for a chrome-free, fullscreen wall — perfect for a TV. Data persists in SQLite across restarts; back up or migrate via Settings → Export / Import.

Download the binary Watch the demo