In May we stopped renting analytics and started hosting our own. Ten days later, our own analytics took every one of our sites down. Both halves of that sentence are in this piece, because the second one is the more useful.
Why we left
We had been paying a privacy-respecting analytics vendor since March. In May it stopped recording traffic across all of our properties. Two rounds of fixes on our side changed nothing, and the vendor's support confirmed the problem was on our end without being able to say what it was. We were paying for a black box that had gone dark.
The decision was simple. Stop renting a black box. Run analytics ourselves, on software we can read, storing data we own, with no Google anywhere in it. On May 20 we deployed a self-hosted instance and switched all twelve properties over in a day, verified one by one. The analytics identity for each publication became a column on its record, like everything else: set the column, and the site starts counting; leave it empty, and it does not.
That last detail is the design principle again. No identifiers hard-coded into the site. The database says which publication counts what.
What happened next
On May 30, at about nine in the evening, every public page on all twelve publications began returning an error. Not one site. All of them, at once.
The cause was our own analytics. To save money, we had put it in the same database as the sites, in its own compartment with its own login. That gave it separate data. It did not give it separate connections. A database has a fixed number of connections it will accept, ours allowed sixty, and the analytics software, which starts a fresh copy of itself for every burst of traffic and had no limit set, opened as many as it liked whenever visits arrived from twelve sites at once. It used up every slot. The sites could not get a connection to load a page. Everything returned an error until the connections were cleared.
The lesson is precise and I want to state it precisely: separating the data is not the same as separating the machine. Two systems in one database share its capacity no matter how cleanly their tables are divided.
The fix, and the rule
The analytics moved to its own database project the same night, with hard caps on how many connections it may open, and it has stayed there. The rule that came out of it is now written where every future decision has to read it: no service shares the sites' connection budget. Anything that talks to a database directly gets its own.
The costs were real. Every site was down until the stuck connections were cleared. But the alternative, leaving analytics in someone else's black box, had already failed quietly, for how long we still do not know, and quiet failure is worse. We would rather have a loud outage we can diagnose than a silent one we cannot.
What we have now
Every publication's traffic on a dashboard we own, reading data we hold, at a small fraction of what the vendor charged. No cookie banner, because there is no cookie. No reader is profiled. When a partner asks how a piece performed, we can answer from our own numbers and show our work.
That is what owning the stack means on a good day. The outage is what it means on a bad one. I am comfortable with both.
This is No. 06 in We Built Our Own. Previous: The newsroom tool we built for ourselves. Next: Every article carries its receipts.
