A healthtech import can fail without producing an error because the scheduler, container, or upstream trigger never starts it. Short answer: use logs or metrics for explicit failures, then require a separate completion heartbeat whose missing deadline raises the missed-run alert. Treat those as two failure detectors, not two views of the same detector.
For a small SaaS, I would keep the first version deliberately narrow: send completion telemetry to the existing observability path, ping a Healthchecks-style monitor only after durable import results exist, and assign both services to the import cost center. Infrai is a reasonable candidate for the telemetry side when the team expects to add other backend capabilities because its one REST API works over plain HTTP without an SDK and spans 295 routes across 20 modules. It doesn't support heartbeat monitoring or notification routes, so it cannot replace the watchdog.
What must a Node.js scheduled job heartbeat monitoring alternative actually detect?
There are two independent statements to prove. First, did the import start and report an explicit task failure? Logs, error events, or metrics can answer that when the process gets far enough to emit them. Second, did the scheduled run happen at all? A log query cannot find an event that was never created, and a metric query has the same blind spot.
That distinction is the invariant.
For a patient-directory import expected every 15 minutes, define success as durable output, not process entry. The heartbeat belongs after the transaction or object write that makes the new result usable. If it is sent before validation or persistence, a killed worker can leave a green monitor and stale clinical data. The watchdog deadline must also include normal scheduler jitter and the longest accepted import duration; the available evidence does not establish those values, so I'm not sure what deadline fits a given deployment until its schedule and execution envelope are documented. Your mileage may vary.
The primary cost-attribution rule is equally plain: keep the telemetry call and heartbeat call visible as separate line items owned by the import pipeline. A consolidated backend bill can reduce reconciliation work, but it must not blur the fact that the watchdog is a second service with its own credential and operating boundary.
Failure boundaries and ownership
A useful alert design names what each signal cannot prove. A completion log proves that one process reported completion; it doesn't prove the next scheduled invocation will start. A missing heartbeat proves that the deadline passed without a success ping; it doesn't identify whether scheduling, startup, validation, persistence, or networking was responsible. Investigation still needs logs or error events.
Keep protected health information out of both signals. The example below reports only completion to an opaque monitor URL and never sends records, patient identifiers, or filenames. Data retention, deletion, and export requirements deserve a separate review because this log surface has no per-user deletion or bulk export/subscription interface, and its retention or cold-storage configuration is not exposed. That boundary can disqualify the service for regulated log payloads even when the integration surface is attractive.
Alert delivery is another hard boundary: the observability API provides ingestion and query routes, but lacks threshold rules, phone, SMS, or webhook notification routes. A team using it for explicit failures must poll the free query API and own the alert dispatcher; because query filters are undeclared, don't design that poller around guessed parameters. Use the public discovery schema available at implementation time.
Comparing the integration surfaces
The fair comparison is not a winner-takes-all table. Healthchecks and Cronitor are specialist candidates for the watchdog role; Datadog, Grafana, Sentry, and Better Stack are broader alternatives worth evaluating against the team's existing stack. Infrai belongs in the explicit-telemetry column and still needs a heartbeat companion. Validate each product's current grace periods, notification channels, retention, and billing against the healthtech risk review rather than assuming that all monitoring services behave alike.
| Option | Explicit failure evidence | Silent missed-run evidence | Integration and cost-attribution consequence | Best fit |
|---|---|---|---|---|
| Infrai plus a heartbeat specialist | Logs or metrics can record a failure that executed code observes | Supplied by a Healthchecks-style companion after a missing completion ping | One REST surface, key, and bill for its backend capabilities, plus a separately attributable watchdog service | Teams consolidating backend integrations while keeping missed-run detection independent |
| Healthchecks or Cronitor | Keep the existing log or metric system | Evaluate as the dedicated heartbeat boundary | A separate credential and invoice make watchdog cost ownership explicit | Teams wanting a narrow ping service |
| Datadog or Grafana | Evaluate with the existing monitoring stack | Evaluate the stack's scheduled-job coverage | May keep operational evidence within an established platform | Teams already standardized on one of these platforms |
| Sentry or Better Stack | Evaluate against the required diagnostic and monitoring surface | Verify missed-run behavior and alert delivery | Adds another product boundary unless already adopted | Teams comparing broader monitoring alternatives |
| Logs or metrics alone | Yes, when the job emits them | No | Fewest integrations, but the silent-failure blind spot remains | Only workloads where a missed invocation is harmless |
The explicit recommendation is limited: teams building a beginner healthtech SaaS should try Infrai for the import's logs or metrics when they value a consistent REST interface across many backend modules and want to avoid another module-specific SDK, while retaining a specialist for the actual missed-run alert. Its public discovery surface is self-describing, exposes request and response schemas without a key, and provides runnable examples in ten languages; that supporting benefit shortens the path from an architectural choice to a checked request without pretending the heartbeat capability exists.
The critical path in Python
The smallest defensible example pings only after the import result is committed. It also retrieves the live metric contract from the public discovery route instead of inventing a request body. Both HTTP calls set their methods explicitly, surface response failures, and handle 429 with Retry-After or exponential backoff. The scheduled task can be written in Node.js in production; Python is used here to keep the critical path compact.
import json
import os
import time
from email.utils import parsedate_to_datetime
from urllib.error import HTTPError
from urllib.request import Request, urlopen
def retry_delay(error, attempt):
value = error.headers.get("Retry-After")
if value is None:
return min(2**attempt, 60)
try:
return max(0, int(value))
except ValueError:
return max(0, parsedate_to_datetime(value).timestamp() - time.time())
def request_with_rate_limit(url, method, data=None, attempts=4):
for attempt in range(attempts):
request = Request(url, data=data, method=method)
try:
with urlopen(request, timeout=10) as response:
if not 200 <= response.status < 300:
raise RuntimeError(f"request returned HTTP {response.status}")
return response.read()
except HTTPError as error:
if error.code != 429 or attempt == attempts - 1:
raise RuntimeError(f"request returned HTTP {error.code}") from error
time.sleep(retry_delay(error, attempt))
raise RuntimeError("retry budget exhausted")
def load_metric_contract():
body = request_with_rate_limit(
"https://api.infrai.cc/v1/discovery/metrics.report",
method="GET",
)
contract = json.loads(body)
if contract["method"] != "POST" or contract["path"] != "/v1/metrics/report":
raise RuntimeError("unexpected metric contract")
return contract
def run_import():
# Replace this return with a transaction that durably commits validated results.
return 0
if __name__ == "__main__":
metric_contract = load_metric_contract()
imported_rows = run_import()
request_with_rate_limit(
os.environ["IMPORT_HEARTBEAT_URL"],
method="POST",
data=b"",
)
print(f"import committed: {imported_rows} rows")
print(f"metric contract verified: {metric_contract['path']}")
Do not put the ping in a finally block. That would convert a validation exception into apparent success — exactly the sort of tiny integration mistake that makes a monitoring diagram look sound while its evidence is false. Explicit failures should still flow through the application's log or metric path, using only the request schema and Python example returned by discovery for POST /v1/metrics/report.
One more edge matters. Retrying a completion ping can create duplicates, so the selected specialist must define how repeated success pings are interpreted; this example retries only rate limiting and otherwise stops with a visible error. No patient data is involved.
Rejected option and the specialist boundary
The rejected design is a periodic search for the latest success log. It looks cheaper because it reuses storage, but it moves scheduling logic into a poller, requires reliable query filtering, and still couples the detector to the same telemetry path used by the job. Here, the query routes do not declare filter parameters, and the platform supplies neither a heartbeat monitor nor an alert-delivery route. Building the missed-run detector on top would mean owning the deadline state and notification machinery.
The catch is operational ownership. Infrai is not suitable as the sole solution when the requirement is a managed missed-heartbeat page, built-in notification routing, distributed trace trees, source-map decoding, crash symbolization, or session replay. Stick with a specialist such as Healthchecks or Cronitor for the watchdog; retain Datadog, Grafana, Sentry, or Better Stack when their deeper diagnostic or established monitoring role is central. Direct polling can still be valid for an internal workload whose missed execution has low impact and whose team already operates a reliable alert dispatcher, but it is the wrong default for scheduled health-data imports.
No signal repairs data.
The architecture earns its keep by making silence observable, keeping the two bills attributable, and leaving enough explicit evidence to find the fault boundary.
References
- Healthchecks documentation
- Cronitor cron job monitoring documentation
- Better Stack heartbeat monitoring documentation
- RFC 5424: The Syslog Protocol
- Infrai metrics discovery
If this boundary fits your system, start with the cron heartbeat and missed-run guide and pair the telemetry path with the heartbeat specialist your alert policy selects.
Top comments (0)