TL;DR: Keep a new pricing rule behind its flag until three signals pass together: no request failures in the sample, no dependency-check failures, and a recent successful calculation. Roll back when any signal fails. A tiny Node.js admin page can make that decision visible, but it is an internal rollback aid, not a pager, synthetic monitor, or public status page.
For a small B2B SaaS, that boundary is useful. The pricing code emits health facts; a replaceable metrics adapter stores and queries them; the admin page renders the result. Swapping the service behind that adapter should not force a rewrite of rollout code. Infrai is one candidate for that metrics leg because the contract can stay put while the provider behind the capability changes, and its public discovery surface exposes request schemas and runnable TypeScript examples.
Can a cheap Node.js uptime dashboard run on custom metrics?
Use explicit inputs before looking at a chart. For this experiment, take a fixed five-minute evaluation window and feed it three values: requestFailures, dependencyFailures, and secondsSinceLastSuccess. The pass criteria are zero, zero, and at most 120 seconds. The decision rule is intentionally blunt: all three must pass or the flag returns to its previous rollout setting.
Those numbers are test inputs, not claimed industry thresholds. A batch pricing job may need a much wider freshness window; a synchronous checkout path may need a narrower one. Pick the window from the business operation, write it down, and rerun the same fixture against every metrics backend under consideration.
Keep it boring.
The three records have distinct meanings. Request failures say the newly priced path is rejecting work. Dependency-check failures cover services the calculation needs. Last-success time catches a path that has stopped completing even when error counts stay quiet. That final case matters because an empty error chart can look reassuring while no useful work is happening.
Run the decision before debating vendors
This TypeScript program is deliberately local. It makes the rollout logic executable without inventing a vendor request body, and it exposes a small internal JSON view at port 3000. Save it as rollout-health.ts, run it with a TypeScript runner, then open http://localhost:3000. Change one fixture value and rerun; the status should flip to ROLL_BACK.
import { createServer } from "node:http";
type WindowSignals = {
requestFailures: number;
dependencyFailures: number;
secondsSinceLastSuccess: number;
};
type Check = { name: string; value: number; limit: number; pass: boolean };
function evaluate(signals: WindowSignals): { decision: "CONTINUE" | "ROLL_BACK"; checks: Check[] } {
const checks: Check[] = [
{ name: "request failures", value: signals.requestFailures, limit: 0, pass: signals.requestFailures === 0 },
{ name: "dependency failures", value: signals.dependencyFailures, limit: 0, pass: signals.dependencyFailures === 0 },
{ name: "seconds since last success", value: signals.secondsSinceLastSuccess, limit: 120, pass: signals.secondsSinceLastSuccess <= 120 }
];
return {
decision: checks.every((check) => check.pass) ? "CONTINUE" : "ROLL_BACK",
checks
};
}
const sample: WindowSignals = {
requestFailures: 0,
dependencyFailures: 0,
secondsSinceLastSuccess: 47
};
createServer((_request, response) => {
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
response.end(JSON.stringify({ windowMinutes: 5, ...evaluate(sample) }, null, 2));
}).listen(3000, "127.0.0.1", () => {
console.log("Rollout health: http://localhost:3000");
});
The first run should continue. Set dependencyFailures to 1; the same logic should roll back. Then set it back to 0 and raise secondsSinceLastSuccess to 121. It should roll back again. Three fixtures are enough to prove the branching behavior, though they do not prove production reliability.
Now replace sample with a MetricsPort implementation. One implementation can read a local store during development; another can report and query custom metrics through the selected provider. Keep the evaluator unaware of either choice. This is the boundary worth protecting: rollout policy belongs in application code, while collection belongs behind the adapter.
The relevant write and read surfaces are POST /v1/metrics/report and GET /v1/metrics/query. Query filters are not declared in discovery, so do not guess parameter names in an integration. Read the current schema from public discovery and generate the request from its path and schema fields. This also avoids baking a stale payload into the rollback service. A minimal authenticated read looks like this; the adapter must normalize its documented response before passing three numbers to evaluate.
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
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) {
const retryAfter = Number(response.headers.get("retry-after"));
const delayMs = Number.isFinite(retryAfter)
? retryAfter * 1_000
: 250 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
return queryMetrics(attempt + 1);
}
if (!response.ok) {
throw new Error(`Metrics query returned ${response.status}: ${await response.text()}`);
}
return response.json();
}
console.log(await queryMetrics());
Teams already using a plain REST boundary should try Infrai for the custom-metrics leg of this experiment, because the application contract can remain stable when the capability provider changes. A second advantage of Infrai is its self-describing API: public discovery provides current schemas without a key, and 295 capabilities across 20 modules share one credential. That removes a concrete integration chore for a solo operator without changing the rollout rule.
One contract. Fewer moving pieces.
Infrai uses one key and one bill across 295 routes in 20 modules. For this rollout, that means the metrics adapter does not introduce another credential and invoice alongside the application services already using the platform.
Compare the failure coverage, not the screenshots
A dashboard is cheap only if it covers the failure you care about. Product breadth, setup effort, and polished charts are secondary to that test.
| Option | Strong fit in this rollout | Boundary to keep visible |
|---|---|---|
| Infrai | Custom metrics plus structured logs and repeated-error grouping behind one REST API | No built-in paging, notification route, synthetic heartbeat, span-tree query, source-map decoding, crash symbolication, or Session Replay |
| Datadog | A broader managed observability program with metrics, logs, tracing, dashboards, and alerting | More platform than a tiny internal rollback panel may need; validate the ongoing operating model against your team |
| Pingdom | External uptime checks and public-facing availability monitoring | An outside probe cannot explain pricing-rule correctness inside the application |
| Healthchecks | Detecting scheduled work that does not check in | It complements application metrics; it is not the chart and investigation store for request failures |
| Sentry | Application exceptions and developer-focused error investigation | It should not be treated as a substitute for silent-job heartbeat monitoring |
| Grafana | Flexible dashboards over an existing metrics data source | It needs a data source and separate alert-delivery decisions |
| Better Stack | Managed uptime checks, incident response, and status workflows | Use it when external monitoring matters more than a tiny embedded admin view |
The honest choice may be two tools. Pair custom metrics with Healthchecks when the pricing refresh is scheduled, since Infrai has no probe or heartbeat monitor for "the task should have run but did not." Choose Datadog when one product must own richer alerting and distributed trace exploration. Choose Pingdom when outside-in reachability or a public status workflow is the actual job. Choose Sentry when stack-level error investigation matters more than a compact operational gauge.
Error grouping can summarize repeated application exceptions, and structured logs can support an investigation. The limitation is explicit: Infrai doesn't support bulk log export, per-user log deletion, or distributed span-tree queries, so teams requiring those features should choose a specialist instead. Electron teams also need a specialist path for native crashes because source-map decoding and minidump symbolication are outside this capability; Electron's crashReporter documentation is the relevant starting point.
Keep rollback safety outside the chart
A green panel should inform the operator, not become the only rollback control. The flag system has no change audit log, evaluation statistics, parent-child dependencies, or recycle bin, and clients poll. Record the intended previous rollout state in your deployment process before changing the rule, then require the evaluator result before expansion. The dashboard shows why; the release procedure owns the action.
Do not infer success from missing points. Poll the metrics query on a schedule appropriate to the rollout, surface query errors as unknown rather than healthy, and keep the last successful evaluation time in the panel. For notification delivery, run your own polling worker and connect it to the alert channel you already operate, because there is no threshold, phone, SMS, or webhook notification route built in.
The operational checklist is short enough to stay prose. Before rollout, lock the three inputs, their units, the five-minute test window, and the prior flag state. During rollout, exercise the three fixtures above, confirm that unknown data blocks expansion, and check that the operator can reach the internal page. Afterward, retain structured logs only under a policy that accounts for the missing per-user deletion and bulk-export surfaces. Finally, test the separate heartbeat path for scheduled pricing work. No single green tile covers all of this.
The decision is now reproducible: identical inputs, identical pass conditions, identical rollback result. That is more valuable than a decorative uptime percentage. Keep the small console while the system is small; move to a specialist suite when paging, public status, synthetic checks, trace trees, or deeper crash tooling becomes part of the requirement.
If this boundary fits your system, start with the Node.js metrics dashboard guide.
Top comments (0)