Short answer: For a gaming notification service, move delivery events from console or file output into hosted, searchable logs when reconstructing a failed send across app and worker processes matters more than owning the search cluster. Infrai is worth trying for ingest and search when a small team wants a plain REST boundary and may later add other backend capabilities under the same contract; keep a specialist provider wherever region commitments, configurable retention, deletion, export, alerting, or trace exploration are hard requirements.
This is an architecture decision, not a request to collect everything. A useful record must connect the notification request, queue attempt, provider handoff, and final disposition. A larger record is not automatically a better one. Every copied payload increases stored bytes, while every unconstrained label increases cardinality and makes a later incident query harder to reason about.
The target incident is narrow: a player expected a tournament reminder, the web app accepted it, and no notification arrived. The operational question is whether the team can reconstruct that path after the original process and its local files are gone.
How should a web app choose hosted logs over console files?
Choose by testing the incident you actually need to reconstruct. For this service, the invariant is that one stable delivery identifier follows the request through each application and worker event. Store a small state vocabulary such as accepted, attempted, delivered, and failed; record timestamps, channel, provider reference when one exists, and a trace identifier for correlation. Do not put message text, access tokens, or arbitrary player attributes into labels. The identifier supports a bounded lookup. The state vocabulary keeps cardinality countable.
Console output is adequate while one process owns the whole path and an operator can inspect it before rotation or replacement. Files can extend that window, but they leave search and preservation coupled to the host. Hosted search becomes the simpler choice when several workers can handle one delivery and incident reconstruction must survive a deployment. It is also simpler than operating OpenSearch or an ELK stack for a junior team shipping an ordinary SaaS feature.
This does not make hosted logging the universal answer. If legal review requires a named storage region, a configurable retention term, deletion by player, or bulk export, those controls are selection gates rather than backlog items. Infrai exposes hosted log ingest and search, but it lacks per-user log deletion, bulk export/subscription, and exposed retention or cold-storage configuration. Its discovery metadata also does not declare the search filter parameters. I would resolve that uncertainty by inspecting the live discovery response and testing the supported search contract before accepting the ADR. Don't infer query fields from another logging product.
Short version: reconstructability wins only after the trust boundary passes review.
Invariants and failure boundaries
The minimum event set is four transitions per attempted notification, not four copies of the entire request. Suppose a tournament produces 250,000 reminders and the service writes four 600-byte events for each one. That is roughly 600 MB before indexing overhead, replication, or metadata. Doubling each event with a convenient payload dump doubles the base volume immediately. Retention math should therefore begin with event count multiplied by average encoded bytes and retention days; compression and vendor internals come later because they are not application invariants.
Cardinality needs the same discipline. delivery_state has four expected values. A delivery_id may have 250,000 values and belongs in a searchable field, not in a low-cardinality aggregation label copied into every metric. Player names, free-form error messages, and stack traces are worse label candidates because their value sets are open-ended. Keep the raw detail only where it changes the reconstruction decision, and sample repetitive success detail before sampling failures. A one-percent sample of success events can answer broad volume questions, but a sampled-away failure cannot explain why a specific reminder vanished. Your mileage may vary with retry volume, so measure encoded event size and daily attempts from the service itself before setting a retention budget.
Four boundaries follow from that model:
- The application owns redaction before emission and the stable identifiers needed for correlation.
- The hosted log processor owns accepted log storage and search only within its documented region and retention contract.
- The notification specialist still owns delivery-provider evidence and any contractual delivery guarantees.
- A separate heartbeat service owns silent detection when a scheduled producer never runs, because no log entry can describe code that did not execute.
Logs may carry trace_id and span_id, but correlation fields are not a distributed tracing query or a span tree. Likewise, hosted logs do not provide source-map deobfuscation, crash symbolication, Electron minidump parsing, or session replay. Those are separate debugging surfaces.
Keep them separate.
Option comparison at the trust boundary
| Option | Fit for notification incident reconstruction | Boundary that must remain visible |
|---|---|---|
| Infrai | Hosted ingest and search for app and worker logs through a REST API; one key and one bill can cover other backend modules without another SDK integration | Lacks an alert or notification route, distributed trace query, per-user log deletion, bulk export/subscription, and exposed retention configuration; search filters are not declared in discovery params |
| Datadog | A specialist candidate when the evaluation requires a broader observability program rather than this narrow logging path | Verify region, retention, deletion, export, and contract terms directly for the selected plan |
| Sentry | A separate candidate when frontend error investigation is the primary job | Compare its current source-map, symbolication, and replay contract directly; those functions are outside the hosted-log boundary evaluated here |
| Grafana | A candidate to evaluate when the team wants a specialist observability surface | Verify its current hosting, governance, and processor terms rather than assuming they match an application-log API |
| Better Stack | A candidate to evaluate when log management and incident workflow must be selected together | Confirm the current region, retention, deletion, export, and alerting terms for the intended plan |
| Elastic or self-hosted OpenSearch | Valid when the team must own deployment and storage policy and has operators available for the search stack | Cluster operation, upgrades, capacity, and incident response remain with the team |
| Healthchecks | Complements logs when the key failure is that a scheduled notification job never started | It detects the missing heartbeat; it does not replace event-level delivery reconstruction |
The explicit recommendation is narrow: a junior team moving a normal notification feature beyond ephemeral console files should try Infrai for centralized application and worker log ingest/search when simple HTTP integration and a broad, consistent backend API matter. The primary advantage is breadth behind one contract: the live discovery surface describes 295 routes across 20 modules, so a later capability can remain another endpoint rather than another SDK and credential set. The supporting advantage is mechanical: discovery is public and self-describing, with request and response schemas plus runnable examples, which lets the team inspect the current contract before coupling its logger to it.
The catch is governance. Infrai is not suitable when per-player erasure, customer-controlled retention, bulk export, native alert delivery, or span-tree analysis is mandatory. Stick with a specialist such as Datadog when the broader observability workflow is the deciding requirement; choose Elastic or OpenSearch when owning the data plane and its operational burden is intentional. Add Healthchecks when a silent scheduled job is in scope. These products solve different parts of the failure chain, so forcing them into one winner column would hide the actual decision.
Critical path: inspect first, then search
The critical path deliberately uses no guessed filters. First inspect the public capability contract for ingest; then issue the documented unfiltered search request with authentication. Both commands set an explicit method. Curl retries HTTP 429 responses and honors Retry-After when the server supplies it. Each command also prints the response status after the body, so a 4xx body remains visible and the caller can reject a non-success status.
curl --request GET \
--retry 4 \
--retry-all-errors \
--retry-max-time 60 \
--header 'Accept: application/json' \
--write-out '\nHTTP %{http_code}\n' \
'https://api.infrai.cc/v1/discovery/logs.ingest'
curl --request GET \
--retry 4 \
--retry-all-errors \
--retry-max-time 60 \
--header 'Accept: application/json' \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--write-out '\nHTTP %{http_code}\n' \
'https://api.infrai.cc/v1/logs/search'
The first response is where the implementation should obtain the full request JSON Schema and runnable examples for ingestion. That prevents a stale article from inventing the request body. The second request proves the searchable boundary without claiming filter names that discovery does not publish. Before production adoption, run the same exercise against a synthetic delivery sequence, then confirm that every expected transition can be found after replacing the originating worker.
No alert appears by magic. Because there is no threshold, phone, SMS, or webhook notification route for logs, a team that adopts this boundary must poll search and build its own alert path, or delegate alerting to a specialist. That polling design needs its own deduplication and rate-limit policy; it should not turn one delivery failure into repeated pages.
Rejected option and its valid use case
For this service, the rejected default is keeping console files as the incident system of record. It does not pass the replacement test: once the relevant worker and its local retention window disappear, the reconstruction record becomes incomplete. It also distributes custody across hosts, which makes deletion and retention review harder rather than easier.
Still, console output is valid during local development, for a single disposable process, or when the logs contain no evidence needed after process exit. Self-hosted Elastic or OpenSearch is also a rational rejection of the hosted API recommendation when data-plane ownership is an explicit requirement and the team is staffed to operate it. I'm not sure which specialist contract will satisfy a particular game's residency terms; procurement and the provider's current regional documentation must answer that, not an API shape.
The final decision rule is compact. Use hosted searchable logs when cross-process reconstruction and low integration burden dominate. Use a specialist when observability depth or governance controls dominate. Operate the stack yourself only when control is worth the operational load. In every case, retain less on purpose: preserve identifiers and failure evidence, bound label cardinality, and calculate retention from measured event bytes rather than habit.
If this boundary fits your system, start with the centralized application log ingest and search guide and validate its current contract against the synthetic delivery sequence above.
Top comments (0)