Your log retention is probably zero, and you will find out the day you need it
Ask most people who run a small website how long their server logs are kept and you will get a number: thirty days, ninety, a year. Ask them when they last read one and the answer is usually never. We were in that position until a question about our own site needed twenty-one months of history, and we went to get it. The raw logs were not ours to read. The log directory we could reach was empty. Our effective retention, for the party who actually needed the data, was zero days — and nothing had gone wrong. This is how the history survived anyway, what we did to stop depending on luck, and the check we should have run long before we needed it.
The question that needed the history
In the previous article we measured what a twenty-month robots.txt defect had cost us, and the honest answer was close to nothing. We could only say that because we had a series spanning the whole fault. A defect that ran for twenty months needs twenty months of data to say anything about; a before-and-after around the fix date measures a week and calls it a trend.
That article did not say where the twenty-one months came from, and the answer is the more useful story. It did not come from the raw access log. It came from the one thing that happened to outlive it.
1. Two claims that sound like one
Our site runs on ordinary shared hosting: one account among many on a machine we do not administer, with file access confined to that account's own directory. It is the setup most small businesses have and it is a perfectly reasonable one. It has a property that is easy to miss until it matters.
The web server's raw access log is written by the server, so it is owned by the server's administrative user and lives outside the boundary of any single account. The host retains it; that is true. We cannot read it; that is also true. The account had a log directory of its own, where a copy is conventionally placed for the customer — and it was empty. It had been recreated, empty, during a host migration a few days before we looked, and nothing had ever depended on its contents, so nothing had noticed.
"The logs are retained" and "you can read the logs" are two different claims. The second is the one that matters at two in the morning, and it is the one nobody checks.
Nobody had lied to us and nothing was misconfigured. Retention, measured as the host measures it, was fine. Retention, measured as the number of days of log we could actually open, was zero. The difference is that retention is a property of the party who will need the data, not of the machine that holds it — and we had never measured it from our side of the line.
2. The record that survived by accident
What we did have was a side effect. The hosting account came with a log analyser of the kind bundled with most shared-hosting control panels: it reads the raw log the host keeps, and renders the familiar monthly report of visits, pages, status codes and user agents. To do that it maintains its own working files — one summary database per calendar month, written into the account's own directory where we could read them.
There were twenty-one of them, January 2025 through September 2026, with no month missing. Every figure in the previous article — the 2,694 requests for /robots.txt that returned 404, the month-by-month third-party crawler series, the ceiling of about four search arrivals a month that never moved — was computed from those files and from nothing else. The raw log that produced them was unreadable to us and the customer copy was gone. The derived artefact was the only record left standing.
Nobody had ever treated it as the system of record. It was a reporting convenience with a retention policy we had not read, on a host whose policy is not ours to set. If one of those months had been rotated out, no later work at any level of access could have recovered it. We had been holding twenty-one months of irreplaceable history in a cache.
A derived artefact that outlives its source quietly becomes your system of record. It does not announce the promotion. Find yours — the analytics database, the monthly report export, the backup of a backup — and ask whether it is being treated like one.
3. Making the accident durable on purpose
Once you know a record is the only one, the next step is not analysis. It is a second copy, taken before anything else happens. We mirrored all twenty-one monthly databases, read-only, into our own version control on 5 September 2026, and committed them alongside a manifest with four columns per file: name, byte size, SHA-256, and the timestamp of the last log record each database says it folded in.
That last column is what turns the manifest from an inventory into an instrument. Twenty of the twenty-one months were closed, so their bytes should never change again; the twenty-first was the current month, still accumulating, and its checksum was expected to move. Written down, that expectation is a drift check: a later re-read that finds a closed month with a different hash has found either a retention event or a collection error, and can tell which.
We also archived the analyser's own configuration file, deliberately rather than incidentally. It holds the settings that decide what every number in those databases means: which HTTP status codes count as a successful hit, which file types are not counted as pages, how aggressively a client is classified as a robot, whether addresses are resolved to hostnames. Change any of them and the same raw log produces different monthly figures. A count quoted without them is a number without an instrument — you can quote it, but you cannot reproduce it, and you cannot compare it with next year's.
Archive the instrument with the data. A figure whose measuring settings are lost is a figure that can never be re-measured, only re-quoted.
One consequence of the configuration is worth stating because it shaped what we were willing to publish. The analyser classifies our own deploy checks and uptime probes as robots, so a large share of its all-crawler total is us, monitoring ourselves. That total is uninterpretable as interest and we have never printed it. The third-party crawler series is clean, and it is the one we report.
4. Arm the re-read; do not promise it
A snapshot protects the past. It does nothing for the month after it was taken, and the sentence "we should re-mirror this in about thirty days" is a plan with nothing that runs it. We have written that sentence before and watched it expire, so this time the re-read is a scheduled job, not a calendar note.
It has two halves, because they need different privileges. The mirror needs access to the hosting account, so it runs inside a session that legitimately has that access; it re-fetches every database on a thirty-day cadence, never assuming the files persisted, and writes what it found to a durable state file. A separate dead-man check runs from plain cron, needs nothing but that local file, and asks one question: how long has it been since a mirror succeeded? If the answer passes thirty-seven days, it raises an alert. Silence is the failure mode of every archive job, so the silence is the thing being instrumented.
The state file has one rule we consider worth breaking a build over. A run that could not read the databases records an explicit failure and no coverage figures at all — not "0 months", not an empty list, nothing. A reader that finds "months captured: 0" cannot tell "the server has no data" from "we could not look", and the second one renders as a clean, complete, reassuring zero. Absence is the only encoding a downstream reader cannot default into a good number.
"We'll pull the logs" is a plan with an unverified dependency. So is "the provider keeps backups." Both are true until the day you test them, and the day you test them is the day you need them.
5. The accidental record contains personal data
There is a second thing you inherit when a derived artefact becomes your system of record: everything it happens to contain. Log analysers keep a per-visitor section, and it is a table of raw client IP addresses with hit counts and timestamps. Under GDPR that is personal data. The moment we made the copy durable, we owned a durable copy of it.
We kept the archive verbatim, on one explicit condition. Stored where the original already sits, in the same account, a second copy adds no new exposure class — it is neither more nor less reachable than the file it was mirrored from. That is a fact about location, not about the data, and so the condition travels with the archive in its own README: the copy does not leave the machine unredacted, and the redaction question is settled before any off-machine copy is taken, not after. An off-machine copy cannot be recalled, so there is no version in which the question is asked afterwards and the answer still means anything.
We also costed the redaction rather than assuming it, and it is not a one-line filter. Dropping the visitor table leaves other sections that were derived from the same addresses — city and network-operator breakdowns that are not anonymous in combination — and it invalidates the internal byte offsets the analyser uses to find its own sections, after which the tool can no longer read the file. Redact a copy at export time, and never by re-mirroring, because by then the server's own copy may be gone. That is the whole reason the archive exists.
When you promote a side effect to a system of record, read what is in it first. It was not designed to be kept, so nobody designed what it keeps.
6. How to run this check on your own site
None of this needed a tool we bought. It needed one question asked from the right side of the line, and a few decisions taken while there was still time to take them.
- Check retention as the account that will do the reading. Not as the administrator, not by reading the hosting plan, and not by asking support. Log in as the account you would use at two in the morning, list the log directory, and look at the date on the oldest file you can open. That date, minus today, is your retention. Ours was empty, and a one-line listing would have told us so any time in the previous year.
- Find your derived artefacts. Analytics databases, monthly report exports, a mail archive, a dashboard's cache. Anything that summarises a source you cannot re-read is a candidate system of record, whether or not anyone called it that. For each one, ask who sets its retention and whether you would find out when a month disappeared.
- Take the second copy before the analysis. A record that exists in one place you do not control is not yet a record. Mirror it read-only into something versioned, with a manifest — name, size, checksum, and the internal timestamp that tells you whether the file was closed or still accumulating.
- Archive the instrument with the data. The configuration that produced the numbers is part of the numbers. Without it you can quote a figure; you cannot reproduce or compare it.
- Arm the re-read as a job with a dead-man. A recommendation to "re-check in thirty days" needs a thing that re-checks and a second thing that notices when the first one stopped. Give the two different privileges if you can: the one that needs access to the host runs only where that access already legitimately lives, and the one that watches for silence needs none.
- Record failure as absence, not as zero. A run that could not read anything must not write a count of zero. Every downstream reader will default a zero into a clean result; none can default a missing field into one.
- Read what the artefact contains before you make it durable. If it holds personal data, the copy that stays where the original is and the copy that leaves the machine are different decisions with different answers, and the second one has to be taken first.
The short version
- We needed twenty-one months of server logs. The raw log was not ours to read and the directory we could reach was empty. Effective retention for the party who needed it: zero days, with nothing misconfigured.
- Retention is a property of who will need the data, not of the host. "The logs are retained" and "you can read the logs" are different claims — check the second, as the account that will do the reading, before you need it.
- The history survived as a side effect: the log analyser's own monthly databases, twenty-one of them with no gaps. A derived artefact that outlives its source becomes your system of record without telling you.
- We made it durable on purpose — mirrored into version control on 5 September 2026 with a manifest of names, sizes, SHA-256 checksums and internal last-record timestamps, plus the analyser's configuration, because the numbers are figures without an instrument.
- The re-read is a scheduled job on a thirty-day cadence with a dead-man at thirty-seven, and a run that cannot read writes an explicit failure with no coverage figures at all. Absence cannot be defaulted into a good number; zero can.
- The accidental record contained raw visitor IP addresses. Kept verbatim where the original already sits; leaving the machine requires redaction settled first, and that redaction is not a one-line filter.
- "We'll pull the logs" and "the provider keeps backups" are both plans with an unverified dependency. Verify it on a quiet day.
We publish this one because it is a near-miss, not a disaster: the record was there when we reached for it, by luck, and luck is not a retention policy. The measurement in the previous article rests on these twenty-one files. Now it rests on a copy we hold, with a checksum, and a job that notices if the next month never arrives.
Not sure what your own hosting actually keeps?
We design and build AI and IT systems for SMBs — privacy-first, no vendor lock-in, and every claim we make about them is one we can show you the measurement for.
Let's talk →