Nothing happens off the record.
More and more of LayerKick runs while I'm not watching every step: agents I've queued, the edge serving, invalidations firing. So all of it reports to one place. Every operation of consequence emits a durable event, a handful of health checks speak up when something breaks, and when I want the full story I query the record instead of guessing.
By June, a good part of what LayerKick does runs while I’m not watching it happen. I line up a batch of work for the coding agents before bed, and some of it is done and waiting when I wake up. The edge serves and re-warms pages on its own. A price change fires an invalidation and a cache purge before I’ve read the email telling me it happened. I’m still in the loop for most of it, but the loop has stretched wide enough that I can’t watch every step. That’s the whole point of building it this way, and it creates a new problem: if I’m not watching, how do I know what happened?
The answer I settled on is that everything reports to one place. Every operation of consequence, a deploy, a cache cutover, an invalidation run, a serve that fell through to Shopify, an agent command, emits a single structured event to one store. I don’t tail logs and I don’t sit in front of dashboards. I query the record when I have a question, and it speaks up on its own when something actually needs me.
Nothing runs without a receipt
Each of those events is one rich record per unit of work rather than a scatter of log lines, a shape that Stripe’s canonical log lines and Honeycomb’s wide events have both preached for years, and one I dig into properly in its own entry. Here the shape is beside the point. What matters is the rule it enforces: nothing of consequence runs without leaving a record.
Every operational command in the repo emits a cli.invoke event, made durable for anything that
touches production, so “who ran what, and when” is a query, not an archaeology dig. Every serve
records the tier that answered it. Every invalidation writes a verdict. The system keeps its own
logbook, and my job is mostly to read it. Deciding this up front means it isn’t extra work per
feature; it’s a house rule: a new operation isn’t done until it reports itself the way every other
one does.
No feed, on purpose
There’s no activity feed I scroll on my phone in the morning, and I decided early not to build one, because a feed is one more thing you have to remember to check. So the deal is inverted: a small set of health checks watch the parts that would actually hurt if they broke, and if one trips, it comes to me. Most mornings the signal is the absence of a signal. A quiet phone means the overnight run was uneventful, which is most nights.
Knowing nothing broke, though, isn’t the same as knowing what happened. When I do want the full account of a night, no dashboard narrates it back to me. I sit down and query the record for the window I care about, which is the next thing.
Query, don’t guess
The rule taped over the whole codebase is evidence before code, and this is that rule pointed at operations. When something looks off, the first move is never to open the source and start theorizing. It’s to query the events and read what actually happened, with the real ids and timestamps in hand.
Here’s roughly what one record looks like. The exact fields aren’t the point, the shape is:
{
"kind": "serve",
"at": "2026-06-02T03:14:22Z",
"store": "northwind-supply",
"path": "/products/roasted-oat-granola",
"market": "US",
"served_by": "edge-cache",
"outcome": "hit",
"total_ms": 9,
"events": [
{ "t": 0.0, "step": "request-received" },
{ "t": 0.4, "step": "pageset-checked", "member": true },
{ "t": 1.3, "step": "cache-looked-up", "result": "hit", "age_s": 740 },
{ "t": 8.6, "step": "response-sent", "bytes": 48213 }
],
"ok": true
}
The events list inside it is what earns the design: a small timeline of everything that happened
during that one unit of work, in order, so I read a single row instead of stitching a story back
together from ten scattered log lines. And one record carries enough context, the store, the path,
the market, the tier, the timing, the outcome, that most questions get answered by filtering what I
already have, not by adding new logging and waiting for the problem to recur. The times I’ve been
burned here were almost always the times I reasoned forward from a hunch instead of reading the row.
The part that matters most for trusting a system I’m not watching: when a step throws, the record
doesn’t vanish. It’s flushed in whatever state it had reached, the error attached and its events
list ending exactly where things went wrong, so a broken run leaves a receipt instead of a hole.
{
"kind": "serve",
"store": "northwind-supply",
"path": "/products/roasted-oat-granola",
"outcome": "error",
"ok": false,
"events": [
{ "t": 0.0, "step": "request-received" },
{ "t": 0.4, "step": "pageset-checked", "member": true },
{ "t": 1.3, "step": "cache-looked-up", "result": "miss" },
{ "t": 42.0, "step": "origin-fetch", "error": "upstream timeout" }
]
}
That last habit I lifted straight from canonical log lines, which are hardened to emit even when the request is busy falling over. It means the worst nights, the ones I’d most want to reconstruct, are the ones best documented.
It speaks up on its own
And I don’t have to remember to look. The pieces that matter announce themselves. An A/B test emails me, once, the first time it reaches significance. A store whose numbers drift past a threshold raises a flag. The default is silence, and that’s the design: a system that’s healthy stays quiet, so the moment it stops being quiet, it has my full attention.
Management by exception is the only way one person keeps pace with a system this automated. I can’t scale my attention to match the agents’ throughput or the edge’s request volume, and I shouldn’t try. What I can do is make sure the small number of things that genuinely need a human find me, and that everything else is sitting in the record for whenever I want to go look.
Why this is load-bearing for a company of one
None of this makes the product more capable. It makes it legible, which for a company of one is nearly the same thing. I can be away from the system precisely because I can reconstruct anything it did while I was gone. The autonomy I’ve written about in the other entries, agents that build without me, an edge that serves without me, only feels safe because none of it is invisible. The lights are off on the factory floor, but the whole floor is wired.
The next entries turn these same instruments outward: onto the serving path itself, one request at a time, and onto our own performance claims, which get held to exactly the standard everything else in here does.
LayerKick layers onto your existing Shopify theme and serves it from Cloudflare's edge. If anything goes wrong, traffic passes through to Shopify like we were never there. The fastest way to understand it is to watch it run on your own storefront, and the waitlist is the way in.