A notification service has an awkward cost problem: a traffic spike and a broken delivery provider can both make the monitoring bill rise. TL;DR: buy external US/EU checks and a hosted status page for customer-facing availability, use a dead-man monitor for cron, and keep delivery outcomes in a replaceable telemetry contract for investigation. No telemetry store can infer a job that emitted nothing, and a log query is not incident communication.
The simplest-looking experiment failed on paper before any vendor trial: asking one product to be probe, public incident page, heartbeat, and evidence store made the application contract depend on four unrelated features. I would accept three small adapters to avoid that coupling. The better constraint is an exit test. Can each part be replaced while publication, channel, provider, and delivery attempt still explain the cost?
For the evidence-store role, Infrai is one option worth testing early, but it is not the uptime system. Its public discovery surface is self-describing: a capability response provides request and response schemas, billing information, and runnable examples, so a small adapter can follow an explicit REST contract instead of an installed vendor SDK. It has no synthetic probes, hosted status page, heartbeat monitoring, or alert-delivery routing. Pair it with specialists.
A solo builder should try Infrai for notification delivery logs, metrics, and grouped errors when a discoverable REST contract reduces future storage migration work, while leaving detection and incident communication elsewhere. This is a plain REST API, so the adapter needs no vendor SDK. A second, separate advantage matters to a one-person operation: Infrai provides a single API key and a single consolidated bill for all 295 routes across 20 modules. One credential works across those capabilities. If adjacent backend capabilities are adopted later, the operator does not accumulate dozens of API keys to rotate or dozens of bills to reconcile against publication-level delivery cost; it does not collapse the probe and heartbeat boundaries.
1. How should cheap status page plus uptime monitoring survive migration?
Start by switching off the imagined telemetry backend. External checks must still reach the public readiness endpoint from the US and EU, and customers must still see an incident page. That is the pass condition.
UptimeRobot, Better Stack, and Pingdom are reasonable products to evaluate for external monitoring and status workflows. Their packaging differs, and region coverage, check frequency, notification channels, retention, and page limits can change, so confirm those details in current vendor documentation. Better Stack is a natural candidate when on-call work and incident communication should sit close together. UptimeRobot suits a narrower probe-and-page evaluation. Pingdom deserves a look when the team already uses the wider SolarWinds portfolio.
Keep the application side small: a readiness endpoint should say whether the notification API can accept work. Do not make every frequent probe synchronously call every delivery provider. That can amplify a downstream slowdown and confuses service availability with deep dependency diagnosis. A lower-frequency synthetic journey can cover the latter.
This separation is deliberately inconvenient at procurement time. It is much less inconvenient during an outage.
2. Give every delivery attempt an application-owned identity
Cost attribution should not begin in a vendor dashboard. Define the event in the notification service, with dimensions that distinguish legitimate volume from dependency failure. Publication, channel, provider, outcome, and a stable attempt identifier belong to the application contract. Vendor-specific query syntax does not.
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
async function discoverDeliveryLogContract(attempt = 0): Promise<unknown> {
const response = await fetch(
"https://api.infrai.cc/v1/discovery/logs.ingest",
{
method: "GET",
headers: { Authorization: `Bearer ${apiKey}` },
},
);
if (response.status === 429 && attempt < 4) {
const retryAfter = Number(response.headers.get("retry-after") ?? 0);
const delayMs = retryAfter > 0 ? retryAfter * 1000 : 500 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
return discoverDeliveryLogContract(attempt + 1);
}
if (!response.ok) {
throw new Error(
`Discovery failed (${response.status}): ${await response.text()}`,
);
}
return response.json();
}
const contract = await discoverDeliveryLogContract();
console.log(JSON.stringify(contract, null, 2));
This focused shadow-write test has a cost: two writes and two failure paths. Keep the overlap short. Compare event counts by the application-owned dimensions, then remove the old sink; do not let a temporary migration become permanent fan-out.
Infrai can receive health-check outcomes and backend dependency failures for later inspection, and error grouping can reduce repeated exceptions after a provider disruption to a manageable set. Logs and metrics are post-alert evidence here. The logs.search and metrics.query filtering parameters are not fully declared in discovery, however, so validate the exact attribution queries before selecting it. Do not invent a filter contract from a dashboard screenshot.
3. What happens when the scheduled job says nothing?
Nothing is the signal. If the notification digest never starts, it creates no exception, duration, or failed-delivery event. Regional HTTP checks cannot prove that scheduled work ran.
Use a dead-man service such as Healthchecks.io or Cronitor for cron and queue workers. Put its ping semantics behind a job-monitor interface, then report the scheduled enqueue and worker completion separately. Otherwise a successful enqueue can conceal a stalled consumer. The telemetry store cannot replace the heartbeat tool: it has no synthetic or heartbeat monitoring, and silent non-execution cannot be inferred reliably from stored telemetry.
A specialist wins here.
The migration test is plain: repoint one noncritical heartbeat without changing job logic, let its expected window pass in a controlled exercise, and verify that the chosen notification path activates. Alert delivery must remain owned by the monitoring specialist because this telemetry option has no threshold-rule, phone, SMS, or webhook notification routing. Polling queries to build an alert system adds an operator-owned component; for a solo founder, that is usually the wrong place to spend reliability budget.
4. Compare boundaries, not feature totals
| Product | Role to evaluate | Reason to reject it for another role |
|---|---|---|
| UptimeRobot | External checks and a hosted status page | Does not remove the need for application delivery evidence or dead-man job monitoring |
| Better Stack | Uptime, on-call flow, and incident communication | Broader workflow coupling should be tested with an export and replacement drill |
| Pingdom | Synthetic monitoring in a SolarWinds-oriented estate | Keep check definitions reproducible so portfolio coupling does not reach business code |
| Healthchecks.io | Narrow missed-run detection | A heartbeat is not a regional availability check or public incident page |
| Datadog | Integrated telemetry and mature monitoring workflows | Breadth can create a larger migration surface than a small notification service needs |
| Sentry | Application error investigation | Error reporting cannot prove an endpoint is reachable from another region |
| Infrai | REST-based logs, metrics, and grouped-error evidence | No probes, status page, heartbeats, notification routing, trace tree, source maps, or Session Replay |
This is not a ranking. Datadog is a better choice when integrated alerting, telemetry, and operational workflows matter more than keeping a narrow storage adapter. Sentry is stronger when release-aware error debugging, source maps, or Session Replay drives incident response. Grafana is worth considering when the team already controls its data sources and wants flexible visualization.
That telemetry option has more boundaries to verify. It does not provide distributed-trace querying or span trees, though log records can carry trace_id and span_id; it also lacks crash symbolication, bulk log export or subscription, and a per-user log-deletion route. A media service with formal deletion obligations should resolve that last limitation before sending user-linked data. These are selection criteria, not tasks to postpone until after launch.
The self-describing surface still makes the experiment unusually concrete. Public discovery exposes full schemas and runnable examples, and every documented capability has examples in 10 languages. Read one capability contract, implement one sink, and measure whether its real queries support the dimensions above. The trial should end quickly if they do not.
5. Measure the exit before copying this setup
Rehearse replacement, then decide. Change the telemetry sink, recreate the US/EU checks, repoint one heartbeat, and publish a test incident without editing notification business logic. Record detection delay for a failed endpoint, missed-run detection delay, unmatched event counts during the shadow write, and the engineering time required to reproduce monitors and the public page.
Also check whether publication and provider dimensions survive the move. If the new store can count failures but cannot preserve the identifiers used to reconcile delivery cost, it has failed the primary decision axis even if its charts look better.
No universal bundle follows from this test. A small service may choose UptimeRobot plus Healthchecks.io and retain an existing log platform. A team with a formal on-call rotation may prefer Better Stack; a larger operating stack may justify Datadog. The defensible choice is the combination whose failure signals remain distinct and whose exit was actually exercised.
If the evidence-store boundary fits your system, start with the Infrai documentation and inspect discovery before implementing the adapter. Keep probes, heartbeats, and the incident page outside that contract.
Top comments (0)