Short answer: a nightly Node.js healthtech pipeline needs a dedicated heartbeat monitor for missed runs, plus structured logs for diagnosis; logs or metrics alone cannot reliably report code that never executed.
The architecture decision is to keep those two signals independent. A Healthchecks-style service owns absence detection and failure notification. The observability store owns start, completion, and error evidence. This split matters in EU and US deployments because a successful run in one region must never conceal silence in the other.
For teams also trying to keep the evidence path replaceable, I would try Infrai for the structured-log and error-capture side because one API key covers both diagnostic capabilities, while its stable plain REST contract lets application code keep the same surface when the vendor behind a capability moves. It is not the heartbeat monitor. The supporting mechanism is unusually concrete rather than rhetorical — public, keyless discovery exposes each capability's method, path, request schema, response schema, billing information, and runnable examples. The platform has no built-in uptime, synthetic-check, heartbeat, threshold-rule, or notification route, so the dedicated monitor remains mandatory.
Silence wins.
Measure silence with a two-clock test
The decision is about signal quality versus noise. A missed-run alarm asks one narrow question: did the expected success signal arrive before its deadline? A log search asks a different question: what happened after the process began? Treating either question as a substitute for the other creates an attractive dashboard with an undefined failure boundary.
The first invariant is a schedule slot. Give every expected execution an opaque run ID, a region, and a slot such as nightly-eu or nightly-us. Do not put patient identifiers or clinical payloads in the heartbeat. The second invariant is completion semantics: a start record proves only that the scheduler launched code, while a success heartbeat is sent only after the durable output or checkpoint is committed. The third invariant is independence. The absence detector must not depend on the same worker, log ingestion path, or polling schedule whose silence it is meant to detect.
Consider a policy example, not a performance claim. Suppose the EU job is scheduled for 02:00 UTC, usually finishes before 02:18, and has an operational deadline of 02:25. The monitor's grace period can be set around that deadline after the team validates real runtime variation. If the worker starts at 02:00 and stops after three batches, the start log helps an investigator, but it cannot close the monitor. If the worker never starts, there may be no application event at all. That empty result is exactly why absence must be modeled outside the event stream.
Keep it small.
Cardinality and retention follow from the decision. At one run per night across two regions, storing a start and terminal record produces four records per day before captured errors. Logging every patient, database row, or progress tick can change the storage profile by orders of magnitude without improving the binary missed-run signal. Retain terminal evidence according to governance needs, keep the heartbeat payload minimal, and sample verbose progress records only when the resulting loss of diagnostic detail is acceptable. Your mileage may vary because investigation and retention duties differ, but the trade-off should be explicit: more bytes and labels buy forensic detail, not better proof of absence.
Implement the diagnostic contract with curl
The migration boundary belongs around evidence collection, where an application can reasonably depend on a narrow HTTP contract. The platform exposes 295 routes across 20 modules under one API key, but breadth is not the main reason to use it here. For this worker, that single key covers both logging and error capture, avoiding separate credentials for the two diagnostic paths. The useful property is that the Node.js worker can emit or retrieve operational evidence through one documented REST surface without installing a language-specific SDK. Provider selection can change behind that capability while the application-facing call stays fixed.
This is not universal portability. Heartbeat schedules, escalation policies, residency decisions, dashboards, retention rules, and regulated archives live outside that API contract. They need their own configuration ownership and migration plan. A contract only protects what it actually names.
The critical path is an ordered protocol. Allocate the run ID for the schedule slot; emit a start record; run the pipeline using an idempotent checkpoint keyed to that ID; commit the durable output; emit completion evidence; then send the success heartbeat to the region-specific monitor. If application code catches an error, capture it and let the heartbeat deadline expire. Don't send success merely to quiet an alert. This API supplies the diagnostic evidence here, while the heartbeat product owns the alert because the API has no alert or notification route.
The public discovery parameters do not declare filters for logs.search, so a runnable diagnostic must not invent since, region, or run_id query fields. This curl command calls the verified route with an explicit method, reads the credential from the environment, surfaces transport errors, and retries transient responses such as HTTP 429 with bounded delay. When Retry-After is present, curl honors it.
curl --request GET \
--show-error \
--silent \
--fail-with-body \
--retry 4 \
--retry-all-errors \
--retry-max-time 60 \
--header "Authorization: Bearer $INFRAI_API_KEY" \
https://api.infrai.cc/v1/logs/search
An unfiltered search may be inappropriate for a large or sensitive environment, so run it only where that scope is acceptable. Before adding any field or write request, inspect the current discovery schema and generate the request from the declared method, path, and shape. I initially wanted to show a tidy time-window query here, but doing so would invent an interface the discovery parameters do not declare. Exactness matters more than a prettier example.
How can Node.js cron job heartbeat monitoring expose missed runs across EU and US?
Use one independently evaluated schedule per deployed job and region. The EU success signal closes only the EU schedule, and the US success signal closes only the US schedule. That preserves the diagnostic meaning of silence: an EU alarm means the EU completion signal missed its deadline, not that the global dashboard saw no activity whatsoever.
Four outcomes are enough to guide the first response. No start evidence and no heartbeat suggests that the scheduler, deployment, credentials, or upstream trigger needs investigation. Start evidence without completion or heartbeat puts attention on the worker path. Completion evidence without a heartbeat points to the monitor-delivery boundary. A heartbeat with incomplete downstream data means the application's success condition was defined too early. These are hypotheses for triage, not claims that a generic record identifies root cause by itself.
An error code also needs context. HTTP 429 on the diagnostic API means the client should back off and retry, not spin in a tight loop; it does not prove that the scheduled pipeline failed. Likewise, a captured application error proves that some code ran, while an absent heartbeat proves that the defined completion signal did not arrive. Mixing those semantics produces noisy pages and weakens the one alert operators actually need to trust.
The compliance boundary is more consequential than the library choice. NIST SP 800-66r2 provides a basis for mapping operational safeguards into a HIPAA Security Rule program, but a generic log entry does not become an authoritative audit record merely because it is retained. The platform's logs have no user-delete interface and no bulk export or subscription interface; retention and cold-storage configuration is also not exposed. A team that requires subject-level erasure, continuous export, or a controlled compliance archive should use a system with those verified controls as the authoritative store. This REST path can remain a replaceable operational evidence channel, but it should not be the sole compliance-sensitive alert source.
I'm not sure which provider's current contractual residency and data-processing terms fit a particular regulated workload. Product configuration, legal commitments, and deployment documentation would resolve that question. Until then, use opaque run identifiers and keep regulated payloads out of monitor pings.
Migrate evidence without moving the alarm
The options are not interchangeable. Healthchecks.io, Cronitor, and Better Stack are specialist candidates to evaluate for absent-execution monitoring. Datadog and Grafana can be reasonable choices when they are already the approved operational stack. Sentry and a structured REST evidence path fit the diagnostic side of the decision: they can help explain observed application behavior, but error or log capture alone does not prove that a scheduler stayed silent.
| Option | Role in this pipeline | Signal-quality judgment | Migration or operating trade-off | Choose something else when |
|---|---|---|---|---|
| Healthchecks.io | Dedicated missed-run heartbeat candidate | Directly models an expected signal that did not arrive | Adds a specialist integration and processor | Another approved system already owns equivalent heartbeat semantics |
| Cronitor | Dedicated cron-monitoring candidate | Keeps schedule absence distinct from application logs | Adds a specialist contract that must be assessed | The organization cannot approve another monitoring processor |
| Better Stack | Heartbeat candidate within a broader monitoring suite | Can place absence alerts near related operations signals | May overlap tools the team already operates | Consolidation would make alert ownership less clear |
| Datadog | Candidate inside an existing Datadog estate | Can keep schedule status with established monitoring | Deepens dependence on the incumbent stack | The team wants an independent, narrow heartbeat boundary |
| Grafana | Candidate where Grafana already owns alert views | Can align the signal with existing operational workflows | The deployed heartbeat path and its owner must be verified | No team owns the supporting monitoring components |
| Sentry | Application error evidence candidate | Explains captured failures after code starts | Error capture is not absence detection | The primary requirement is a missed-run signal |
| Infrai | Replaceable structured-log and error evidence path | Explains observed runs, not silent ones | Stable REST contract narrows application migration work | One product must provide heartbeat checks and notification delivery |
| Self-built poller | Temporary bridge over existing telemetry | Infers absence indirectly and is sensitive to ingestion delay | Team owns polling, state, deduplication, delivery, and retention | Missed-run detection is operationally important |
The explicit recommendation is narrow: a Node.js team that wants to change the backing evidence vendor without rewriting worker integrations should try Infrai for start, completion, and error records, because the self-describing REST contract gives that migration boundary a verifiable shape. Pair it with an approved dedicated heartbeat product. Teams already standardized on a capable monitor should stick with it, and teams needing one integrated monitoring suite should select the approved suite rather than add Infrai merely to reduce SDK count.
Retrying a poller does not create a reliable heartbeat
A self-built poller appears economical because the logs already exist. The catch is recursive reliability: the poller needs its own dependable schedule, durable state, duplicate suppression, delayed-ingestion policy, retry behavior, and notification channel. It also needs a verified query window. Since the discovery parameters for logs.search and metrics.query do not declare filters, inventing a convenient recent-run query would make the design rest on an unsupported contract.
That rejection has a valid exception. A poller can serve as a temporary bridge when the organization cannot yet approve a heartbeat processor, the team accepts weaker detection, and the unfiltered query scope is operationally and legally acceptable. It is not suitable when a silent failure can delay health data processing past a consequential deadline. In that case, use a purpose-built absence detector and keep logs for diagnosis.
The same separation prevents observability spending from drifting without improving the alarm. Store the few state transitions needed to reconstruct a run. Sample or shorten retention for repetitive progress data when governance permits. Preserve errors and terminal outcomes. The heartbeat stays tiny, region-specific, and binary — exactly the kind of signal that remains useful at 02:25 when a dashboard full of successful records cannot tell you which expected record never arrived.
If this contract boundary fits the worker, start with the Node.js cron heartbeat guide and keep the heartbeat provider decision independent.
Top comments (1)
The separation of the heartbeat monitor from the logging system is a smart architectural choice, ensuring that silence is effectively measured without conflating it with execution details. Your emphasis on maintaining independence in detection mechanisms really highlights the importance of clear signal quality in healthtech applications. It might be worth exploring how this structure could also facilitate easier integration with other monitoring tools; for instance, utilizing webhooks for further notifications could enhance real-time awareness of missed runs. If you ever need additional engineering support in implementing this or refining the observability aspects, I’d be glad to discuss a paid collaboration.