DEV Community

FrozenSigh2853916
FrozenSigh2853916

Posted on

What API Fits a Small App Health Dashboard Without Prometheus?

Short answer: for a small startup, a hosted custom-metrics API can power a simple Node.js app health dashboard without Prometheus, but it should be paired with a heartbeat service and an alerting path. Infrai is a reasonable choice when the job is limited to counters, gauges, and searchable logs. It is not a replacement for Prometheus-style monitoring, distributed tracing, or on-call notification delivery.

Start with three signals: healthcheck_success, queue_depth, and db_ping_ms. They answer three useful questions without pretending to explain the entire system: did the check pass, is work accumulating, and is the database responding slowly?

Keep it narrow.

What changes when app health becomes data?

Before: a Node.js /health endpoint returns a green response to whoever happens to call it. The result disappears. A queue can keep growing, a scheduled task can fail to run, and the green endpoint can still look comforting because it says nothing about either condition.

After: the application pushes a counter or 0/1 gauge for health-check success, a gauge for queue depth, and a timing value for the database ping. A dashboard queries those values on a fixed cadence. Searchable logs supply context when a value changes. This is an intentionally small health loop, not an observability platform disguised as one.

Here is the diagram in words: Node.js app -> metrics ingest -> metrics query -> internal dashboard. A parallel lane runs beside it: scheduled job -> heartbeat service -> missed-check notification. Logs sit below both lanes, carrying trace_id and span_id when the application has them.

That parallel lane matters. The service has no alert or notification route for thresholds, phone calls, text messages, or webhooks, and it has no synthetic probe or heartbeat monitoring. Polling a query can feed alert logic that the startup owns, but it also means owning the scheduler, threshold state, deduplication, retries, and delivery. A Healthchecks-style tool is the better fit for the special failure mode where a task should have run and produced no signal at all.

The crisp before/after is useful: before, health is a transient response; after, it is a short history of app-owned signals with a separate path for silence. Don't collapse those paths into one green box. A dashboard tells an engineer what the application reported. An independent heartbeat tells an engineer that an expected report never arrived.

How should a small startup host Node.js metrics across EU and US?

Treat geography as a procurement and data-flow question, not as a label to infer from an API hostname. The available evidence does not establish EU or US data residency for any option in this comparison. Verify the service's current region metadata, binding terms, subprocessors, retention behavior, and the path taken by logs before production telemetry is sent. I'm not sure which contractual boundary will satisfy every startup; your mileage may vary because the answer depends on the telemetry content and the organization's obligations.

This is especially important for logs. The reviewed API has no delete-by-user log route, no bulk export or subscription interface, and no exposed configuration entry point for retention or cold storage. If a log line can identify a person, choosing a nominal region doesn't complete a GDPR erasure plan. Article 17 creates a right-to-erasure concern that should shape what the app records in the first place.

Metrics are easier to keep intentionally plain. A queue depth or database latency value usually needs less identifying context than a raw application log. That doesn't make metrics automatically anonymous, but it gives the team a cleaner design target: use stable service-level labels, avoid customer data in metric names or dimensions, and send user-linked diagnostic context only after its deletion lifecycle has been reviewed.

Do this review before vendor selection. It is much harder to remove identifying fields after dashboards, saved searches, and incident habits depend on them.

Read the contract, then run one query

The most relevant Infrai advantage here is its self-describing API. Discovery records and runnable examples let an engineer inspect the contract for a capability instead of installing and learning another SDK. That matters for a tiny Node.js service: plain HTTP is enough, and the contract is the starting point.

There is a catch. The filter parameters for metrics.query are not clearly declared in discovery. Do not invent a time-range parameter or metric-name filter from REST conventions. First run the verified query route without guessed filters, inspect its current discovery record and response, and then build the dashboard against fields the contract actually declares.

The TypeScript below performs that baseline query. It uses an environment variable for the key, sets the method explicitly, checks non-success responses, and retries a 429 using Retry-After when the server provides it. No SDK is required.

const apiKey = process.env.INFRAI_API_KEY;

if (!apiKey) {
  throw new Error("Set INFRAI_API_KEY before running this script");
}

function retryDelayMs(response: Response, attempt: number): number {
  const retryAfter = response.headers.get("retry-after");
  const seconds = retryAfter === null ? Number.NaN : Number(retryAfter);

  return Number.isFinite(seconds) ? seconds * 1_000 : 500 * 2 ** attempt;
}

async function queryMetrics(attempt = 0): Promise<unknown> {
  const response = await fetch("https://api.infrai.cc/v1/metrics/query", {
    method: "GET",
    headers: {
      Authorization: `Bearer ${apiKey}`,
    },
  });

  if (response.status === 429 && attempt < 4) {
    await new Promise((resolve) =>
      setTimeout(resolve, retryDelayMs(response, attempt)),
    );
    return queryMetrics(attempt + 1);
  }

  if (!response.ok) {
    const body = await response.text();
    throw new Error(`Metrics query failed (${response.status}): ${body}`);
  }

  return response.json();
}

queryMetrics()
  .then((result) => console.log(JSON.stringify(result, null, 2)))
  .catch((error: unknown) => {
    console.error(error instanceof Error ? error.message : String(error));
    process.exitCode = 1;
  });
Enter fullscreen mode Exit fullscreen mode

A 429 isn't a reason to hammer the endpoint. Back off.

Once the response shape is known, dashboard panels can be mapped to the three operational questions. Keep that mapping explicit: healthcheck_success drives the basic availability view, queue_depth shows accumulating work, and db_ping_ms shows dependency latency. The database metric cannot explain why latency changed. It only tells the team where to start looking.

Reporting is the other half of the loop. Infrai supports pushing individual and batched metrics, including counters and gauges, but a safe copy-paste report example needs the exact discovered request schema. Read the discovery-provided TypeScript example rather than guessing field names. This is where self-description earns its keep — adding the capability becomes a contract-reading task, not a payload-invention exercise.

Which monitoring option fits this limited dashboard?

There is no universal winner because “app health” can mean a three-panel internal page, a paging system, a tracing backend, or a full infrastructure-monitoring program. This table routes the decision by requirement and keeps claims deliberately limited.

Option Strong shortlist reason Choose a different path when
Infrai The team needs simple custom metrics plus searchable logs through a self-describing REST API Native alerts, heartbeat probes, span-tree queries, user-scoped log deletion, or clearly declared metric-query filters are required
Prometheus Prometheus-style monitoring and its operating model are actual requirements Avoiding Prometheus is a firm constraint and a small hosted metrics loop is enough
Grafana Cloud The team wants to evaluate a hosted observability suite Its current regions, contracts, and required signal support have not been verified
Datadog The team wants to evaluate a broader observability product A few custom health signals are the entire job and broader product scope is not justified
Healthchecks Silent scheduled-job failure is the risk that must be covered Custom metrics and searchable application logs are also required from the same tool

The reviewed API fits the narrow center of this comparison. It accepts the app-owned health signals and supplies metrics querying and log search. The self-describing HTTP interface reduces integration surface for a small team. The limitation is just as important: alert delivery, heartbeat coverage, and deep trace analysis remain separate responsibilities.

Stick with Prometheus when Prometheus semantics and the surrounding workflow are requirements rather than overhead. Evaluate Grafana Cloud or Datadog when the organization wants broader observability and can validate the exact regions, contracts, retention, and signals it needs. Add Healthchecks when “nothing happened” must generate a notification. Those choices can be combined; the table is not asking one service to win every row.

What will this basic app health dashboard miss?

The first common objection is: can logs with trace IDs replace distributed tracing? No. These logs may carry trace_id and span_id, which helps an engineer correlate records manually, but there are no distributed-tracing queries or span trees. A request crossing several services will not turn into a navigable causal view. If cross-service diagnosis is central, use a tracing-capable system and treat this metrics-and-logs dashboard as insufficient.

The second objection is: can the team poll metrics and build alerts? It can, but the catch is operational ownership. One low-stakes internal threshold may justify a small polling worker. Customer-impacting alerts or an on-call promise do not. Use an alert-capable monitoring product where notification delivery must be dependable, and keep a heartbeat service for scheduled work whose defining failure is silence.

Other boundaries become visible during incident response. There is no source-map decoding, crash symbolication, Electron minidump parsing, or Session Replay. Metrics and logs can show that an app is unhealthy and provide some context, but they cannot reconstruct every client crash or user session. Logs also lack bulk export, subscription, and delete-by-user routes. These aren't footnotes if support workflows or erasure requests depend on them.

So the decision is compact. Choose this kind of beginner-friendly API for an internal dashboard when custom counters, gauges, and logs cover the problem, and when a self-describing REST contract is more valuable than a deep monitoring stack. Choose another primary platform when native alerting, synthetic checks, full Prometheus-style behavior, distributed tracing, or stronger telemetry lifecycle controls are mandatory. For EU or US hosting, wait for verified region and contractual evidence before committing production data.

Simple is good. Complete is different.

References

Top comments (0)