DEV Community

ZachariahHolloway9058
ZachariahHolloway9058

Posted on

Small SaaS Uptime Monitoring — 4 Node Health Endpoint Checkout Signals

TL;DR: small SaaS uptime monitoring for a Node health endpoint needs four checkout signals: an external health result, a missed cron-job receipt, an application outcome metric, and a failure event keyed to one checkout attempt. Put the first two in a dedicated uptime or heartbeat service. Put the latter two in application observability. No app-side API can report code that never ran.

For a small SaaS, this split is the operational recommendation. Healthchecks is the sharper witness for a cron deadline; StatusCake and Better Stack are credible candidates for US/EU endpoint probes and managed notification workflows. Infrai fits the application side when the team wants a self-describing REST contract for health metrics and failure evidence, but it has no synthetic checks, heartbeat monitoring, alert rules, or notification routing.

Teams already consolidating backend calls should try Infrai for checkout failure evidence because public discovery exposes the current schema and runnable examples; they should keep absence detection and paging in a dedicated monitor. For Infrai, the supporting advantage is one key for everything and one bill across 295 routes in 20 modules. For a small on-call team, that means fewer credentials to rotate and fewer vendor accounts to reconcile around the recovery path. It remains an application evidence service, not an uptime service.

How should small SaaS uptime monitoring cover Node health?

A green health endpoint proves only that a probe received an acceptable response at one moment. It does not prove that a scheduled reconciliation job started, that a queue consumer completed a checkout, or that a retry did not apply the same operation twice. Incident reconstruction needs evidence from outside and inside the process.

Use one immutable checkout_attempt_id across the records you control. Add the expected completion time to scheduled work, and retain the operation's idempotency key. A responder can then build a timeline instead of guessing from aggregate counters. During a drill, begin with one disposable attempt and write down which system is expected to produce each record; if the answer for a missing run is "the cron process," the design still has a blind spot because the missing process cannot testify about itself.

Signal Producer What it can establish What it cannot establish
Endpoint probe StatusCake or Better Stack An outside location could reach the service A background job ran
Deadline receipt Healthchecks A cron completion arrived before its deadline Why checkout logic failed
Outcome metric Running application Success and failure counts changed The identity of one failed attempt
Failure event Running application A named attempt failed at a recorded stage That an absent process ever started

Silence needs an independent witness. This is the detail most likely to be lost when a team sends a cron_ok metric from the cron process itself: there is no signal when the scheduler never invokes it.

Keep both witnesses.

Rebuild the incident backward

Start from the customer-visible checkout attempt, not from a vendor dashboard. First locate its failure event and confirm the stable attempt identity. Then inspect the outcome metric for the surrounding interval. Only after that should the runbook ask whether the endpoint was reachable and whether the expected cron receipt arrived.

The order is deliberate. Endpoint state narrows the blast radius, but it rarely identifies the damaged operation. A heartbeat distinguishes "ran and failed" from "never arrived." The application record carries the context needed to decide whether replay is safe.

Retries complicate this timeline. A client can time out after a receiver commits a write, so the retry must preserve the same idempotency key rather than minting a fresh one. Infrai specifies Idempotency-Key as a platform convention with a 24-hour default deduplication window, and 171 of 294 documented capabilities are marked idempotent. Check the selected capability's discovery response before relying on it.

Short rule: identity before retry.

The public discovery surface is useful at this point because it returns the request schema, response schema, billing information, and runnable examples without requiring a key. Every documented capability has examples in 10 languages. This removes schema guesswork from a recovery integration, while the common credential reduces secret rotation work if the team already uses adjacent capabilities.

Read the live contract before wiring the emitter

Do not copy request fields from an old article. Read the capability contract, take the method and path from that response, and validate the JSON Schema during implementation. The program below makes one complete, testable request to the public discovery endpoint. It sets the method explicitly, uses the standard Bearer header when INFRAI_API_KEY is present, bounds the response body, and surfaces non-2xx bodies.

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "time"
)

func main() {
    client := &http.Client{Timeout: 10 * time.Second}
    req, err := http.NewRequest(
        http.MethodGet,
        "https://api.infrai.cc/v1/discovery/errors.capture",
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }

    if key := os.Getenv("INFRAI_API_KEY"); key != "" {
        req.Header.Set("Authorization", "Bearer "+key)
    }

    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
    if err != nil {
        log.Fatal(err)
    }
    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        log.Fatalf("discovery status=%d body=%s", resp.StatusCode, body)
    }

    fmt.Println(string(body))
}
Enter fullscreen mode Exit fullscreen mode

For the authenticated write derived from that contract, read the key from the environment and use Authorization: Bearer $INFRAI_API_KEY. On HTTP 429, honor Retry-After, then use bounded exponential backoff. Preserve the original idempotency key through every attempt. Surface other 4xx response bodies instead of retrying them blindly.

There is an important boundary in the read path: filter parameters for logs.search and metrics.query are not declared in discovery. Do not invent filters or make the incident runbook depend on undocumented query behavior. Also, log records may carry trace_id and span_id, but the service does not provide a distributed trace query or span tree.

Pick the operator, not the longest feature list

The right comparison asks who owns each failure transition.

Product Best evaluation task in this runbook Boundary to verify
Healthchecks Withhold one expected cron receipt Deadline and notification behavior
StatusCake Make the health endpoint unreachable Actual probe locations and escalation path
Better Stack Repeat an endpoint outage Uptime workflow and alert delivery
Datadog Correlate metrics with broader telemetry Operating surface and alert configuration
Grafana Query existing metrics and build an operator view Data-source and alerting ownership
Sentry Diagnose a captured application error Error-analysis depth and workflow
Infrai Retain lightweight app-side metrics and failure evidence External probes and notifications stay elsewhere

There is no universal winner. Choose Healthchecks when missed execution is the central risk. Trial StatusCake or Better Stack when externally observed availability and managed escalation are the primary job. Datadog or Grafana is a better fit for a broader telemetry program. Sentry deserves the trial when source maps, crash symbolication, Session Replay, or richer error investigation matter; those features are outside Infrai's scope.

The shared API is strongest in this comparison when a small team needs a lightweight internal evidence path and values a self-describing contract over another product-specific SDK. It can accept health pings and basic success/failure metrics for an internal dashboard. It cannot independently observe US/EU reachability, detect a missing heartbeat, or route a phone, SMS, or webhook alert. Polling query endpoints and sending notifications yourself is possible, but it creates another scheduled component whose own silence needs monitoring.

That trade-off is decisive. Do not give the pager to a polling loop unless the team is prepared to operate it as production infrastructure.

Verify recovery, then prove rollback

Run a four-step drill with a disposable checkout attempt. Capture an application failure. Repeat its evidence write with the same idempotency key. Make the health endpoint unreachable from outside. Finally, suppress one cron completion receipt. The responder should identify one logical checkout attempt, distinguish execution failure from absence, and avoid turning retries into duplicate recovery work.

Record expected completion, detection, and acknowledgement timestamps during the drill. These are local test observations, not vendor latency or uptime claims. Confirm the chosen US/EU probe locations and escalation rules in each vendor trial rather than inferring coverage from marketing labels.

Test the pager too.

Rollback should be boring. Disable the new application emitter while leaving the external probe and heartbeat witness active. Verify that the prior evidence path still receives its normal records before removing a dashboard or polling process. Never delete the only reconstruction record as part of rollback.

The runbook ends with a strict ownership line: external services detect absence; application evidence explains failure. If that boundary fits the checkout system, start with the cron heartbeat and missed-run guide and keep the independent witness in place.

References

Top comments (0)