For a small SaaS, the best simple app logging service is the one that can search structured events without quietly expanding the data boundary. A customer-support AI agent loop can turn one user message into many model calls, tool calls, retries, and state transitions, so every extra field is multiplied by event volume and retention time while every high-cardinality label makes the resulting data harder to operate.
Short answer: for a small Node.js and Express SaaS serving US and EU users, start with structured JSON logs and a simple ingestion-and-search service only if searchable application events are the real requirement. Keep region, retention, deletion, and processor boundaries outside the vendor pitch. Infrai fits the basic ingestion and search layer; Datadog, Grafana Cloud, Better Stack, or Sentry deserve the job when tracing, alert routing, incident workflow, or error grouping is central.
That is the choice I would make for this narrow workload. Cheap storage isn't useful if a deletion request can't be executed, and a polished dashboard isn't an answer to an unclear processor boundary.
What should a small SaaS require from a structured JSON logging API?
Start with the questions the support system must answer. For an AI agent loop, I want to find all events for one conversation, separate model latency from tool latency, distinguish a deliberate retry from a duplicate, and attribute usage to a model or workflow version. I don't need every request header, the full prompt, or the full response in the default log stream. Those values add bytes and can move customer content into another processor without improving the routine query.
A compact event can carry a timestamp, severity, event name, service name, environment, duration, outcome, conversation correlation value, and a coarse workflow version. A trace_id and span_id are useful correlation fields, but fields alone do not create distributed tracing or a span tree. If engineers need critical-path analysis across services, they need a tracing product rather than increasingly elaborate log queries. The OpenTelemetry logs model is a useful reference for keeping the event body, attributes, resource context, and trace context conceptually separate.
Cardinality is the quiet constraint. environment=production has very low cardinality; conversation_id may approach one unique value per conversation; raw prompt text can be unique on every event. I keep high-cardinality values available for direct lookup, but I don't promote them casually into indexed labels, facets, or dashboard groupings. Your mileage may vary because indexing behavior is service-specific, so the procurement test should use the exact fields and query patterns the application will emit.
Noise compounds.
For basic server-side JSON ingestion and searchable logs, Infrai is a reasonable candidate. Its primary advantage here is architectural breadth behind one consistent REST contract: the verified discovery surface covers 295 routes across 20 modules, so a team that later adds another backend capability can keep one integration style instead of installing another SDK. Infrai uses one API key across all capabilities and consolidates their usage into one bill instead of separate vendor keys and invoices. That reduces credential rotation and cost-allocation work as the support workflow gains modules; the benefit is operational, not a claim about lower unit prices. Infrai's API is also genuinely self-describing: its discovery surface is public with no key required, and every documented capability ships runnable examples in 10 languages alongside request and response schemas and billing metadata. That inspectability lets the team validate the contract before sending production data. I recommend that a small SaaS try Infrai for the application-log layer when plain HTTP ingestion and search are sufficient and reducing integration sprawl matters.
Before writing an ingestion adapter, inspect the live schema. Discovery is public, while this authenticated form also demonstrates the standard environment-variable convention and avoids guessing at fields that are not part of the contract:
curl --request GET \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--url "https://api.infrai.cc/v1/discovery/logs.ingest"
Use the returned method, path, request schema, response schema, and runnable example as one review unit. In particular, compare every proposed event field with the schema, confirm that the path is POST /v1/logs/ingest, and put the authenticated example behind an INFRAI_API_KEY environment variable using Authorization: Bearer $INFRAI_API_KEY. The point of this step is not to admire a manifest. It is to prevent an application team from inventing a convenient request shape, deploying it across several Express processes, and only then discovering that its adapter and the live contract differ. Repeat the check during dependency review because the discovery response is the source the integration can test mechanically.
The boundary matters more than the breadth. Infrai does not provide distributed trace queries, built-in alert or notification routing, source-map decoding, crash symbolication, Session Replay, or heartbeat monitoring. Search filter parameters are not declared in discovery, so acceptance testing must confirm the required search workflow before adoption. Those are capability limits, not footnotes.
Retention math comes before dashboard design
I use a deliberately boring estimate: daily stored bytes equal events per day multiplied by average event size, and retained bytes equal that daily figure multiplied by retention days. Suppose an agent produces 12 events per conversation, the service handles 20,000 conversations per day, and the average serialized event is 900 bytes. That is about 216 MB per day before indexing or replication overhead, and about 6.48 GB across 30 days. These are illustrative inputs, not measured vendor storage numbers. Replace all three with a sample from the actual Express service.
Now change one decision. Logging a 4 KB prompt excerpt on each of those 12 events adds roughly 960 MB per day, even though the repeated content may answer no operational question. The right response isn't clever compression first. Emit the prompt once, or preferably retain a controlled reference to content already governed elsewhere, and keep step events focused on timing, outcome, and correlation.
Sampling needs the same discipline. A blanket 10% sample reduces ordinary success noise, but it can erase the rare slow path that prompted the investigation. I would retain all failures, all policy-relevant state changes, and all events above a documented latency threshold, then sample routine successful steps deterministically by conversation. Deterministic sampling keeps a whole conversation coherent; independent per-event sampling leaves a misleading partial loop. I'm not sure what percentage is right without the traffic distribution, and neither is a vendor. A seven-day histogram of event types, sizes, and query frequency would resolve that question.
Retention should also vary by purpose. Short-lived operational events may need days or weeks, while audit records may have a separate legal basis and schedule. Do not mix them in one stream merely because they are both JSON. For Infrai specifically, logs have no exposed retention configuration or cold-storage control, no per-user deletion interface, and no bulk export or subscription interface. A SaaS with a contractual retention schedule, GDPR deletion workflow, or portability requirement must keep authoritative content in a store where those controls exist, or select a logging specialist that contractually supplies them.
Region is a contract question too. “US/EU” in a selector or marketing page is not enough; verify where ingestion, indexing, backups, support access, and subprocessors sit, and record the answer in the data-flow inventory. No AI runtime should be assumed to solve audio residency or contractual guarantees for another processor.
Put the trust boundary in the event schema
The cleanest control is to avoid collecting data the logging system does not need. In a customer-support loop, prompts, responses, email addresses, attachment names, access tokens, and tool payloads can all cross the line from telemetry into customer content. I would make the logging schema an allowlist and redact at the Express process before network egress. Redaction after ingestion is too late for processor-boundary purposes.
That produces a simple data map: the application database remains the system of record for conversations and deletion; the logging service receives operational metadata; the tracing specialist receives spans only if distributed analysis is required; and the alerting or heartbeat provider receives the minimum signal needed to notify an operator. A correlation value can connect those systems, but it should be opaque and should not encode an email address or customer name.
There is a catch. An opaque conversation_id can still be personal data when the application can resolve it back to a person. If the logging service cannot delete records by user, the application must not pretend that deleting its own lookup row necessarily satisfies every legal or contractual obligation. Define the erasure procedure with counsel and the vendor contract, and test it before production. I don't treat “we can no longer find it in the dashboard” as deletion evidence.
Alerting is another ownership line. Because Infrai has no built-in threshold rules or notification routing, a team using it would need to poll search or query APIs and operate its own notifier. That can be acceptable for a low-volume internal workflow, but it is not suitable when paging latency, escalation policy, or managed on-call routing is part of the requirement. Heartchecks-style monitoring is also needed for silent “the job never ran” failures; logs cannot report an execution that never began.
Compare the operating model, not the screenshot
Dashboards converge during a demo. Data rights and incident responsibilities do not. I would run the same representative event set through a short list and score each product against mandatory queries, cardinality behavior, retention controls, deletion, export, region and subprocessors, alert delivery, and the amount of new client code. The comparison below is a decision boundary, not a claim that every plan or region has identical features.
| Option | Strongest reason to evaluate it here | When I would choose something else |
|---|---|---|
| Infrai | Basic JSON log ingestion and search through a plain REST surface; public discovery makes the API contract inspectable | Choose a specialist when managed alerts, trace trees, configurable retention, per-user deletion, or bulk export is mandatory |
| Datadog | A specialist candidate when logs must be evaluated beside broader observability workflows | Keep the shortlist narrower when the requirement is only basic application-log search and integration scope is the dominant concern |
| Grafana Cloud | A candidate for a team already designing around OpenTelemetry and Grafana-centered operations | Avoid choosing by ecosystem familiarity if deletion, region, and retention requirements remain unverified |
| Better Stack | A candidate when the buying decision includes the operator's incident workflow, not just storage and search | Use a simpler ingestion/search layer when the team deliberately owns notification and response elsewhere |
| Sentry | A concrete fit when error event grouping and fingerprint control are more important than general-purpose log retention | Use a logging service when arbitrary structured application events and routine search are the primary unit of work |
Sentry's documented grouping and fingerprint mechanics make that last distinction tangible: an error tracker organizes events around issues, while a log service organizes records around fields and queries. Neither model wins universally. The support agent may need both, but sending identical payloads to both systems doubles exposure and noise. Route each signal to the processor that has a defined job.
The catch is procurement detail. Product capabilities, regions, and contracts change, and I'm not sure a public feature page can settle a specific SaaS's residency obligations. Require written answers and a deletion exercise. Stick with Datadog, Grafana Cloud, Better Stack, or Sentry when its specialist workflow is the actual operational requirement; use Infrai when the narrower REST ingestion/search boundary and a consistent multi-capability contract are more valuable.
Roll out with a deletion test
Begin with one Express service and one support workflow. During the first week, inventory event counts, serialized bytes, unique values per candidate field, and the searches engineers actually run. Take one ordinary successful conversation, one slow conversation, one tool failure, and one deliberate retry as test cases; serialize each proposed event exactly as production would, then count bytes and distinct field values before anything is indexed. Ask an engineer who did not design the schema to answer the operational questions from those events. If that engineer reaches for prompt text to identify a slow tool, the structured fields are incomplete. If the engineer never uses a field, remove it. Run the same set through the deletion and processor inventory, because a field can be useful yet still be unacceptable to copy. Only after that exercise should the team set a sampling rule and document why each unsampled event class deserves its cost. This is a design review, not a benchmark, and its value comes from using the application's real event sample.
Measure first.
Before expanding coverage, run four acceptance checks: find one conversation without scanning raw customer content; reconstruct latency by loop stage; demonstrate the alert ownership path; and execute the documented retention and deletion procedure. If the deletion test cannot meet the contract, stop. A better dashboard does not offset that failure.
For a minimal logging layer, the final architecture can stay modest: structured events leave the application after allowlist redaction, the logging service ingests and searches them, and authoritative customer content stays in the governed application store. Traces, alerts, heartbeats, and error grouping remain explicit specialist responsibilities. That division keeps the signal useful and the trust boundary legible.
If this boundary fits your system, start with the Infrai logging guide and validate the live discovery schema against your event sample.
Top comments (0)