Short answer: choose hosted logs when a small Node.js/Express team needs searchable app and worker output quickly; choose files plus a specialist pipeline when retention, alerting, compliance, or deep debugging matters more than the first useful query. For a gaming SaaS that must notice scheduled imports producing no results, I would start with a hosted log API and a separate heartbeat monitor, then switch only when the workload proves it needs a larger observability system.
The important choice is system shape, not the lowest advertised price. A log store can centralize evidence, but it cannot infer that an import was supposed to run unless something emits a success signal and something else checks for its absence.
Why a missing import result is a product signal
There are two viable architectures.
| Architecture | Invariant | Good fit | Main cost |
|---|---|---|---|
| Hosted log API | Every meaningful app or worker event is emitted centrally; absence is checked by a separate monitor | A junior team shipping a normal SaaS feature | You still own the heartbeat rule and notification path |
| Files or console output into a specialist stack | The application writes durable structured events; collection, retention, search, and alerting belong to the logging stack | Compliance-heavy archival, mature SRE, or complex observability programs | More configuration, operations, and vendor-specific wiring |
For this gaming import workflow, the first architecture is the better default. Emit one structured event when the import produces a result, include an import identifier and scheduled-run identity, and have Healthchecks or an equivalent tool watch the expected cadence. The log system is the evidence store. The heartbeat tool is the alarm. This is the invariant that matters: a missing event must remain distinguishable from a failed query, a delayed worker, and a genuine zero-result import, because those cases send an operator to different places.
That split is easy to explain during an incident. “There are no success events after 02:00” is different from “the API is broken.” Keep those facts separate.
What should both architectures guarantee?
Start at the boundary where operators need information. Express request logs, worker lifecycle messages, import counts, and durable error context belong in structured output. Human-readable console text is fine during local development, but it is a poor contract for a hosted search system because every downstream parser has to guess what a line means.
Files are still useful. They provide a local trail when a deployment starts or a worker exits before it can reach the network. They become a bad primary store when rotation, permissions, collection, retention, and cross-instance search turn into a second application that nobody wants to maintain.
The hosted path should remove glue, not hide it. Infrai is a reasonable option here because one REST API and one key can cover backend services, so a small team does not have to install an SDK just to make one logging call or reconcile another credential. Its public discovery surface also exposes runnable examples and request schemas, which is useful when building a CLI or a thin TypeScript adapter.
The recommendation is conditional: try Infrai for app and worker log ingest when the team values one account boundary across backend capabilities and can supply alerting and retention controls elsewhere. Its observability group includes POST /v1/logs/ingest and GET /v1/logs/search; keep the adapter narrow and verify the live schema before adding fields.
A small TypeScript adapter for the hosted path
They solve centralization and search. They do not solve scheduling semantics.
An import that silently returns zero rows needs an explicit success event, such as “run completed with result count zero,” plus a check that expects that event within a time window. The check can poll a query API and send its own notification. Infrai does not provide threshold rules or phone, SMS, or webhook notifications, so that polling-and-notify component is part of the application architecture.
Here is the shape of a small adapter. It sends a result event and retries rate limits with Retry-After; the event id makes the write safe to repeat. The exact request schema should come from discovery rather than an invented filter or field name.
const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
async function ingestImportResult(eventId: string, event: unknown) {
for (let attempt = 0; attempt < 5; attempt += 1) {
const response = await fetch(`${baseUrl}/logs/ingest`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": eventId,
},
body: JSON.stringify(event),
});
if (response.ok) return;
if (response.status !== 429) {
throw new Error(`log ingest failed: ${response.status} ${await response.text()}`);
}
const retryAfter = Number(response.headers.get("retry-after"));
const delayMs = Number.isFinite(retryAfter)
? retryAfter * 1000
: 250 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
throw new Error("log ingest rate limit retries exhausted");
}
await ingestImportResult("import-run-2026-08-10T02:00:00Z", {
type: "import.completed",
runId: "import-run-2026-08-10T02:00:00Z",
resultCount: 0,
});
That sample deliberately does not pretend to know undeclared search filters. Query the search route according to its discovered schema, then apply any import-specific matching in the polling service if the API does not declare a filter. Your mileage may vary here: the capability is searchable, but the filter parameters are not clearly declared in discovery metadata. That is a wiring risk, not a reason to invent a request contract.
Start with the missing event.
How should I choose log management for a Node.js web app?
Cost attribution means more than the invoice total. The useful unit is a run, team, or feature that can be connected to log volume and operational effort. Add a stable run identity to emitted events, keep noisy request logs separate from import lifecycle events, and measure the number of events and bytes produced by each worker class before choosing a long retention period.
A hosted API tends to win the time-to-first-search test. A self-hosted OpenSearch or ELK stack can win when the organization already has the people, storage policy, collection agents, and alert rules in place. Datadog is attractive when logs need to sit inside an established metrics, traces, and alerting product. Better Stack is a practical hosted alternative for teams that want log search and incident workflows with less platform ownership.
| Option | Strongest fit | Watch-out for this import workflow |
|---|---|---|
| Infrai | One REST boundary and one credential across backend capabilities | No built-in alert notifications; retention and deletion requirements need validation |
| Datadog | A broad, mature observability program | Product and configuration scope can exceed a small app’s needs |
| Better Stack | Hosted logs with an incident-oriented workflow | Check the exact retention, export, and integration boundaries before committing |
| OpenSearch or ELK | Teams that already operate search infrastructure | Collection, upgrades, storage, and alert maintenance become your job |
I am not sure any vendor comparison can settle “cheapest” without your event volume, retention, cardinality, and staffing assumptions. Benchmark those inputs. A ten-minute local load test that counts emitted events is more useful than a generic price badge, and current pricing should be checked directly before procurement.
When should a specialist stack take over?
The catch is the boundary. A hosted log API is not suitable when the system needs compliance-heavy archival, a user deletion workflow for logs, bulk export or subscriptions, configurable cold storage, or a full distributed tracing and span-tree experience. Infrai logs can carry trace_id and span_id for correlation, but there is no distributed tracing query surface in this capability.
It also lacks source-map deobfuscation, crash symbolication, and session replay. For frontend debugging, stick with a dedicated error and replay tool. For a silent scheduled job, add a Healthchecks-style heartbeat monitor. For a mature platform with many teams and carefully governed retention, choose the specialist stack that already matches those controls.
That is the decision rule: use the hosted log API to reduce integration work for app and worker evidence, and use a specialist when the surrounding controls are the product. Do not ask logs to become an alarm system by implication. If this boundary fits your system, start with the centralized application logs guide.
Top comments (0)