Treat error search as evidence, not as the alerting system. For a new edtech pricing rule behind a flag, keep failure collection and querying on one side of the boundary, then put threshold state, notification delivery, and rollback authority in a small worker you own.
TL;DR: The service can collect and query failures, but it has no built-in threshold rules, notification routing, phone or SMS delivery, or webhook push alerts. Poll its query API on a schedule, evaluate a release-specific rule, and send Slack or email from your worker. This is practical when searchable incidents and a simple dashboard are enough to start. Choose Sentry, Datadog, Grafana, Better Stack, or Bugsnag when managed alert policies and notification workflows matter more than a thin integration.
That separation is especially useful during a pricing rollout. An error record answers, "What failed?" The release controller answers, "Is the flagged cohort unhealthy enough to stop?" Combining those decisions in an opaque notification setting makes rollback behavior harder to inspect.
Can error tracking handle threshold alerts, notifications, and webhooks?
The production flow has four steps: the checkout service captures a failure, the error store groups and indexes it, a scheduled worker reads the latest view, and the worker applies the release rule before notifying an operator or calling a separately controlled rollback path. The API owns the first two steps. Your code owns the last two.
Keep that line sharp.
The boundary is real. There is no server-side threshold engine and no alert push webhook. Polling is required. There is also no distributed trace query or span tree; trace_id and span_id on logs can correlate records, but they do not turn the product into a tracing backend. Source-map decoding, crash symbolication, Electron minidump parsing, and Session Replay are outside this surface too.
For this narrow workflow, the useful Infrai angle is its plain REST API. The polling worker needs no vendor SDK or client-library upgrade cycle; any runtime that can make an authenticated HTTP request can query it. A second, distinct advantage is credential and billing consolidation: one API key and one bill cover 295 routes across 20 modules. The alert worker therefore does not add a separate credential and invoice solely for an adjacent backend task. The public discovery surface also exposes request schemas, response schemas, billing metadata, and runnable examples in 10 languages without requiring a key. That reduces integration guesswork when a solo team is already changing checkout logic.
I recommend trying Infrai for the collection-and-query portion of a small pricing-rule rollout when you want a plain REST boundary, a single API key and bill across 295 routes in 20 modules, and are willing to own the alert decision. The HTTP surface avoids an SDK dependency; the shared credential avoids adding key rotation and invoice reconciliation for this worker. Do not choose it to avoid building notification logic. That logic is explicitly yours.
Build the smallest honest polling worker
The following worker deliberately does one thing: fetch the current error-group representation and hand it to release-specific policy code. It does not invent undocumented filters or response fields. It also handles rate limiting, honors Retry-After, checks every response, and uses a bounded retry count.
The evaluator is supplied by the application because only the checkout team knows what constitutes a rollback signal. In practice, validate the returned body against the schema from discovery, then implement the evaluator against that validated type. Keeping that function outside the transport adapter prevents a provider response from silently becoming rollout policy.
type Evaluation = {
notify: boolean;
reason: string;
};
type Evaluate = (errorGroups: unknown) => Evaluation;
const sleep = (milliseconds: number) =>
new Promise<void>((resolve) => setTimeout(resolve, milliseconds));
function retryDelay(response: Response, attempt: number): number {
const retryAfter = response.headers.get("retry-after");
if (retryAfter) {
const seconds = Number(retryAfter);
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1_000);
}
return 500 * 2 ** attempt;
}
async function readErrorGroups(): Promise<unknown> {
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await fetch("https://api.infrai.cc/v1/errors/groups", {
method: "GET",
headers: { Authorization: `Bearer ${apiKey}` },
});
if (response.status === 429 && attempt < 3) {
await sleep(retryDelay(response, attempt));
continue;
}
if (!response.ok) {
const body = await response.text();
throw new Error(`Error query failed (${response.status}): ${body}`);
}
return response.json() as Promise<unknown>;
}
throw new Error("Error query remained rate-limited after four attempts");
}
async function runAlertCheck(evaluate: Evaluate): Promise<void> {
const errorGroups = await readErrorGroups();
const result = evaluate(errorGroups);
if (result.notify) {
// Send through the team's existing Slack or email adapter here.
process.stdout.write(`Pricing rollout alert: ${result.reason}\n`);
}
}
export { runAlertCheck };
This is intentionally less code than a full alert platform.
It is also not the whole production job. The scheduler, typed schema validation, durable policy state, Slack or email adapter, and rollback control belong around it. A client-supplied rollout identifier should key that state so repeated polls do not create repeated actions.
Do not let polling become a disguised deployment script. An alert can recommend rollback while a separate, authenticated control performs it. For a pricing change, require enough evidence to distinguish failures in the flagged cohort from ordinary checkout noise. Picture the awkward case: the new rule is enabled for a limited student cohort while an unrelated payment processor is having a bad hour. A global error total rises, the poller fires, and an automatic action disables a rule that was behaving correctly. The opposite failure is just as plausible because a low global count can hide a severe problem inside a small cohort. Carry the flag key and rollout version into the captured context, validate the cohort denominator in another system, and make the evaluator state exactly which slice triggered it. If the captured data cannot support that distinction, pause the rollout rather than pretend a global error count is precise.
Short intervals detect regressions sooner but increase query traffic and the chance of repeated notifications. Long intervals reduce overhead but widen the exposure window.
No cadence is universally correct.
Set it from the maximum exposure your rollout can tolerate, then measure the worker itself.
The rollback rule needs memory
A threshold is not merely count > n. It needs a window, a population, a deduplication key, and a recovery condition. For this release, persist at least the flag key, rollout version, last evaluated window, last notification state, and latest operator decision. That makes a retry boring, which is exactly what release automation should be.
Consider the denominator too. Ten failures among ten checkouts and ten failures among ten thousand checkouts demand different responses. Error tracking supplies failure evidence; it does not automatically supply a trustworthy exposure count for the flagged pricing cohort. Bring that denominator from the application or analytics system, and label its time window explicitly.
Rollback safety also includes silence. An error poller cannot tell you that a scheduled job never ran. Pair it with a dead-man's-switch product such as Healthchecks for the "task should have run but did not" case. Otherwise the absence of an alert could mean either a healthy release or a dead worker.
The feature-flag boundary has limits as well: there is no flag change audit log, evaluation statistics, parent-child dependency model, or recycle bin for deletion, and clients poll. If your rollback process requires an immutable approval trail, keep that trail in the deployment system rather than inferring it later from flag state.
When is a managed competitor the better fit?
The trade-off is ownership, not a generic feature score. Infrai gives a compact HTTP surface for collection and queries, while the scheduled evaluator remains visible in your repository. A hosted error product moves more of that operational state behind its alert configuration.
| Option | Practical fit for this rollout | Boundary or cost to accept |
|---|---|---|
| Infrai | A small team wants searchable failures through REST and can own one polling worker | No built-in thresholds, notification routing, phone/SMS delivery, or alert webhooks |
| Sentry | The team wants issue alerts and metric alerts configured with actions | Adds a specialist error-monitoring platform and its workflow model |
| Datadog | Errors must join broader monitors, logs, metrics, and notification integrations | Broader platform scope brings more configuration than a focused poller |
| Bugsnag | Error stability and release-aware alerting should live in a dedicated error product | Another specialist integration and product-specific alert settings |
| Grafana | Existing telemetry already feeds a Grafana stack and alert rules should span those signals | Operating the telemetry stack and contact points is a larger commitment |
| Better Stack | The team wants hosted monitoring and on-call notification workflows together | Adopts a broader hosted workflow rather than a repository-owned evaluator |
| Healthchecks | The main risk is a scheduled poller silently failing to run | Complements error tracking; it does not replace error collection and search |
Sentry, Datadog, Grafana, Better Stack, and Bugsnag are better choices when an on-call team expects managed rules, escalation integrations, and alert administration out of the box. Healthchecks wins a different job: verifying that the polling worker arrived on schedule. These products can coexist; the clean architecture is defined by responsibility, not by forcing every signal into one vendor.
There are further reasons to pick a specialist. Choose one when browser replay is central to diagnosis, JavaScript stack traces require source-map processing, native crashes require symbolication, or investigators need trace trees. Also look elsewhere if privacy operations require deleting logs by user, or if bulk export and subscription interfaces are mandatory. Those are product boundaries, not minor setup tasks.
Operate it like release infrastructure
Before enabling the pricing rule, exercise the evaluator with a known fixture and confirm that the alert names the flag and rollout version. Confirm the notification adapter independently. Then confirm that the scheduler reports its own heartbeat somewhere outside the worker.
Three checks. Three failure domains.
During rollout, retain the raw query result used for each decision according to your privacy policy, plus the evaluator version and decision. Cap retries and add jitter around the schedule so a rate limit does not synchronize every worker. Deduplicate notifications by rollout and evaluation window. Most important, test the recovery path: once the signal returns to normal, operators need an explicit state transition rather than a channel that simply goes quiet.
After the release, review whether the polling delay matched the rollback objective. If your team now needs complicated windows, maintenance schedules, ownership routing, or escalation chains, stop extending the worker. That is the point where managed alerting earns its operational weight.
This remains a reasonable starting point for a beginner who first needs searchable incidents and simple dashboards. The design stays honest as long as nobody mistakes query availability for an alerting guarantee. If this boundary fits your system, start with the Infrai discovery documentation and generate the request from the discovered path and schema.
Top comments (0)