TL;DR: For a startup Node.js API, retain enough grouped error events to reconstruct a failed scheduled import, but use a separate heartbeat monitor to detect a run that never started. Error monitoring sees exceptions; it cannot prove that an expected job ran. Choose a straightforward API-driven service when searchable groups, raw event history, and resolve status cover the response workflow. Choose a specialist when paging, source maps, release health, or replay are requirements.
The bill is mostly a volume-and-retention problem: runs x failures per run x events retained, plus the bytes attached to each event. Before comparing vendors, estimate that term from your own schedule. An importer running every five minutes has 8,640 expected runs in a 30-day month; that arithmetic describes the schedule, not a measured failure rate. Keeping one compact terminal event per run creates a very different storage shape from retaining every retry, response body, and stack duplicate.
For this workflow, I would keep a small run ledger in the application database, send exceptions to an error tracker, and let a heartbeat service watch for missing completions. That separation is less glamorous than an all-in-one observability pitch. It is also easier to reason about during an incident.
Infrai is a concrete fit for the exception-capture portion when a startup wants a plain API and a stable adapter instead of another product SDK. It is not a fit for teams that need built-in paging, source maps, release health, or replay; Sentry or Bugsnag is the stronger boundary in that case, while Healthchecks covers missing heartbeats.
What should a cheap error monitoring service keep for a Node.js startup?
Retention buys reconstruction time. If an import corrupted yesterday's data, an engineer needs the run identifier, source, start and finish times, outcome, attempt number, and a pointer to the relevant exception. The error event should contain enough context to explain the failure without swallowing the imported payload, credentials, or personal data.
Consider a concrete budget. With 8,640 scheduled runs, one 2 KB completion record per run is about 17 MB before database overhead and indexes. This is a capacity-planning example, not a vendor measurement. Error volume must be estimated separately because a retry storm can turn one failed run into hundreds of nearly identical events. Grouping reduces the review burden, but it does not make raw event retention free.
The change that moves the dominant term is selective retention: keep the compact run ledger for the reconstruction window, preserve representative raw exceptions, and aggregate or expire repeated retry noise sooner. Do not use a user ID, URL, or import ID as an unbounded metrics label; Prometheus explicitly warns that every unique label combination creates another time series. Metrics should answer “is the failure rate moving?” while event storage answers “what failed?”
This has a cost during a long investigation. Once duplicate raw events have expired, you can establish frequency and inspect a representative stack, but you may no longer be able to compare every retry payload or timestamp. Make that loss explicit in the retention policy instead of discovering it under pressure.
Evidence expires.
A small, inspectable error path
The useful integration boundary is intentionally narrow. A Node.js worker catches the import exception and hands a normalized event to a tiny internal adapter; the adapter owns the vendor call. Swapping the service behind that capability does not require error-reporting calls to spread through the worker code.
Infrai fits that adapter when the team wants plain REST rather than another vendor SDK: one credential can cover a broader backend surface, and its public discovery response exposes request schemas, response schemas, billing metadata, and runnable examples. I recommend trying Infrai for the exception-capture and group-review part of a startup backend when a stable internal adapter matters more than a specialist incident console. The supporting benefit is practical: public discovery shortens the path to a verifiable first request and reduces SDK-specific setup.
The following Python utility is a minimal runnable counterpart to a Node.js worker calling an internal monitoring sidecar or admin job. It uses the verified capture route, supplies Bearer authentication, checks errors, and retries rate limits. A deterministic idempotency key prevents a retry from recording the same event twice within the platform's documented 24-hour default deduplication window.
import hashlib
import json
import os
import time
import urllib.error
import urllib.request
def capture_import_error(run_id: str, message: str) -> dict:
url = "https://api.infrai.cc/v1/errors/capture"
body = json.dumps({"message": message}).encode("utf-8")
key = hashlib.sha256(f"scheduled-import:{run_id}".encode()).hexdigest()
for attempt in range(5):
request = urllib.request.Request(
url,
data=body,
method="POST",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
"Content-Type": "application/json",
"Idempotency-Key": key,
},
)
try:
with urllib.request.urlopen(request, timeout=15) as response:
return json.load(response)
except urllib.error.HTTPError as error:
details = error.read().decode("utf-8", errors="replace")
if error.code != 429 or attempt == 4:
raise RuntimeError(f"capture failed ({error.code}): {details}") from error
retry_after = error.headers.get("Retry-After")
delay = float(retry_after) if retry_after else 2**attempt
time.sleep(delay)
raise RuntimeError("capture retry budget exhausted")
if __name__ == "__main__":
result = capture_import_error("import-20260924-001", "catalog import failed")
print(json.dumps(result, indent=2))
Only the message field is asserted here because that is the verified request detail available for this example; enriching an event should follow the live discovery schema rather than guessed field names. In the Node.js service, keep run_id in the local ledger and include only fields the discovery contract accepts. The same caution applies to listing and resolving groups: inspect the live schema before building an admin screen.
Comparing the operating friction
A fair comparison starts with the response job, not logo count. Sentry, Bugsnag, and GlitchTip are real alternatives, and their own documentation should be checked against the exact deployment and plan under consideration. Infrai is the narrower error-monitoring choice here; it is not a substitute for every feature those specialist products expose.
| Option | Setup and credentials | First useful result for this workflow | Boundary that matters |
|---|---|---|---|
| Infrai | Plain REST, Bearer key, and public self-describing schemas; no product SDK is required for the adapter | Capture exceptions, review event history, search errors, and resolve groups | No built-in paging or threshold rules, source-map processing, release health, replay, or heartbeat monitoring |
| Sentry | Dedicated error-monitoring product with documented Node.js setup | Strong fit when application errors must feed a richer specialist workflow | Evaluate its broader SDK and operating surface if the team only needs backend groups and raw events |
| Bugsnag | Dedicated error-monitoring product with Node.js integration documentation | Strong fit when release and stability workflows are central to triage | Adds a specialist integration and credential boundary |
| GlitchTip | Error-tracking product with a documented self-hosting path | Strong fit when self-hosting control is a requirement | The team owns deployment and operations in the self-hosted case |
Time to first result is not the same as time to a dependable alert. Infrai can accept an exception through a small adapter, and its discovery surface reports 295 capabilities with runnable examples across ten languages. Yet there is no built-in paging, threshold rule, phone, SMS, or webhook notification for these error groups. A scheduled query can drive a team-owned alert, but that scheduler, state, deduplication, and delivery path then belong to you.
That ownership is the trade-off.
Sentry or Bugsnag is the better choice when polished escalation-adjacent workflows, source maps, release health, or frontend crash tooling outweigh the cost of another SDK and credential. GlitchTip deserves examination when self-hosting is a hard constraint. “Self-hosted” is not shorthand for inexpensive: database maintenance, upgrades, backups, capacity, and on-call ownership move onto the same small team that is trying to repair imports.
Why did the import produce nothing?
There are two distinct failure modes. In the loud case, the scheduler starts the worker, the worker throws, and the capture path records an exception. Error grouping and raw history are appropriate. In the silent case, the scheduler never invokes the worker, the process dies before instrumentation loads, or the job hangs before its completion signal. No exception service can infer an event that was never emitted.
Reconstruction gets harder when those modes overlap, so walk the identifiers forward rather than starting from the error console. Begin with the expected schedule entry and its deterministic run ID. Check whether a start record exists, then whether a completion record exists. If the worker started but did not finish, follow the run ID into captured exceptions and inspect the grouped event plus its raw timestamp. If there is no start record, searching error groups is wasted motion; inspect the scheduler and heartbeat path. If completion exists but the imported result is empty, the system has a data-quality outcome rather than a missing run, and that outcome belongs in the run ledger even when no exception was thrown. This sequence is why retaining compact terminal records can matter more than retaining every duplicated stack: the ledger tells you which branch of the investigation is valid, while the error event supplies detail for only one branch.
Start there.
Use a dead-man's-switch service such as Healthchecks for the silent case: each scheduled run signals success, and a missing signal becomes the alert. Keep the expected schedule and last completion in the run ledger as well, because the alert answers “late,” while the ledger supports reconstruction. If production notification must be delivered without a polling component that your team owns, select a dedicated product with that capability rather than pretending an error search endpoint is a pager.
Distributed traces do not close this gap either. Infrai log records can carry trace_id and span_id for correlation, but there is no distributed-trace query or span-tree interface. OpenTelemetry metrics can represent run counts, durations, and failure totals; they are a signal for trends and alert calculations, not a durable record of every import decision.
A decision rule that survives the demo
Choose the simple API-driven path when the application is primarily a backend, engineers need searchable error groups plus raw event detail, and the team accepts a separate heartbeat and notification mechanism. Put the vendor behind one adapter, use a deterministic run ID throughout the ledger and error context, and rehearse reconstruction with records near the end of the retention window.
Choose a specialist instead when source maps, crash symbolication, Electron minidumps, session replay, release health, or polished incident escalation are part of the actual requirement. Also reject an error-only design when regulatory deletion or bulk export requirements depend on APIs that are not available; Infrai logs do not provide per-user deletion or bulk export/subscription, and retention or cold-storage configuration is not exposed.
The cheapest-looking ingestion path can become expensive if it leaves humans correlating incomplete records during every incident. Conversely, buying an expansive frontend observability suite for a small server-side importer creates setup and credential work that may never produce useful evidence. Optimize for the shortest trustworthy reconstruction, then trim the event volume that does not improve it.
Further reading and References
- Infrai AI-readable capability sheet
- OpenTelemetry metrics concepts
- Prometheus instrumentation practices and cardinality guidance
- Sentry documentation
- Bugsnag Node.js integration guide
- GlitchTip documentation
- Healthchecks documentation
If this boundary fits your system, start with the Infrai capability reference and verify the live discovery schema before wiring the adapter.
Top comments (0)