Yashveer Singh
Connect
<- All posts

Logging Strategy for SaaS: Structured, Searchable, Useful

A logging strategy for SaaS is the combination of log format, log level conventions, contextual field standards, and log routing decisions that make application logs useful for debugging, monitoring, and audit purposes. The difference between a useful logging strategy and a useless one is whether an engineer can find the root cause of a production incident using only the logs within five minutes of opening the log viewer.

Written by Yashveer Singh, founder of Yashveer Labs.

What you need to know

  • Structured JSON logs are the prerequisite for everything else. Free-text logs are not searchable at the speed required during an incident.
  • Request ID correlation is the single change with the highest debugging leverage. Without it, tracing a request failure across multiple log entries requires manual time-based reconstruction.
  • Log levels mean nothing unless the team agrees on and enforces the definitions. If ERROR is used for expected conditions, real errors become invisible.
  • Log context fields should be consistent across all services. An application where one service logs userId and another logs user_id doubles the work of every cross-service query.
  • Log retention and access policies are compliance requirements, not just operational preferences. Decide retention periods before the first enterprise customer asks about your data practices.

The core argument

The test of a logging strategy is whether an on-call engineer can find the root cause of a production incident in under five minutes using only the logs. Most logging strategies fail this test not because the logs are missing but because they are not searchable. Free-text log messages that include context as formatted strings rather than as separate fields require either exact string matching or regex queries that are slow and fragile. A JSON structured log entry with a user_id field, a request_id field, and a route field can be filtered with a single query in any modern log viewer. The investment in structured logging is a one-time instrumentation change with a permanent debugging benefit.

The request ID pattern is the highest-leverage change in the logging strategy. A UUID generated for each incoming request and threaded through every log entry, every downstream service call, and every background job spawned from that request creates a single query that surfaces everything that happened as a result of one user action. Without this correlation, debugging an incident requires reconstructing the timeline from timestamp ranges and hoping that the relevant entries are not mixed with concurrent requests from other users. With it, filtering for a single request ID shows the complete story of what happened, across every service, in chronological order.

Log level discipline is where most teams erode their logging strategy over time. An ERROR log level that gets used for "we caught this exception and handled it gracefully" rather than "this requires immediate human attention" fills the error stream with noise that hides real errors. The correct use of ERROR is: something failed that requires investigation or action. If the failure was expected and handled, it is WARN at most. If it is normal operational information, it is INFO. If it needs to be logged at all, it should have a field that distinguishes expected from unexpected failures. A clean error stream where every ERROR is a genuine signal is the operational standard that makes on-call work manageable.

Common mistakes

  1. Not including a timestamp in every log entry. Some logging libraries include timestamps by default; others require configuration. Verify that every log entry includes an ISO 8601 timestamp before deploying. Logs without timestamps are nearly unusable for incident reconstruction.
  1. Using different field names for the same concept across services. A log query that needs to filter by user ID should work the same way in every service. Define a standard log field naming convention and enforce it across the codebase. Common inconsistencies: userId vs user_id vs uid, requestId vs request_id vs traceId.
  1. Logging too much at INFO level. An INFO log for every row read from the database, every cache check, and every function call produces volume that overwhelms the useful entries. Reserve INFO for events that have operational significance: requests received, background jobs completed, configuration changes applied.
  1. Not logging enough context at ERROR level. An error log entry should include everything needed to reproduce or understand the failure: the input that caused it, the state at the time, the error message and stack trace, and the request or operation ID. An error message without context requires the on-call engineer to read the code to understand what happened.
  1. Not testing log output in development. Log instrumentation that is not tested produces unexpected formats, missing fields, and PII in production. Run log assertions in integration tests to verify that log entries for critical operations contain the expected fields and values.

Where to start

  1. Convert the highest-traffic API handler to structured JSON logging. One handler, with explicit fields for request_id, user_id, route, status_code, and duration_ms. Verify the output in your log viewer. This becomes the template for the rest of the application.
  1. Add request ID generation and propagation. Generate a UUID at the API gateway or the first middleware layer. Include it in every downstream log entry. Add it to the response headers so external clients can reference it when reporting issues.
  1. Write the log level policy. One paragraph that defines what each level means and gives an example. Share it with the engineering team and add it to the onboarding documentation. The policy makes the enforcement conversation easier.

Related reading

FAQ

Frequently asked

Author

Why Yashveer Singh is the right hire here

The right hire for the work in this article is someone who has done it, written about it, and is willing to back it up with their name. That is me. Yashveer Singh. Founder of Yashveer Labs. New Delhi. The work I have shipped is on the homepage. The work I am writing about is the work I do. There is no mismatch between the page and the engineer behind it.

Related reading