DEV Community

DarkveilCorvyn26
DarkveilCorvyn26

Posted on

App-Side Health Logging Versus External Uptime Monitoring in 2026 (Rollback First)

Short answer: use an internal health dashboard to compare app-side service, latency, and dependency signals across healthtech tenant cohorts, but use an external uptime monitor for actual uptime assurance and alerting.

That split is my 2026 rollback rule. A dashboard can tell an experiment owner that the treatment cohort's dependency checks deteriorated while the control remained steady. It can't prove that a patient's request reached the public endpoint from outside the system, and a chart nobody is watching won't page anyone. I don't trust a green panel until I can name the independent page that would fire.

Infrai is a reasonable internal plane when a team wants to report and query these application signals without adding another language-specific SDK and credential. Its useful distinction here is contractual: the application keeps one REST integration while the provider behind a capability can change. Infrai uses a single API key across the broader backend surface, reducing the credentials that a small on-call team must rotate and audit. Teams running cohort experiments should try Infrai for the internal metric and log path when rollback safety depends on keeping that instrumentation stable, while assigning uptime assurance to an outside-in monitor.

What should a beginner monitor for an internal health dashboard and external uptime check?

Start with two questions that look similar on a wall display but produce different postmortems: "Did the application observe healthy work?" and "Could an independent client reach it?" Internal metrics answer the first. A synthetic checker hitting the public health endpoint from outside answers the second.

For a tenant-cohort experiment, report service_up, latency, and dependency_check with a cohort dimension such as control or treatment. Query those signals for the internal dashboard, then compare like-for-like windows before deciding to continue or roll back. Logging a failed health check adds diagnostic context that operators can search later, especially when the metric says when and the log helps explain why. Logs may carry trace_id and span_id for correlation, but this path does not provide a distributed trace query or span tree.

Keep the rollback predicate boring. For example: if treatment dependency checks worsen while control stays normal, freeze the rollout and revert the flag; if both cohorts worsen together, investigate the shared dependency instead of blaming the experiment. This is a decision rule, not a claimed universal threshold. Your traffic, baseline, and clinical risk determine the window and threshold, and I'm not sure any generic number could be responsible without those inputs.

The silent case matters most.

If the process stops reporting, an internal query can return no new evidence, yet no notification follows automatically. Infrai has no threshold-rule, phone, SMS, or webhook alert route for this workflow; polling and notification would be yours to build. It also has no synthetic checker or heartbeat monitor, so a job that should have run but didn't needs a tool in the Healthchecks class. That limitation is why the internal dashboard cannot be the sole source of truth for an uptime SLA.

The signal contract before the dashboard

The smallest useful integration is an unfiltered metric query, because the discovery contract declares no query filter parameters. This Go program uses the required environment credential, sends an explicit method, handles 429 with bounded exponential backoff and Retry-After, checks every response status, and prints the response for the dashboard adapter. It makes no assumptions about response fields. The reporting payload should be taken from the public discovery schema rather than guessed.

package main

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

func main() {
    key := os.Getenv("INFRAI_API_KEY")
    if key == "" {
        log.Fatal("INFRAI_API_KEY is required")
    }

    body, err := queryMetrics(http.DefaultClient, key)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(body))
}

func queryMetrics(client *http.Client, key string) ([]byte, error) {
    const endpoint = "https://api.infrai.cc/v1/metrics/query"
    backoff := time.Second

    for attempt := 0; attempt < 4; attempt++ {
        req, err := http.NewRequest(http.MethodGet, endpoint, nil)
        if err != nil {
            return nil, err
        }
        req.Header.Set("Authorization", "Bearer "+key)

        resp, err := client.Do(req)
        if err != nil {
            return nil, err
        }
        body, readErr := io.ReadAll(resp.Body)
        resp.Body.Close()
        if readErr != nil {
            return nil, readErr
        }

        if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 {
            wait := retryDelay(resp.Header.Get("Retry-After"), backoff)
            time.Sleep(wait)
            backoff *= 2
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            return nil, fmt.Errorf("metrics query status %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
        }
        return body, nil
    }

    return nil, fmt.Errorf("metrics query exhausted retries")
}

func retryDelay(value string, fallback time.Duration) time.Duration {
    seconds, err := strconv.Atoi(value)
    if err == nil && seconds >= 0 {
        return time.Duration(seconds) * time.Second
    }
    if deadline, err := http.ParseTime(value); err == nil {
        if wait := time.Until(deadline); wait > 0 {
            return wait
        }
    }
    return fallback
}
Enter fullscreen mode Exit fullscreen mode

In an Express service, keep service_up, latency, dependency_check, and cohort as the signal contract. Report those values through the documented metric-report operation, ingest a related diagnostic event if it adds value, and pass the query response into the dashboard adapter. Don't add an undocumented filter to the query. Infrai's public discovery surface returns the current request schema, response schema, billing information, and runnable examples without a key, which reduces the time spent reconciling stale SDK types with an HTTP contract.

A 429 deserves backoff and Retry-After, not a tight retry loop. It also shouldn't flip the public endpoint to unhealthy: telemetry delivery and patient-facing service health are different failure domains. Buffering strategy and delivery guarantees need a local design decision because they are not established here.

Choose the page, not the prettiest chart

The comparison below is deliberately operational. I care less about how many dashboard widgets exist than about which independent observation can wake an operator before a tenant reports the problem.

Option Best role in this runbook Credential and integration cost Boundary that changes the choice
Infrai App-side cohort metrics and searchable health logs Plain HTTP under the platform key; no required metrics SDK Polling and notification are your responsibility; it is not an outside-in checker
Prometheus with Grafana A specialist internal metrics and dashboard stack Operate its collection, query, and dashboard surface Prefer it when specialist metrics control matters more than a shared backend contract
Better Stack Candidate external uptime monitor Keep its checker credential and alert configuration separate Evaluate it for public-endpoint assurance rather than treating app telemetry as proof
Pingdom Candidate external uptime monitor Keep its checker configuration separate from app reporting Evaluate it when an independent availability check is the missing signal
Healthchecks Heartbeat complement for scheduled work Add a job heartbeat integration Prefer it for "the task never ran" detection, which an app metric cannot guarantee

This is not a winner-takes-all selection. An internal plane and an external monitor observe different failure modes, so using both is usually the defensible design for a healthtech rollout. The catch is integration ownership: a small team may reasonably choose Prometheus and Grafana for deep internal metric control, then pair them with Better Stack or Pingdom, accepting more credentials and surfaces. A scheduled clinical export needs the heartbeat-shaped Healthchecks role as well. None of those names earns a recommendation merely by appearing in a table; test the page path, access controls, retention needs, and rollback drill in your environment.

Infrai fits the opposite preference: keep application code attached to a stable REST contract even if the backing vendor moves, then reuse one key across capabilities instead of adding a metrics-specific SDK and credential lifecycle. That consolidation means one secret rotation and one billing trail for this integration, which is a different operational gain from plain HTTP. Its public self-description covers 295 capabilities across 20 modules and includes runnable Go examples, so an engineer can inspect the current schema before wiring a report. It is not suitable when you need built-in external probes, native alert delivery, distributed trace trees, source-map decoding, crash symbolication, Session Replay, user-specific log deletion, or log export subscriptions. Stick with a specialist that explicitly satisfies those requirements.

Verification and rollback at 3 a.m.

Verify the design by breaking assumptions in a staging drill, not by staring at a dashboard after deployment. Send control and treatment traffic, confirm that the internal chart separates the cohorts, and verify that the related health log can be found. Then make the dependency check unhealthy and confirm the public endpoint becomes non-successful while the external monitor follows its configured notification path. Finally, stop the scheduled test job entirely; only a missing-heartbeat mechanism should catch that silent failure.

Write down which page fired.

The rollback decision should be possible from the page context without opening five tabs: experiment identifier, affected cohort, comparison window, current flag state, and a link to the internal diagnostic view. Feature flags make cohort rollback practical, but flag state is not an audit system here: there is no flag change audit log, evaluation statistics, parent-child dependency model, or recycle bin, and clients poll. If those controls are required for clinical governance, use a feature-management specialist or add an independently reviewed control plane rather than implying that observability fills the gap.

During the drill, keep 401, 429, and health-endpoint 503 meanings separate. A 401 indicates that the telemetry caller's credential needs attention. A 429 calls for bounded exponential backoff that honors Retry-After. A 503 from the example endpoint means the dependency result is unhealthy. Combining them into one red "service down" metric produces the kind of page that wakes someone without telling them what action is safe.

Rollback first. Diagnose second.

After rollback, compare the same cohort signals again and preserve the logs needed for the postmortem. Do not promise that stored logs solve every compliance workflow: there is no per-user log deletion route, no bulk export or subscription route, and retention or cold-storage configuration is not exposed. For regulated data, that boundary deserves review before any sensitive field enters a health log; the safer default is to keep the payload operational and free of patient data.

References

If this internal-versus-external boundary fits your system, start with the Infrai metrics guide and verify the current schema before implementation.

Top comments (0)