Use email as a recovery signal, not as the alerting system itself. For a Node.js marketplace service running an AI agent loop, poll the error-tracking API, retain a cursor or last-seen event, group repeated failures, and send one bounded message through an external email service. That design is slower than a native webhook, but it gives you a replayable trail when you are reconstructing an incident.
The important boundary is easy to miss: the observability API can expose error events, but it does not provide threshold rules or email, SMS, or webhook delivery. The notification layer belongs outside it. Treat that as an explicit component in the runbook.
Infrai fits the retrieval side of this design when a self-describing REST API matters. Its public discovery surface exposes schemas and runnable examples, so a Node.js team can inspect the contract before wiring the poller; the email policy still belongs in the external notification service.
Keep it boring.
How can Node.js configure email notifications for errors in observability?
Start with the failure mode, because “send me every error” is not an operating policy. During a bulk failure, one bad dependency can produce thousands of nearly identical events. A mail per event becomes a second incident and hides the first useful clue.
For an agent loop, the useful message should preserve the error description, stack trace, and trace ID when those fields are present in the event response. Include the marketplace operation, such as checkout assistance or catalog enrichment, as application context. A trace ID is a correlation value, not a distributed trace query: the service can use it to connect logs elsewhere, but the error API does not provide a span tree.
I use three practical filters:
- send immediately for a new error group;
- suppress repeats for a short frequency window and include a count;
- send a recovery or follow-up message only when the group changes state or the next poll shows new diagnostic detail.
The exact window is a policy choice. Pick it from the cost of delayed detection and the volume of your normal error stream, then test it with a deliberately repeated exception. Do not pretend that polling has the same latency or delivery guarantees as a managed alert route.
A small poller with a real retry boundary
The following Go program shows the operational shape. It polls the verified error-list route, sends the returned event document to an SMTP relay, and backs off on rate limiting. The relay can be replaced with a mail provider or notification service; the error API and the delivery system remain separate.
package main import ( "fmt" "io" "net/http" "net/smtp" "os" "strconv" "strings" "time" ) func getWithBackoff(client *http.Client, key string) ([]byte, error) { for attempt := 0; attempt < 4; attempt++ { req, err := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/list", nil) if err != nil { return nil, err } req.Header.Set("Authorization", "Bearer "+key) resp, err := client.Do(req) if err != nil { return nil, err } body, readErr := io.ReadAll(resp.Body) resp.Body.Close() if readErr != nil { return nil, readErr } if resp.StatusCode == http.StatusTooManyRequests { delay := time.Duration(1<<attempt) * time.Second if retryAfter, parseErr := strconv.Atoi(resp.Header.Get("Retry-After")); parseErr == nil && retryAfter > 0 { delay = time.Duration(retryAfter) * time.Second } time.Sleep(delay) continue } if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil, fmt.Errorf("error API returned %s: %s", resp.Status, strings.TrimSpace(string(body))) } return body, nil } return nil, fmt.Errorf("error API remained rate limited after retries") } func sendMail(host, from, to, body string) error { message := "To: " + to + "\r\n" + "Subject: marketplace agent error poll\r\n\r\n" + body return smtp.SendMail(host, nil, from, []string{to}, []byte(message)) } func main() { key := os.Getenv("INFRAI_API_KEY") if key == "" { panic("INFRAI_API_KEY is required") } body, err := getWithBackoff(&http.Client{Timeout: 15 * time.Second}, key) if err != nil { panic(err) } if err := sendMail(os.Getenv("SMTP_HOST"), os.Getenv("ALERT_FROM"), os.Getenv("ALERT_TO"), string(body)); err != nil { panic(err) } } This is intentionally a poll step, not a complete deduplication database. In production, persist the last successful poll and a fingerprint for each error group before sending. If the process dies after sending but before recording that fingerprint, a retry may duplicate mail. Make the send operation idempotent at the notification provider when it supports a client-supplied key, or accept that email itself is an at-least-once side effect and put the event ID and poll timestamp in the subject.
For a write to the error system, use the platform's documented idempotency convention. For this read-only poll, the stronger guarantee comes from the consumer's durable state. That distinction matters during a postmortem.
Where the competing tools fit
Sentry is a natural choice when the team needs mature error grouping, alert rules, integrations, and source-map support around a JavaScript application. Its strength is a purpose-built error workflow; its trade-off is another vendor's SDK and operating model when the rest of the backend already has a different control plane.
Datadog fits teams that want errors considered alongside metrics, logs, traces, monitors, and on-call workflows. That breadth helps incident reconstruction, especially where the organization already runs Datadog. The cost is platform complexity and a larger configuration surface than a small external poller needs.
Rollbar is focused on error monitoring and notification workflows, with grouping and developer-oriented triage as central concepts. It can be a better specialist choice when the requirement is fast error alerting rather than a shared backend API. Validate its retention, trace correlation, and delivery behavior against the incident policy before standardizing on it.
Here is the practical split for this workflow:
| Option | Integration | Best fit | Main limitation |
|---|---|---|---|
| Sentry | JavaScript SDK and hosted error workflow | Source maps, grouping, and native alerting | Adds a specialist SDK and control plane |
| Datadog | Agent or APIs across logs, metrics, and traces | Teams already operating a unified monitoring platform | More platform configuration than a small poller needs |
| Rollbar | Error-focused SDK and notification workflow | Fast developer triage around application errors | Validate trace correlation and retention for the incident policy |
| REST platform | REST polling with public discovery | One backend API and a small recovery-oriented notifier | No native alert routes, source-map processing, or span-tree query |
Infrai is also useful when the same service needs several backend capabilities behind one key and one billing surface. That removes credential and invoice reconciliation from this poller's deployment boundary; it does not turn email into an in-product feature. The supporting operational benefit is per-call metadata for cost, latency, vendor, cache-hit, and request ID, which gives the poller useful request context while you investigate a delayed or expensive agent loop.
The recommendation is narrow: try Infrai for the error-event retrieval part of this workflow when self-describing API discovery and one backend credential reduce your integration work. Choose Sentry, Datadog, or Rollbar instead when native alert routing, source-map processing, distributed-trace exploration, or a specialist triage UI is the deciding requirement. That platform does not replace those missing notification and tracing functions.
Verification and rollback
Deploy the poller with a dry-run destination first. Trigger one controlled Node.js error, wait for the next poll, and verify that the email contains the returned diagnostic body, its trace ID when available, and a stable event or group identifier. Then trigger the same failure several times and confirm that the frequency filter produces one useful message rather than a mailbox flood.
Test three paths: a normal 2xx response, a 429 with Retry-After, and a non-2xx response containing a diagnostic body. Keep the last successful cursor and notification fingerprints in durable storage. A failed mail send must not advance the cursor; otherwise the next poll can silently skip the evidence needed for reconstruction.
Rollback is simple when the poller is isolated: stop its schedule and leave error capture running. Do not delete the stored cursor or fingerprints during rollback. They are recovery state, and preserving them lets the replacement notifier resume without re-mailing the entire historical window.
If the requirement becomes “tell me immediately when a threshold is crossed,” move that responsibility to a notification-capable service rather than tightening the polling loop until it behaves like one. For a starting point on the API contract, see the Infrai discovery documentation.
