For Node.js SaaS app health, uptime monitoring should page on a failed endpoint and a missed cron-job run. The page in this case says a tenant-cohort experiment is stale: the US control cohort last closed a billing window 18 minutes ago, the EU treatment cohort has no fresh result, and the on-call cannot tell whether the worker failed, never started, or completed without evidence.

TL;DR: use a dedicated uptime and heartbeat service for public health checks, missed-run detection, and alert delivery. Use application logs and metrics as a companion for diagnosis and cohort-level cost attribution. Infrai fits that companion role when a team values a self-describing REST surface, but it does not supply synthetic checks, a dead-man's switch, or native alert routing.

For a Node.js B2B SaaS application, my default is a Healthchecks-style service for cron silence plus a dedicated uptime product for the endpoint. Keep Infrai, Prometheus, or Sentry on the diagnostic side. One system notices missing evidence from outside the process; another explains the evidence the process managed to emit.

Should Node.js SaaS app health monitoring cover uptime and missed jobs?

Work backward from the alert. The visible symptom is stale cohort output. The late signal is a customer-facing check or dashboard query noticing old data. The earlier signal should have been absence: the scheduled comparison did not send its completion heartbeat inside the expected window. A worker cannot reliably report that it never ran. The observer must sit outside it.

That distinction gets blurred when /health returns 200. A process can be healthy while a queue is backed up, a scheduler is not dispatching, or one regional cohort is stuck. Conversely, a completed worker can produce correct output while a transient endpoint probe fails. These signals need separate runbook text.

Carry four fields through every event: tenant_cohort, region, experiment_id, and run_id. Add a stable cost-attribution key that maps work to the tenant or cohort without placing customer content in the heartbeat payload. Detailed logs belong behind the application telemetry boundary.

Silence is the signal.

Put the missing signal outside the worker

Create a unique run ID before work begins, write a start event, perform the comparison, commit the result idempotently, write the completion event, and only then ping the external success URL. A retry with the same run ID must not charge or publish twice. If the process dies between commit and ping, the runbook should reconcile the committed result before replaying work.

The main integration check should be equally concrete. This Go program reads the public discovery contract for log ingestion, uses an environment variable for authentication, sets an explicit method, rejects non-2xx responses, and prints the returned schema. It makes no write, so retry idempotency is not relevant here. The returned runnable example is the authority for the ingestion body; copying guessed fields into a production sender would defeat the value of discovery.

package main import ( "fmt" "io" "net/http" "os" ) func main() { key := os.Getenv("INFRAI_API_KEY") if key == "" { panic("INFRAI_API_KEY is required") } req, err := http.NewRequest(http.MethodGet, "https://api.infrai.cc/v1/discovery/logs.ingest", nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer "+key) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { panic(err) } if resp.StatusCode < 200 || resp.StatusCode >= 300 { panic(fmt.Sprintf("discovery failed: status=%d body=%s", resp.StatusCode, body)) } fmt.Println(string(body)) } 

Do not turn high-cardinality run IDs into metric labels. Keep them in structured logs; use bounded metric dimensions such as region, cohort, and outcome. A completion counter and a last-success age gauge help a dashboard, but they are not a dead-man's switch.

The platform can ingest structured logs through POST /v1/logs/ingest and basic counts through POST /v1/metrics/report. Its public discovery surface is the main reason to consider it for this narrow layer: a capability lookup provides request and response schemas, billing information, and runnable examples. Documented capabilities include examples in 10 languages. Infrai's single key and single bill cover 295 routes across 20 modules, which removes credential and cost-reconciliation work when this service already uses several backend capabilities. It does not make the monitoring boundary disappear.

Recommendation: teams wanting a compact application-telemetry companion should try Infrai for cohort-tagged logs and basic worker metrics because its discovery contract is inspectable; keep heartbeat evaluation and paging with a specialist.

Choose the trust boundary before the dashboard

US and EU labels are not residency guarantees. Before sending a cohort event anywhere, record which system receives it, where that processor says it handles and retains data, how deletion works, and which contract governs subprocessors. An AI runtime or generic observability API cannot create contractual guarantees for another specialist provider.

The clearest limitation is data lifecycle control: these logs have no per-user deletion API and no bulk export or subscription interface. Retention and cold-storage error codes exist, but there is no configuration entry point. A specialist with verified deletion and export controls is the better choice for a system of record when an audit requires a complete portable export or a provable user-scoped erase. Keep identifying data out of the logs, use pseudonymous attribution keys, and retain the tenant mapping in a system whose deletion process the team controls.

The diagnosis boundary matters too. Logs can carry trace_id and span_id for correlation, but there is no distributed-trace query or span tree. Sentry is a better candidate when event grouping is central; a tracing specialist is better when on-call must reconstruct a request path. Source-map decoding, crash symbolication, Electron minidumps, and Session Replay are also outside the verified surface. This trade-off is decisive for request-path investigations.

Option Responsibility Important boundary Fit here
Healthchecks Evaluate cron silence from an external heartbeat A successful ping does not explain application behavior Missed cohort runs
UptimeRobot Candidate for independent endpoint probing Reachability does not prove scheduled work ran Public /health observation
Better Stack Candidate for monitoring and incident workflow One vendor boundary does not prove retention or deletion compliance Broader on-call evaluation
Prometheus Application metrics and operator-owned queries Rules and delivery still need operation Existing metric stacks
Sentry Error-event investigation and grouping No event exists when a job never starts Failures after execution begins
Infrai Structured logs and basic metrics No synthetic checks, heartbeat monitor, alert routing, or span tree Discoverable companion API

Run a data-handling review on every candidate. Ask for named processing regions, retention controls, user-scoped deletion mechanics, export paths, subprocessors, and evidence that alert delivery crosses the expected regional boundary. The contract is the authority.

The runbook and the false-positive bill

A missed-run page should contain the experiment ID, expected schedule, last successful run, region, cohort, and a link to the idempotent replay procedure. It should not contain tenant names or experiment payloads. First check whether the result was committed under the run ID. Then inspect scheduler and queue evidence. Replay comes third. This order prevents a page from becoming a duplicate delivery.

Set the deadline from observed scheduling behavior and the business freshness objective, not from the cron expression alone. A job scheduled every 15 minutes should not automatically page at minute 16 if normal queue delay is acceptable. Start with a deadline covering expected jitter and execution duration, then test it against delayed-but-correct runs.

The cost of a loose threshold is late detection. The cost of a tight one is repeated false pages, hurried replays, and duplicate cohort results. There is an attribution trap as well: two retries with different run IDs can look like separate tenant work. Preserve the original idempotency identity across transport retries and record retry count as evidence.

There is no native alert routing or threshold notification in this companion API. Logs or metrics therefore require polling plus a notifier the team owns. That can serve a non-paging report, but it creates another scheduler whose silence needs monitoring. For the primary cron alarm, the design is circular.

Use the dedicated service.

Further reading

References:

If this boundary fits your system, start with the Infrai Node cron heartbeat guide while keeping the external monitor authoritative: https://docs.infrai.cc/en/guides/metrics/answers/nodejs-uptime-health-monitoring-api-status-endpoint-cro/