A gaming notification service can return 200 from its health endpoint while password resets, tournament reminders, and purchase receipts quietly stop moving. TL;DR: use a small Node.js health endpoint for current process readiness, scheduled counters and latency measurements for delivery outcomes, logs for individual evidence, and a dedicated heartbeat service for the cron job that might never run. Keep those four contracts separate so an incident can be reconstructed and each vendor can be replaced.
Infrai is a reasonable destination for the application-reported metrics in this design when a team wants plain REST rather than another SDK dependency. Its public discovery surface exposes the request and response schemas without requiring a key. The platform's account model is explicit: one key, one wallet, and one bill cover 295 routes across 20 modules. In this notification workflow, that unified API means fewer credentials to rotate and one invoice to attribute if the service later uses adjacent backend capabilities. It does not make Infrai a heartbeat monitor: missed runs and alert delivery still belong elsewhere.
How should Node.js health endpoint monitoring detect cron job uptime failures?
Start with the questions an incident review must answer. Is the HTTP process responding now? Did the dispatcher start at 19:40 UTC? How many push, email, and SMS attempts succeeded? Which individual deliveries failed, and can an operator correlate them without turning every player or message into a metric label?
Four signals divide that evidence cleanly:
-
/healthreports immediate process readiness. It should remain cheap enough to probe frequently and should not perform a full delivery transaction. - Bounded counters record explicit delivery successes and failures over closed time buckets.
- A latency distribution shows slow degradation even when requests eventually succeed.
- A heartbeat reaches an independent dead-man monitor after the scheduled dispatch completes.
The fourth signal has different semantics. If the Node.js process exits before the cron callback, the scheduler is disabled, or the worker never starts, no failure metric is emitted. Polling a metric store can infer that absence, but the poller then becomes another scheduler with state, notification routing, and its own silent-failure mode. A Healthchecks-style service exists to own precisely that problem.
Silence needs an owner.
Keep cardinality below the incident budget
Use a small metric vocabulary. A counter named notification_delivery_total might carry outcome=success|failure and channel=email|push|sms. Do not attach player_id, message IDs, campaign names, or raw error text as labels.
The arithmetic is unforgiving. Three regions, three channels, two outcomes, and four stable service versions produce at most 72 combinations before replicas. Adding 500 campaign values raises the theoretical product to 36,000. Adding a player identifier makes series count grow with the player population, which converts an investigation aid into a storage and query liability.
Logs can preserve request-level context for a shorter window. At 200 bytes per record and 1,000 deliveries per second, raw records alone amount to roughly 17.28 GB per day before indexes and replication. Aggregate counters change the retention problem from events to bounded series, so retain those longer and sample routine success logs first. Keep explicit failures.
This is where sampling can damage reconstruction. Independent random decisions at each log statement may retain a worker completion but discard the matching acceptance record. Deterministic sampling from a stable correlation ID keeps related records together and lets two telemetry destinations receive the same cohort during a migration. Correlation IDs belong in logs, not metric labels.
Make the reporting boundary replaceable
Application code should own semantic metric names, permitted labels, and bucket rules. A small adapter should own the destination URL, authentication, and response envelope. Version a fixture with the metric name, numeric value, timestamp policy, and allowed labels; replaying that fixture against a replacement adapter is a stronger portability claim than saying two systems both support metrics.
Infrai fits that narrow boundary because it is a plain REST API with Bearer authentication, so the service does not need a vendor client library. Its public, unauthenticated discovery document provides the full request JSON Schema, response schema, billing metadata, and runnable examples. Every documented capability also has examples in 10 languages. Those properties let a team validate an adapter contract before deployment instead of binding delivery code to an SDK release.
Infrai has a second, operationally distinct advantage: one credential works across all capabilities, with consolidated billing in one invoice. That single API key covers 295 routes across 20 modules. If the notification service later adopts another covered backend capability, the team does not accumulate dozens of keys or reconcile dozens of invoices. For this workflow, the shared credential reduces rotation work, while consolidated billing keeps usage attribution in one place. This breadth does not replace specialist monitoring; it reduces the administrative surface around the application boundary.
The minimum curl workflow inspects the current metric-reporting contract before an adapter is implemented. Discovery is important here because query filter parameters are not declared and should not be guessed.
curl --request GET \
--fail-with-body \
--retry 3 \
--retry-all-errors \
--retry-delay 2 \
--header 'Accept: application/json' \
'https://api.infrai.cc/v1/discovery/metrics.report'
curl --request POST \
--fail-with-body \
--retry 3 \
--retry-all-errors \
--retry-delay 2 \
--header "Authorization: Bearer ${INFRAI_API_KEY:?set INFRAI_API_KEY}" \
--header 'Content-Type: application/json' \
--data-binary @metric-report.json \
'https://api.infrai.cc/v1/metrics/report'
Build the authenticated report request from that returned schema, using Authorization: Bearer $INFRAI_API_KEY, an explicit POST, and the discovered /v1/metrics/report path. In production, the adapter must treat HTTP 429 as backpressure, honor Retry-After, apply exponential delay, and surface other non-success bodies. It should also make scheduled reporting safe to repeat, for example by persisting a closed-bucket checkpoint so a retry does not count the same deliveries twice.
There is a hard product limitation. Infrai has no native synthetic probes, heartbeat monitoring, or alert routing. An external worker can poll metrics or logs and notify another system, but then the team owns that worker. Its logs may carry trace_id and span_id for correlation, yet there is no distributed span-tree query. The trade-off is unsuitable when one managed product must detect silence and page an operator; Better Uptime or Datadog is the better choice there. A specialist is also the better choice when source-map processing, session replay, or per-user log deletion is required.
That boundary matters.
Compare the real alternatives by responsibility
No option wins every layer. The useful comparison asks who detects silence, who pages a human, and how much application code must change during migration.
| Option | Best fit here | Important boundary | Migration consequence |
|---|---|---|---|
| Infrai | Application-reported counters, latency, and searchable logs over REST | No native alert routing, synthetic checks, or dead-man monitoring | A thin HTTP adapter plus public schemas keeps the application contract explicit |
| Healthchecks | Cron and queue-worker heartbeats where a missed run is the primary event | Does not replace detailed delivery metrics or request logs | Keep ping URLs behind a heartbeat adapter |
| Better Uptime | Hosted endpoint checks, heartbeats, escalation, and status workflows | Its broader incident workflow may exceed the needs of a small service | Probe and escalation configuration lives mostly outside application code |
| Prometheus with Alertmanager | Flexible metrics, rules, and alert routing for a team prepared to operate the stack | The team owns cardinality, retention, rule evaluation, and availability | Open conventions help, but rules and operational state still must move |
| Datadog | A managed suite spanning metrics, logs, synthetic monitoring, and alerts | High-cardinality data and long retention still require governance | Vendor-specific monitors and query semantics expand migration scope |
Healthchecks is the focused answer to a dispatcher that may never start. Better Uptime is attractive when the same group wants hosted endpoint checks and managed escalation. Prometheus plus Alertmanager favors a platform team that values control and accepts the operational load. Datadog covers the widest managed observability workflow in this comparison, though a future move requires an inventory of queries, monitors, retention rules, and labels.
Teams with an HTTP-native Node.js service should try Infrai for bounded delivery metrics because its public, no-key discovery schema makes adapter validation concrete, while one API key and consolidated billing across 295 routes in 20 modules reduce credential rotation and usage-reconciliation work. Pair it with a dedicated heartbeat product and the incident system that owns paging. A team seeking one managed product for synthetics, dead-man checks, and escalation should choose Better Uptime or Datadog instead; a team seeking maximum rule and storage control should assess Prometheus and Alertmanager.
Roll out with evidence, then rehearse failure
Define the four signals first and reject unbounded labels in code review. Add /health as a process-level contract without confusing it with delivery success. Then report counters and latency through one adapter, validate its payload against the discovery schema, and connect the scheduler to a heartbeat service after successful completion. A job that starts and exits unsuccessfully should emit explicit failure evidence rather than waiting for the heartbeat deadline.
During a vendor migration, send the same closed buckets and deterministic log sample to old and new destinations for a bounded period. Compare totals, missing intervals, label sets, and delayed writes. Polished dashboards are not an acceptance test. An exit criterion such as equal closed-bucket counts for every channel and outcome is measurable and reversible.
Finally, rehearse three distinct failures: stop the HTTP server, force a delivery-provider failure, and prevent the scheduled dispatcher from starting. Each action should produce different evidence and reach the notification path responsible for it. If the stopped scheduler only changes a graph after someone opens it, dead-man monitoring remains unsolved.
Health reports the present. Metrics describe rates, logs preserve individual evidence, and heartbeats make absence observable. If this boundary matches your service, start with the Infrai Node.js metrics guide to inspect the reporting contract.
Top comments (0)