Log Management Best Practices When There's No Platform Team
Nearly every article about log management best practices is written for a company with a platform team, a compliance department, and a SIEM budget. If you’re five engineers running a SaaS, most of that advice is not just premature — following it will actively slow you down. The best practices for you are a different, shorter list, and about half of it is deciding what not to build yet.
I’ve done log management at both ends of the spectrum: a two-person startup where “the logging pipeline” was a tmux session, and an org where the logging cluster had its own on-call rotation. The small end taught me more.
The three practices that pay off immediately
If you do nothing else from this article, do these. Each one takes under a day and keeps paying out for years.
1. Log in JSON, one event per line.
Structured logging is the single highest-leverage change a small team can make, because it converts every future problem from “write a regex” into “write a filter.” Every language has a mature library — pino for Node, zerolog for Go, structlog for Python. Switch the formatter, don’t rewrite call sites.
The discipline that matters more than the library: pick five field names (level, msg, ts, request_id, user_id) and use them everywhere. A team of five can enforce this in code review. A team of fifty needs a schema registry and a committee. Enjoy being five.
2. Put a request ID on everything.
Generate it at the edge, pass it through every service call, log it in every line, and — this is the part that separates teams that debug fast from teams that don’t — return it to the browser in a response header. When a customer emails “checkout is broken,” a request ID turns twenty minutes of timestamp archaeology into one query. If you also run session replay or error monitoring on the frontend, correlate the same ID there; the whole point is one string that follows the request across every system you own.
3. Centralize errors and warnings first, everything else later.
You don’t need every debug line in a central store. You need every error and warn from every service in one place, because the debugging failure mode that actually hurts is not “the log line was hard to query” — it’s “the log line was on a box nobody thought to check.” Ship the high-severity stream first. It’s maybe 1% of your log volume and 80% of the value. The full sequencing — which service, which signals, in what order — is its own topic, and I’ve written up the first steps of centralizing logs separately.
Retention that fits a real budget
Log storage pricing is where small teams get quietly bled. The hosted platforms’ per-GB-ingested pricing models (as of mid-2026, most of the big names price this way) mean a chatty debug logger in a hot loop can turn into a surprising invoice before anyone notices.
The defensible retention shape for a small SaaS:
- Errors and warnings: 90 days. This is your incident history and your “has this ever happened before” archive. It’s small; keep it.
- Info-level application logs: 14–30 days. Long enough to debug anything a customer will actually report, short enough to be cheap.
- Access logs and debug noise: 3–7 days, or don’t centralize them at all — leave them on-host with logrotate and let them die there.
Notice that this is severity-based, not service-based. Retention policies organized by team or service always decay into “everything gets the maximum,” because nobody wants to be the person whose service had short retention during an incident.
And write the numbers down somewhere. A retention policy that exists only as bucket lifecycle rules is a policy nobody remembers agreeing to.
When grep over SSH is honestly fine
Here’s the opinion that gets me looks: for a single-digit number of servers, grep over SSH is a legitimate log management strategy, and pretending otherwise is how five-person teams end up operating an Elasticsearch cluster that needs more care than their product.
I’ve watched a 4GB Elasticsearch heap eat itself during an incident — the log cluster went down with the thing it was supposed to help debug, which is the kind of irony you only need to experience once.
grep is fine when all of these are true:
- You have fewer than, say, five hosts, and you know their names.
- Your logs are structured (see practice #1 —
grepplusjqover JSON lines is genuinely pleasant). - Nobody outside engineering needs to read logs.
- Your compliance obligations don’t require centralized audit trails.
It stops being fine the day one of those flips — usually the host count, or the day a support person needs log access and you realize “SSH to prod” is not an acceptable answer. Until then, a for-loop over SSH answers most questions in seconds and costs nothing.
Log management best practices that don’t apply yet
For completeness, the enterprise checklist items you can skip without guilt, roughly ordered by how often people burn time on them anyway:
Log-based alerting on everything. You need alerts on error rate and a handful of known-bad strings. You do not need forty alert rules; you’ll mute them within a month, and muted alerts are worse than none because they emit false confidence.
A dedicated SIEM. Security information and event management tools exist to satisfy auditors and staffed SOCs. If you have neither, a SIEM is a subscription that produces dashboards nobody opens.
Sampling infrastructure. At small volumes, sample nothing. Sampling is a solution to a cost problem you don’t have yet, and it costs you the one log line you’ll eventually need.
A schema registry / logging standards document longer than a page. Your five field names in a pinned Slack message outperform a governance process.
Multi-region log replication. Your logs can live where your servers live. When a customer contract says otherwise, the contract will fund the work.
None of these are bad practices. They’re practices with a prerequisite — headcount — that you haven’t met. The failure mode I keep seeing is a small team implementing the fortune-500 list at 20% each instead of the small-team list at 100%.
The one-page version
Structured JSON logs with five agreed field names. A request ID that travels from browser to database and back. Errors and warnings centralized in one queryable place, kept for 90 days; everything else kept short or kept local. grep without shame while you’re small. And a written half-page policy so that next year’s hire understands why it’s set up this way.
That’s the whole list. Everything else is either a scaling problem you’ll be glad to have, or vendor marketing wearing a best-practices costume.
See the bug the way your user did
LogReplay captures session replays, console output, network requests, and errors in one timeline — so you stop guessing what happened before the ticket arrived.
Try LogReplay free