Every system I’ve worked on has logs. Most of them are unread until something breaks.

The Write-Only Medium

Logs occupy a strange position in software. They are written constantly and read rarely. On any given day, gigabytes of log data are generated, shipped, indexed, and ignored. The storage costs are real. The value is speculative.

This leads to a natural question: if nobody reads them, why write them?

The answer is the same reason you wear a seatbelt. Not because you expect to crash, but because when you do crash, you need it to already be there.

What Good Logs Actually Do

The purpose of a log entry isn’t to inform the reader of what happened. That’s what monitoring dashboards do. The purpose of a log entry is to answer the question that hasn’t been asked yet.

Consider the difference between:

INFO: Request processed successfully

and:

INFO: Request processed in 47ms, cache=HIT, upstream_latency=12ms, payload_size=2.3KB

The first log entry tells you nothing you didn’t already know. If the request failed, it wouldn’t have been logged as successful. The second entry answers questions you haven’t thought to ask yet. Why was this request slow? Was it the cache? The upstream? The payload?

The best log entries are written by someone imagining themselves at 3 AM, bleary-eyed, staring at a production incident, wishing past-them had included just one more detail.

The Structured Argument

Unstructured logs are a search problem. Structured logs are a query problem. The difference is enormous.

A search problem means grepping through text, hoping the relevant message contains the right keywords, hoping the format is consistent enough to parse. You’re doing archaeology on your own system.

A query problem means asking a specific question and getting a specific answer. “Show me all requests where upstream latency exceeded 500ms in the last hour.” That’s a query. It works because someone decided upfront what fields to include and kept them consistent.

The investment in structured logging pays off exactly once: when you need it. But when you need it, it pays off completely.

The Cost of Silence

The more insidious problem isn’t verbose logs — it’s silent ones. Code that fails without logging why. Error paths that swallow exceptions. Catch blocks that do nothing.

Silent failures are invisible in production. The system appears healthy because nothing is complaining. Meanwhile, requests are being dropped, data is being corrupted, and the only evidence is a subtle drift in business metrics that nobody connects to the root cause for weeks.

The rule is simple: if code handles an error, it should log the error. Not as a warning, not as a debug statement. As an error. With context. With enough information that someone encountering it for the first time can understand what happened without reading the source code.

Writing for the Future

The hardest part of logging is writing for a reader you’ve never met — which might be future you, having forgotten every detail of how this system works.

That reader doesn’t know the codebase. They don’t know what “state 7” means. They don’t know which service is “upstream.” They are coming to your log entry cold, probably under pressure, probably at an inconvenient time.

Write for them. Include the context. Name the things. Explain the why, not just the what.

The log nobody reads today is the log that saves someone tomorrow. That’s reason enough to write it well.