<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://lord.technology/feed.xml" rel="self" type="application/atom+xml" /><link href="https://lord.technology/" rel="alternate" type="text/html" /><updated>2026-09-11T18:56:23+01:00</updated><id>https://lord.technology/feed.xml</id><title type="html">Jamie Lord</title><subtitle>Jamie Lord is a Solution Architect at CDS, building multi-tenant SaaS applications with C#, Cloudflare, Azure and AWS.</subtitle><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><entry><title type="html">Limiting AI news would hide what is happening to software</title><link href="https://lord.technology/2026/09/11/ai-is-not-crowding-out-hacking.html" rel="alternate" type="text/html" title="Limiting AI news would hide what is happening to software" /><published>2026-09-11T16:45:00+01:00</published><updated>2026-09-11T16:45:00+01:00</updated><id>https://lord.technology/2026/09/11/ai-is-not-crowding-out-hacking</id><content type="html" xml:base="https://lord.technology/2026/09/11/ai-is-not-crowding-out-hacking.html"><![CDATA[<p>There is an <a href="https://news.ycombinator.com/item?id=49657850">Ask HN thread on the front page today</a> asking whether Hacker News can “please limit the AI news flood”. To be fair to its author, this is not a request to ban AI. The complaint is that AI stories take up so much of the front page that interesting hardware, open-source projects and ordinary programming work never escape the <code class="language-plaintext highlighter-rouge">newest</code> page. Attention is finite; one story surfacing means another one does not. Could Hacker News put its thumb on the scale and make room for the rest of technology again?</p>

<p>There is too much bad writing about AI. Every minor model release arrives with a benchmark selected by its maker, a launch post declaring a new era and fifty people reporting that it either replaced their engineering department before lunch or failed to count the letters in <em>strawberry</em>. The same three arguments consume the comments. I would happily read less of it.</p>

<p>Limiting AI stories is still the wrong fix.</p>

<p>AI is not a specialist interest taking attention away from software development. It is changing how software is made, what one developer can build, what users expect and which attacks our systems must survive. You do not need to believe in AGI, enjoy generated prose or want a chatbot in your toaster to recognise that. You only need to have used the tools seriously, or to employ somebody who has.</p>

<p>The flood is irritating because the change is large, uneven and happening in public. Filtering it out would produce a tidier front page and a worse account of the world.</p>

<h2 id="the-category-has-already-broken">The category has already broken</h2>

<p>The proposal assumes that “AI news” is a category like photography, databases or laptop cooling: useful to people who follow it, safely removable for everyone else. That category no longer holds.</p>

<p>A vulnerability found by an agent is security news. A browser redesigned around an agent is browser news. A chip built for inference is hardware news. A change in how a developer turns a requirement into running software is programming news. Which of these should be moved into the AI section so that technology can return?</p>

<p>The problem becomes more obvious in the thread’s own replies. People build AI classifiers to remove AI stories. Someone uses Gemini to repair a brittle regular expression intended to hide mentions of Gemini. A commenter objects that AI projects are not really DIY because they are “ways of getting something else to do it for you”, while another points out that this would also make a 3D printer rather suspect. The boundary keeps collapsing because the tool is no longer sitting beside the work. It is entering the way the work gets done.</p>

<p>The comparison with previous Hacker News obsessions only gets us so far. HN has been full of cryptocurrency, Rust, JavaScript frameworks, self-driving cars, SaaS and Apple launches before. Those subjects rose and fell. AI may also be overfunded and overreported, but unlike cryptocurrency it is a general-purpose input into other technical work. It writes Rust, operates browsers, searches codebases and triages support queues. Its failures now appear inside otherwise ordinary systems. Calling all of that “AI-adjacent” does not define a useful category. It defines most of the adjacency graph.</p>

<p>Asking a technology forum to cap that at ten or twenty per cent would be rather like asking one in 1998 to restrict Internet stories so there was still room for proper computers. It would have removed plenty of rubbish. It would also have hidden the fact that networking was becoming part of what a computer was.</p>

<h2 id="hacker-news-is-not-a-balanced-newspaper">Hacker News is not a balanced newspaper</h2>

<p>There is another assumption underneath the complaint: that the front page ought to represent the whole field in fair proportions. Some hardware, some languages, some operating systems, some small projects, and no one subject allowed to consume the issue.</p>

<p>That would be a perfectly reasonable editorial product. It is not what Hacker News is.</p>

<p>HN’s own <a href="https://news.ycombinator.com/newsguidelines.html">guidelines</a> reduce its subject matter to “anything that gratifies one’s intellectual curiosity”. Its front page is not a syllabus. It records what one particular technical community finds urgent enough to submit, discuss and upvote today, with ranking rules and moderators modifying the result. Sometimes that attention is badly allocated. Popularity is not merit. But a link aggregator that guarantees every beat a share of the page is no longer measuring collective attention; it is publishing a magazine.</p>

<p>The author wants overlooked work to be discoverable, which is reasonable. Reducing the representation of a subject other people currently consider important does not tell us which neglected stories deserve the vacant slots. It only guarantees that some lower-ranked non-AI stories receive them. A quota can manufacture variety. It cannot manufacture interest.</p>

<p>The two examples in the post make this awkward. One is a Lenovo proof of concept using solid-state cooling. The other is a promotional video for a set of devices that are not yet available. Both might be interesting; the cooling system interests me more than another funding round. But neither was necessarily denied a front-page discussion by AI. Commenters offer ordinary reasons for passing over them: scant technical detail, vaporware, a video instead of a substantial write-up, doubts about the company, and the fact that the cooling technology has appeared in products before. Those judgments may be wrong. They are still judgments about the submissions themselves.</p>

<p>“My interesting link did not rise” and “another subject prevented it from rising” are not the same claim. The second needs more evidence than the first.</p>

<h2 id="i-did-not-become-a-developer-to-preserve-typing">I did not become a developer to preserve typing</h2>

<p>One of the thread’s most revealing comments says: “I miss all the programming articles. It feels like everyone has given up with the very idea of ever writing code now.” The commenter sees the practice of making software being handed over to AI.</p>

<p>I understand the loss in that sentence. Programming is a satisfying craft. Holding a problem in your head, reducing it until the right abstraction appears and then making the machine obey is one of the best feelings in the job. I do not want a profession of people who prompt systems they do not understand, accept code they cannot review and call the result engineering. I have written before that <a href="/2026/01/31/what-becomes-expensive-when-code-becomes-cheap.html">code generation became cheap while owning code did not</a>, and that <a href="/2026/07/29/opus-5-gets-things-wrong-more-quietly.html">models can become more dangerous when they get things wrong more quietly</a>.</p>

<p>But I did not become a developer to preserve the act of entering syntax into a text editor. I became one because I like building things for people and solving problems for them. Code is usually the material, sometimes the obstacle, and never the user need.</p>

<p>If programming means producing code, an agent looks like an elaborate machine for taking programming away. If it means turning an ambiguous human need into a system that reliably meets it, an agent removes some implementation cost and leaves the hard part exposed. What is the actual problem? What must never happen? How will we know the answer is right? What will this cost to operate in three years? The model can help with those questions. It cannot be accountable for the answers.</p>

<p>Earlier this year I built <a href="/2026/05/21/the-military-aircraft-tracker-i-built-for-an-audience-of-one.html">a military aircraft tracker for an audience of one</a>. There is no LLM in the running product. I tried one for its daily summaries and removed it because deterministic templates were better. But a coding agent wrote much of the implementation under my direction. That leverage is why an evenings-and-weekends project grew an ingestion pipeline, queues, workflows, anomaly detection, replayable history and a usable interface before the old version would have made it past decoding the feed.</p>

<p>Was that less like hacking because I did not type every queue consumer? I think it was more like hacking. I found an itch, assembled tools, learnt the constraints, discarded AI where it made the product worse and used it heavily where it made the product possible. The important judgment was not loyalty to or rejection of the tool. It was knowing which problem belonged to it.</p>

<p>Blind AI enthusiasts mistake generation for understanding. At the other extreme, some developers have turned a justified dislike of the hype into a refusal to inspect the capability. Neither is especially technical. The job is to evaluate the thing in front of us: use it where it works, contain it where it is unreliable, and remove it where it does not help the user.</p>

<h2 id="slop-is-a-quality-problem-not-a-subject">Slop is a quality problem, not a subject</h2>

<p>The best case for intervention is that AI has made low-effort material extremely cheap to produce, and that material is consuming a system whose scarce resource is human attention. The label “AI story” is a bad way to identify it.</p>

<p>A person can repeat a press release, cherry-pick a benchmark and contribute nothing. A hand-written project can be useless. An AI-assisted one can solve a real problem and contain careful engineering. The production method is not the quality. “Slop” describes the distance between the confidence and volume of an artefact and the thought behind it, not whether a model touched the keyboard.</p>

<p>The thread demonstrates this neatly. Several developers have built sites that filter AI stories out of Hacker News; at least one uses an LLM to classify them. That is not hypocrisy. Fuzzy classification is exactly the sort of bounded, reversible task language models are useful for, and the developer shipped something people in the thread wanted. A filter made with AI to avoid reading about AI is still a product built for users. The user need decides whether it is worthwhile; ideological consistency does not.</p>

<p>Hacker News should be more aggressive about the properties it already cares about: originality, technical substance and intellectual curiosity. A model release that changes nothing, a generated essay with no firsthand evidence and a demo whose only feature is that a model produced it should struggle. So should their human-made equivalents. A careful account of a failed AI deployment or a developer showing exactly how a tool changed their work should survive. So should the cooling system and the open-source wall display, if the submitted material gives readers enough substance to engage with them.</p>

<p>Judge the work by what it reveals. “AI” is too blunt a proxy for that judgment.</p>

<h2 id="the-attention-problem-is-partly-us">The attention problem is partly us</h2>

<p>There is a more uncomfortable reason AI keeps swallowing the front page: even people who hate the subject cannot leave it alone.</p>

<p>They open the story to complain that it is there. They add the hundredth comment saying language models merely predict the next token. They call the project slop without running it, somebody responds with an extravagant claim about AGI, and both sides return for six rounds. A modest post about an unusual cooling system cannot compete with a subject that recruits its supporters and opponents into the same engagement loop.</p>

<p>No ranking change can entirely solve that because the flood is not only a supply problem. It is demand, including hostile demand. The Ask HN thread objecting to too much AI became one of the day’s largest AI discussions within hours. That is funny, but it is also the mechanism.</p>

<p>Personal filters are reasonable. If reading another model announcement makes your day worse, hide it. Use a third-party feed. Read Lobsters. Go directly to Hackaday for hardware. No single front page has ever owed us a complete view of an industry. Choosing several narrower sources is healthier than expecting one community to preserve the mixture of subjects we happened to like when we joined it.</p>

<p>What personal filtering should not become is institutional denial. There is a difference between “I do not want to spend my attention on this today” and “this community should behave as if the subject is less consequential than its members believe”. The first is curation. The second is distortion.</p>

<h2 id="look-harder-not-away">Look harder, not away</h2>

<p>I do not want more AI news merely because it is about AI. I want fewer launch posts, fewer benchmark victory laps, fewer wrappers presented as companies, fewer declarations that software engineering ended last Tuesday and fewer denunciations written by people whose last serious experiment with a coding model was asking it for a sorting function two years ago.</p>

<p>I want more evidence. Show me what the system made possible that was not possible before. Show me where it failed under real load. Show me the review burden, the changed threat model, the bill, the maintenance cost and what the users thought. Show me the code when code is the interesting part and the product when it is not.</p>

<p>Boosterism asks us to lower our standards because the future has arrived. I want higher standards because these systems are being deployed before they are understood, and will affect developers whether or not we enjoy reading about them.</p>

<p>AI is a massive part of development now. It is also full of hype, waste, brittle systems and people selling inevitability because they cannot yet sell a reliable product. Both are true. The answer to a noisy, important change is not to reserve fewer slots for it. It is to get better at distinguishing signal from noise.</p>

<p>Hacker News should make room for deeply interesting work wherever it appears. It should give overlooked submissions a second chance and punish repetitive, shallow material. But it should not decide in advance that the largest change to the practice of building software in decades has received its fair allocation of attention for the day.</p>

<p>I do not need to love AI to know that ignoring it would make me worse at building things for users. Believing everything its vendors say would too. The job is still the same: pay attention, test the claims and build something useful.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="ai" /><category term="hacker-news" /><category term="software-development" /><category term="agentic-engineering" /><summary type="html"><![CDATA[There is an Ask HN thread on the front page today asking whether Hacker News can “please limit the AI news flood”. To be fair to its author, this is not a request to ban AI. The complaint is that AI stories take up so much of the front page that interesting hardware, open-source projects and ordinary programming work never escape the newest page. Attention is finite; one story surfacing means another one does not. Could Hacker News put its thumb on the scale and make room for the rest of technology again?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cloudflare doesn’t have AI psychosis. It has a thesis.</title><link href="https://lord.technology/2026/08/16/cloudflare-doesnt-have-ai-psychosis-it-has-a-thesis.html" rel="alternate" type="text/html" title="Cloudflare doesn’t have AI psychosis. It has a thesis." /><published>2026-08-16T09:00:00+01:00</published><updated>2026-08-16T09:00:00+01:00</updated><id>https://lord.technology/2026/08/16/cloudflare-doesnt-have-ai-psychosis-it-has-a-thesis</id><content type="html" xml:base="https://lord.technology/2026/08/16/cloudflare-doesnt-have-ai-psychosis-it-has-a-thesis.html"><![CDATA[<p>“I am not blaming the innovation. I am blaming the chaos of innovation. Everything feels DISJOINTED.” That’s the author of <a href="https://opensauce.it/cloudflare-ai-psychosis/">“Cloudflare’s AI psychosis”</a>, on <a href="https://news.ycombinator.com/item?id=49310719">Hacker News</a> this weekend, after the essay reached the front page. The essay itself is wider and angrier than that. Cloudflare used to be boring infrastructure run by engineers and is now a product-management organisation with a posting habit; too many overlapping primitives, still no proper Postgres, a developer experience bolted on as an afterthought, observability that never ships, more outages than ever, 1,100 people made redundant under an “agentic” banner. It opens by missing the old company, the one that “sat in front of your site, ate the attacks, cached the static stuff, did the DNS, and that’s it. No BS.” I agree with most of what it lists. I think the diagnosis is wrong, and I want to say why at some length, because the essay is being passed around as if the two were the same thing.</p>

<p>I work for a Cloudflare partner, I build on the Developer Platform most working days, and I <a href="https://architectingoncloudflare.com/">wrote a book about it</a> this year, independent and unendorsed, so discount accordingly. In my defence, the book has a chapter called <a href="https://architectingoncloudflare.com/chapter-24">When Not to Use Cloudflare</a>, and I’ll be quoting it against Cloudflare a few times, because several of the essay’s best points are ones I’d already conceded in print.</p>

<h2 id="the-dashboard-and-the-rest-of-it">The dashboard, and the rest of it</h2>

<p>If “developer experience” means the dashboard, then yes, it’s a mess, and I haven’t opened it in anger for about a year. yodon on the thread called it “the densest collection of UI anti-patterns known to man” and I’m not going to argue. The outage the essay leads with, the <a href="https://blog.cloudflare.com/deep-dive-into-cloudflares-sept-12-dashboard-and-api-outage/">12 September 2025 dashboard and API failure</a>, was the dashboard’s fault: a React <code class="language-plaintext highlighter-rouge">useEffect</code> with an object in its dependency array, recreated on every render, calling the Tenant Service API “many times during a single dashboard render instead of just once” until it fell over. A React hook took the control plane down for over an hour. The postmortem is candid about it.</p>

<p>The developer experience I actually use is a terminal, a config file and a runtime, and I think that part is the best local story of any serverless platform I’ve worked on. <code class="language-plaintext highlighter-rouge">wrangler dev</code> runs your code in <a href="https://github.com/cloudflare/workerd"><code class="language-plaintext highlighter-rouge">workerd</code></a>, built from the same source as the production runtime. To be fair to Lambda, <code class="language-plaintext highlighter-rouge">sam local</code> runs the real Lambda image too; what both simulate is the services around the runtime, and Miniflare’s stand-ins for KV and D1 and R2 and Queues are the vendor’s own and cover more of the platform. What Cloudflare has that Lambda doesn’t is one path: <code class="language-plaintext highlighter-rouge">wrangler deploy</code> is seconds, <code class="language-plaintext highlighter-rouge">wrangler rollback</code> is seconds, and there’s no fast-but-unsafe route sitting next to a slow-but-safe one. What’s left is the gap I spend most of <a href="https://architectingoncloudflare.com/chapter-05#the-simulation-boundary">Chapter 5</a> on: you can simulate the runtime but you cannot simulate the network. Local D1 answers in microseconds and production D1 in tens of milliseconds, and that difference causes more works-on-my-machine bugs on this platform than anything else. You can’t fix it in Wrangler.</p>

<p>Look at where the money went this year. In April Cloudflare started <a href="https://blog.cloudflare.com/cf-cli-local-explorer/">rebuilding the CLI</a> as <code class="language-plaintext highlighter-rouge">cf</code>, generated from one schema across nearly three thousand API operations. In June it <a href="https://www.cloudflare.com/press/press-releases/2026/cloudflare-acquires-voidzero-to-build-the-future-of-the-ai-native-web/">bought VoidZero</a>, Evan You’s company, the people behind Vite and Vitest, and You’s <a href="https://blog.cloudflare.com/voidzero-joins-cloudflare/">own post</a> says what for: “<code class="language-plaintext highlighter-rouge">cf dev</code> should be a superset of <code class="language-plaintext highlighter-rouge">vite dev</code>”. An acquisition is also an announcement, yes. It’s also a large cheque and a team, and you don’t spend either on an afterthought.</p>

<h2 id="one-animal-different-coats">One animal, different coats</h2>

<p>The essay’s central exhibit is storage. D1, Durable Object SQLite, KV, R2, Queues, Hyperdrive: “too many ways to do the same thing, none of them great”. They aren’t the same thing. Map them and you get a SQLite, an eventually consistent cache, an S3, an SQS and a connection pooler, and nobody calls AWS disjointed for having RDS, ElastiCache, S3, SQS and RDS Proxy. Hyperdrive is a marketing name, granted. So is Lambda. Cloudflare doesn’t have fewer products because it’s tidier; it has fewer because it offers less, no VMs, no Kubernetes, no GPUs by the hour. What it does have is one programming model. Four general-purpose ways to run code, on two substrates, V8 isolates and Linux containers, and everything that isn’t an isolate is fronted by a Durable Object, configured in the same file, deployed by the same command, reached through the same bindings. A Durable Object is a Worker with state. A Container is a Durable Object with a bigger body. A Dynamic Worker is a Worker whose code another Worker hands it at request time. D1 is a Durable Object you didn’t have to build. If you know what a Worker is, the rest isn’t a zoo. It’s one animal in different coats. The book calls it <a href="https://architectingoncloudflare.com/chapter-01#primitives-over-managed-services">unbundling</a> and is blunt about the cost: derived data needs explicit code, you build your auth instead of configuring it, and the first week feels like being handed a bag of parts. You might not want that trade. But it’s a design, not a symptom, and it’s been the design since KV in 2018.</p>

<p>The compute side is where the essay has a point. There is no single page that puts Workers, Dynamic Workers, Sandboxes and Containers next to each other and tells you which to reach for; I looked. That’s a real documentation failure, and Cloudflare more or less admitted it on 3 August by shipping <a href="https://blog.cloudflare.com/cloudflare-computer/"><code class="language-plaintext highlighter-rouge">@cloudflare/computer</code></a>, which hands the model a single <code class="language-plaintext highlighter-rouge">exec</code> tool and lets it choose between a shell inside an isolate and a real container, so that you don’t have to. That is exactly the pattern the essay is complaining about. Look at who wrote the newest layer, though. Dynamic Workers and Code Mode came out of a <a href="https://blog.cloudflare.com/code-mode/">September 2025 post</a> by Kenton Varda and Sunil Pai; Varda designed the Workers runtime and is the one engineer the essay names approvingly. If product managers have taken the pen from the infrastructure engineers, it’s odd that the infrastructure engineer keeps writing the new things.</p>

<h2 id="the-database">The database</h2>

<p>The Postgres point is the strongest one in the essay, and it’s true. There is no first-class Cloudflare-run PostgreSQL. I said so in <a href="https://architectingoncloudflare.com/chapter-12#the-decision-d1-hyperdrive-or-something-else">Chapter 12</a>: “A native serverless PostgreSQL offering would fill an obvious gap.” The closest thing is PlanetScale. In April Cloudflare <a href="https://blog.cloudflare.com/deploy-planetscale-postgres-with-workers/">wired PlanetScale Postgres into Workers</a> through Hyperdrive, and since <a href="https://developers.cloudflare.com/changelog/post/2026-06-18-planetscale-databases-cloudflare-billing/">18 June</a> you can create one from the Cloudflare dashboard and it lands on your Cloudflare invoice at PlanetScale’s prices. You get Cloudflare billing and Cloudflare wiring; the database is still a PlanetScale database in a PlanetScale region.</p>

<p>The essay reads Hyperdrive as an admission that Cloudflare never built the database serious apps want. I read it differently. A managed Postgres is the one product that would contradict the platform’s own architecture, and they haven’t built it. Varda, <a href="https://blog.cloudflare.com/sqlite-in-durable-objects/">announcing SQLite in Durable Objects</a> in 2024: “Traditional cloud architecture favors large distributed databases that live separately from application servers.” In <a href="https://blog.cloudflare.com/introducing-workers-durable-objects/">2020</a>, Durable Objects were “the missing piece in the Workers stack that makes it possible for whole applications to run entirely on the edge, with no centralized ‘origin’ server at all.” A managed Postgres in one region is an origin, and the platform was founded on the idea that the origin is the problem. I’ve overstated that idea myself. For most SaaS the origin isn’t the problem; the origin is where the customers are, users cluster in one to three regions, reads dominate, and a replica handles the read path. Hyperdrive is a pooler and a read cache in three hundred cities. It pays the connection handshakes once; every query still crosses the ocean, writes always do, and the cache is time-based, so the fast reads are the ones that might be stale. What it buys is that a Worker at the edge talks to a regional Postgres at roughly the cost a regional Lambda would, so the work that belongs at the edge can happen before or instead of the query. In the book I call that <a href="https://architectingoncloudflare.com/chapter-14#hyperdrive-as-architecture-not-just-bridge">a permanent architecture rather than a bridge</a>, and I still think that, but it’s a claim about the topology being reasonable, not about latency going away.</p>

<p>The real difference isn’t that Cloudflare distributes data and the hyperscalers don’t. Aurora Global Database, DynamoDB Global Tables and DSQL distribute data fine, across a few dozen regions, by configuration. Cloudflare partitions it by key and moves the code to the partition, per object, across a few hundred cities. A Durable Object is a single writer in a single place with its SQLite in the same thread as the code, wonderful for a chat room or a per-user agent and useless for an ad-hoc join across tenants. D1 has an origin too, a primary in one location with read replicas behind it. So it depends what you mean by Postgres. If you mean SQL, you get D1, fifty thousand databases by default, one per tenant, 10 GB each, and you pay for that in fleet migrations and cross-tenant reporting you write yourself. If you mean Postgres, the extensions and pgvector and twenty years of tooling, you keep it where it lives and put Hyperdrive in front. Neither is the “first-class managed PostgreSQL that feels native” the essay asks for, and the <a href="https://architectingoncloudflare.com/chapter-24#red-flags-when-to-look-elsewhere">red flags</a> chapter says plainly that if your data model assumes a single large database you should use Hyperdrive or go somewhere else, because “Cloudflare isn’t a general-purpose cloud. It’s a specific bet on a specific model.”</p>

<p>Here’s the awkward part. I’d bet on a Cloudflare-run Postgres arriving. They bought <a href="https://blog.cloudflare.com/cloudflare-acquires-outerbase-database-dx/">Outerbase</a> for the database experience, they put PlanetScale on the invoice, and it isn’t hard to see where that goes. That’s a guess from the public record; every source is linked and I have no inside knowledge. You can’t believe both that “no origin” is doctrine and that they’re about to ship one, so one of those is posture, and I think it’s the first. “No origin” was a preference the platform could hold while partners met the demand, and PlanetScale on the Cloudflare invoice is that preference already bending. If they build their own, the essay gets to say it told me so. I don’t think it’ll look like RDS when it comes; I think it’ll be many small ones near the code, because that’s the bet, and the bet is what you’re buying when you buy Cloudflare. And if “feels native” means what I think it means, that’s the database the essay is asking for as well. We want the same thing. Where we differ is whether not having it yet means the company has lost its mind.</p>

<p>Ryan Dahl, who is building a competitor to it, shipped <a href="https://celld.dev/">celld</a> this week, a self-hosted Durable Objects clone on S3, and called the model “one of the best primitives distributed systems has been handed in years”. That cuts against me too: the primitive is right and Cloudflare’s terms for it, the price and the lock-in, are what people actually object to. That’s the argument I’d rather be having. It’s a better one than psychosis.</p>

<h2 id="0x-with-an-operating-system-on-top">0.x with an operating system on top</h2>

<p>The agents section lists Agents SDK, Flue, Project Think and Cloudflare OS as “another harness or framework instead of finishing the one they already have”. Cloudflare’s own <a href="https://blog.cloudflare.com/agents-platform-flue-sdk/">Flue announcement</a> sets out the layering: Flue is a framework, Project Think and Pi are harnesses, “the agentic loop”, and the Agents SDK is “the compute, state, and storage primitives everything above depends on”. Flue came from the Astro team, who <a href="https://astro.build/blog/joining-cloudflare/">joined Cloudflare</a> in January; it grew out of the <a href="https://blog.cloudflare.com/astro-issue-triage/">triage pipeline</a> that took Astro’s own open issues from over two hundred to about thirty. Cloudflare OS, which I spent <a href="https://lord.technology/2026/08/05/cloudflare-os-is-an-architecture-of-distrust.html">last week reading</a>, is an application built on all of that. One runtime with things stacked on it, not four harnesses. None of that answers the actual complaint, though. The SDK everything depends on is still on version 0.x eighteen months after launch. Think is labelled experimental. The SDK, the Agents dashboard that arrived on 4 August, and Agents Week, which has now happened twice this year, all share a name. A tidy diagram doesn’t make the base reliable, and I’d rather have a 1.0 of the SDK than another thing on top of it. That part of the essay is right.</p>

<p>Some of the rest was out of date by the time it was published. AI Search “lags proper RAG platforms … on quality, filtering, hybrid search”: <a href="https://developers.cloudflare.com/ai-search/configuration/indexing/hybrid-search/">hybrid search</a> shipped on 16 April, <a href="https://developers.cloudflare.com/changelog/post/2026-03-23-custom-metadata-filtering/">custom metadata filtering</a> on 23 March, reranking last October. What’s left is five metadata fields, one reranker, and a product still in open beta with billing <a href="https://blog.cloudflare.com/ai-search-easier/">not switched on</a> a year and a half in, which makes it an unpriced dependency; I’d keep it out of the critical path until it has a price. The docs ship without “even basic SKILL.md stuff for agents”: the <a href="https://github.com/cloudflare/skills">cloudflare/skills</a> repository has been up since December, next to an <a href="https://developers.cloudflare.com/llms.txt">llms.txt</a> and a docs MCP server from May 2025. The docs complaint that does stick is the Matrix post. In January a Cloudflare TPM published a <a href="https://www.thestack.technology/cloudflare-matrix-blog-ai-assisted-vibe-coding/">personal project</a> on the company blog as a “serverless, post-quantum Matrix homeserver”, and Matrix developers found the signature checks were <code class="language-plaintext highlighter-rouge">TODO</code>s and the README said production-grade; <a href="https://matrix.org/blog/2026/01/28/matrix-on-cloudflare-workers/">Matthew Hodgson</a>: “the code doesn’t yet implement any of Matrix’s core features which allow you to federate safely, and so doesn’t yet constitute a functional Matrix server”. Cloudflare added a proof-of-concept note the same day. That’s embarrassing for the blog, and the tracing docs carried a billing start date that had already passed for months, so docs rot is a fair charge, and so is the narrower one that new products arrive without versioned reference material. Docs-for-agents being absent isn’t. Workers AI does trail on speed: when I checked on 15 August, <a href="https://artificialanalysis.ai/models/kimi-k2-6/providers">Artificial Analysis</a> had Cloudflare well behind Fireworks and Baseten on throughput for Kimi K2.6, and the book says flatly that these aren’t the best models available and that edge inference “optimises the rounding error”. But the essay’s line that this forces “a lot of teams to send the hard inference somewhere else and treat Cloudflare as plumbing again” is meant as a dig, and it’s what the product is for. On the day the essay was published, Cloudflare <a href="https://blog.cloudflare.com/workers-ai-gateway-unification/">merged Workers AI into AI Gateway</a>: one wallet, spend it on OpenAI or Anthropic or their own GPUs, <a href="https://developers.cloudflare.com/ai-gateway/features/unified-billing/">five per cent on top</a>. Running an agent on Cloudflare means holding its state, sandboxing its code and surviving its restarts. It has never meant running the frontier model.</p>

<h2 id="where-the-essay-is-right">Where the essay is right</h2>

<p>Observability. Workers tracing has carried a beta badge since <a href="https://blog.cloudflare.com/workers-tracing-now-in-open-beta/">October 2025</a>, and the <a href="https://developers.cloudflare.com/workers/observability/traces/known-limitations/">known limitations page</a> says the three things the essay says: some spans report zero milliseconds because the runtime doesn’t advance the clock between I/O events, a Spectre mitigation; trace IDs “are not propagated to services outside of Cloudflare”; span attributes are incomplete. Cross-binding propagation was fixed in May, custom spans in June, local tracing this month, so it’s moving, but ten months is a long open beta for the thing you use to find out why production is broken. <a href="https://architectingoncloudflare.com/chapter-20#hyperscaler-comparison">Chapter 20</a> says the same as the essay in politer language, “where Cloudflare still trails is full APM instrumentation”, which spelled out means no service map, no SLO objects, no alarms on custom dimensions without building them yourself, so what you’d actually compare is Cloudflare plus Honeycomb or Datadog against CloudWatch and X-Ray on their own. If you’re on Workers and reading this to decide whether to leave: don’t, but stop waiting for the beta badges to come off and ship your traces out through the OTLP export now. The 1% sampling bug on paid accounts the essay cites I couldn’t verify either way, because the source is behind a bot wall. The community thread I could read, an account on what looks like the Free plan whose <a href="https://community.cloudflare.com/t/workers-observability-logs-most-logs-not-appearing-in-dashboard-since-march-10/904412">logs vanished from the dashboard</a> in March while <code class="language-plaintext highlighter-rouge">wrangler tail</code> kept showing them, has zero replies. Zero. That’s the bit that stings, and it isn’t unrelated to what happened in May.</p>

<p>The volunteer Community Champions <a href="https://shoftech.com/question/cloudflare-community-champions-update/">said in May</a> that Cloudflare had let go of many of its community team, that they’d lost their contacts inside the company, and that the programme was dissolved without a clear reason. Cloudflare hasn’t said so itself, but the replacement, announced the same day as the essay, <a href="https://blog.cloudflare.com/community-program-refresh/">says of itself</a> that it is “not about being on hand to perform moderation and admin tasks” because they’re building automation to do that “with far less human intervention”. An unanswered thread is what that looks like from the outside. That one made me angry, and I don’t get angry at Cloudflare much.</p>

<p>And the redundancies are real. More than 1,100 people on 7 May, about a fifth of the company. The <a href="https://www.sec.gov/Archives/edgar/data/1477333/000147733326000033/cloud-20260507.htm">8-K</a> calls it a plan “to further accelerate its evolution to an agentic AI-first operating model”. That phrase is Cloudflare’s, not the essay’s. It’s grim. Matthew Prince’s defence in <a href="https://fortune.com/2026/05/21/cloudflare-ceo-matthew-prince-layoffs-ai-automation-measurers/">Fortune</a> was that “the vast majority of those we laid off last week were measurers”, his word for middle management, finance, legal and audit. I have no way to know whether that’s true, and neither does the essay. What I can check is the talent-drain claim, and it’s one name: Kate Reznykova, an engineering manager on the Agents and Sandboxes team, <a href="https://www.sdxcentral.com/news/openai-strengthens-web-infrastructure-team-with-cloudflare-hire/">went to OpenAI</a> in July, the one departure the essay could actually have cited. I couldn’t find anyone who went to Anthropic. Varda is still there and shipped Dynamic Workers and Cloudflare OS this year. The stock fell 24% the next day, on the same call as the earnings, so whatever the cuts were for, the market didn’t read them as a gift.</p>

<h2 id="what-fell-over">What fell over</h2>

<p>On reliability I have to be careful, because the essay’s own line is that “the core network, reliability, and simplicity that made Cloudflare different get less consistent attention”, and the two big outages of 2025 were in the core network. So the essay gets to say the boring layer fell over. It did. On <a href="https://blog.cloudflare.com/18-november-2025-outage/">18 November</a> a ClickHouse permissions change made the Bot Management feature file more than double in size, past a hard-coded limit, and the Rust proxy hit an <code class="language-plaintext highlighter-rouge">unwrap()</code> and panicked across the network for about three hours; Prince called it “Cloudflare’s worst outage since 2019” and apologised “for the pain we caused the Internet”. On <a href="https://blog.cloudflare.com/5-december-2025-outage/">5 December</a> a WAF change tripped a global kill switch and the older Lua proxy threw a nil error for 25 minutes across 28% of HTTP traffic. Their own words: “how closely they are clustered together” is “not acceptable for a network like ours”. No argument from me. The same autumn took out us-east-1 for about fifteen hours and Azure Front Door for about eight, both from automated configuration changes with too little staging, so the boring cloud that doesn’t fall over isn’t on offer anywhere. The difference, and it’s the essay’s strongest card, is that those were regional. Cloudflare’s are global by design.</p>

<p>The cause is where I disagree. Neither November nor December was a new failure mode that arrived with the AI products. They were the same class as Cloudflare’s oldest one: something propagated to every machine on earth in seconds, with no staged rollout, and a proxy that fell over hard on the result. That’s how the <a href="https://blog.cloudflare.com/details-of-the-cloudflare-outage-on-july-2-2019/">July 2019 outage</a> happened, a bad WAF regex pushed globally, in the boring era the essay misses, and that postmortem names the gap in one sentence: “The SOP for a rule change specifically allows it to be pushed globally. This is very different from all the software we release at Cloudflare”. Cloudflare’s own Fail Small post says of the 2025 pair that “both outages followed a similar pattern. In the moments leading up to each incident we instantaneously deployed a configuration change in our data centers in hundreds of cities around the world.” They promised staged rollouts for WAF rules in 2019. Nobody widened the promise to feature files and kill switches until it hurt. It’s the failure mode I warn readers about in <a href="https://architectingoncloudflare.com/chapter-02#the-global-blast-radius">Chapter 2</a>: the property that makes a global deploy valuable is the property that makes a global mistake instant. If attention drifted, and I think the clustering says it did, it drifted from a discipline the company had already learned once, in one place, and had to relearn everywhere.</p>

<p>And relearn it they did, in the least exciting engineering Cloudflare has published in years. <a href="https://blog.cloudflare.com/fail-small-resilience-plan/">Code Orange: Fail Small</a> in December committed to “controlled rollouts for any configuration change that is propagated to the network, just like we do today for software binary releases”, which is the 2019 sentence with the fix applied, and the <a href="https://blog.cloudflare.com/code-orange-fail-small-complete/">completion post</a> on 1 May reports health-mediated config rollout on most production systems, a break-glass drill with over two hundred people, and a Rust rule that reads, in full, “Do not use <code class="language-plaintext highlighter-rouge">.unwrap()</code> outside of tests and <code class="language-plaintext highlighter-rouge">build.rs</code>.” Companies optimising for announcement cadence don’t publish that rule, and if you want the writing about hard trade-offs that the essay says Cloudflare no longer does, the postmortems are it. That’s a company that got frightened in November and spent the winter on rollout discipline. Whether it stays frightened I can’t tell from the public record.</p>

<p>I’ve now spent a chapter and three thousand words explaining why the missing Postgres is doctrine. I’d still like the database.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="cloudflare" /><category term="cloudflare" /><category term="architecture" /><category term="workers" /><category term="agents" /><summary type="html"><![CDATA[“I am not blaming the innovation. I am blaming the chaos of innovation. Everything feels DISJOINTED.” That’s the author of “Cloudflare’s AI psychosis”, on Hacker News this weekend, after the essay reached the front page. The essay itself is wider and angrier than that. Cloudflare used to be boring infrastructure run by engineers and is now a product-management organisation with a posting habit; too many overlapping primitives, still no proper Postgres, a developer experience bolted on as an afterthought, observability that never ships, more outages than ever, 1,100 people made redundant under an “agentic” banner. It opens by missing the old company, the one that “sat in front of your site, ate the attacks, cached the static stuff, did the DNS, and that’s it. No BS.” I agree with most of what it lists. I think the diagnosis is wrong, and I want to say why at some length, because the essay is being passed around as if the two were the same thing.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cloudflare OS is an architecture of distrust</title><link href="https://lord.technology/2026/08/05/cloudflare-os-is-an-architecture-of-distrust.html" rel="alternate" type="text/html" title="Cloudflare OS is an architecture of distrust" /><published>2026-08-05T21:00:00+01:00</published><updated>2026-08-05T21:00:00+01:00</updated><id>https://lord.technology/2026/08/05/cloudflare-os-is-an-architecture-of-distrust</id><content type="html" xml:base="https://lord.technology/2026/08/05/cloudflare-os-is-an-architecture-of-distrust.html"><![CDATA[<p>The strangest thing in the <a href="https://github.com/cloudflare/cloudflare-os">Cloudflare OS source code</a> took me a while to understand.</p>

<p>When an agent inside Cloudflare OS wants to do something with a side effect (merge a pull request, send an email, write a row to a system of record), it goes through a Gatekeeper, a small service that holds the credential and mediates the action. So far, that’s just a well-built MCP server. But read the contract a Gatekeeper is written against (<code class="language-plaintext highlighter-rouge">packages/workshop-shared/src/gatekeeper.ts</code>, <a href="https://github.com/cloudflare/cloudflare-os/blob/e1ab8fbd4f609aff7ede9d490bafe1bcf9b2a682/packages/workshop-shared/src/gatekeeper.ts#L617">around line 617</a>) and you find this instruction to the author:</p>

<blockquote>
  <p>It is suggested that the gatekeeper “simulate” actions that have not been approved yet, that is, the <code class="language-plaintext highlighter-rouge">Session</code> interface should reflect the state of the resource as if all actions had been applied.</p>
</blockquote>

<p>Sit with that. The agent asks to merge the PR. The human hasn’t approved it. So the Gatekeeper tells the agent the PR is merged, and if the agent reads the branch back to check its work, hands it a fabricated reality in which the merge happened. The agent, satisfied, queues the next three steps that depend on it. None of it is real. Later a human looks at the batch and either commits it or bins it, and if they bin it, everything the agent built on the fiction goes too.</p>

<p>The first time I traced this I thought it was a hack. It’s the philosophy of the whole system, compressed into one method signature. The Gatekeeper lies to the agent on purpose, because the alternative (letting an agent’s actions touch the world the moment it decides to take them) assumes the agent’s decisions are sound. Cloudflare OS is built from end to end on the assumption that they are not.</p>

<p>The name is a distraction, so set it aside. The Hacker News thread spent most of its energy arguing about whether “OS” is a permitted word for the thing, and that’s a dead end. What’s actually interesting is that a team led by Kenton Varda, the people who built the Workers runtime, sat down to design a platform for AI agents doing real work inside a company, and the organising principle they landed on was this: the agent cannot be trusted, so build so that its mistakes cannot matter. Every load-bearing part of the system is a variation on that sentence.</p>

<p>Last week I <a href="https://lord.technology/2026/07/29/opus-5-gets-things-wrong-more-quietly.html">wrote about Opus 5</a> getting things confidently, quietly wrong: shipping a change that reported success while doing the opposite, caught only on a second pass. This is what it looks like to take that failure mode not as a grievance but as a permanent design constraint, and pour concrete on top of it.</p>

<h2 id="make-the-code-irrelevant-to-safety">Make the code irrelevant to safety</h2>

<p>Start with the sandbox, because everything else stands on it.</p>

<p>When you make a slide deck in Cloudflare OS, you aren’t using one shared slide-deck app. The system spins up a private instance of the slide-deck code, a “gadget”, that belongs only to you. It runs in its own Dynamic Worker, with its own SQLite database behind a Durable Object Facet, outbound networking switched off. Every document is its own sandboxed process.</p>

<p>This is Sandstorm, Kenton’s startup from a decade ago, reborn. What Sandstorm got right and could never make cheap was fine-grained instancing: every document in its own isolation boundary. Containers made that far too expensive, seconds of cold start and hundreds of megabytes per grain, so the idea sat on a shelf for ten years until V8 isolates made it roughly a hundred times cheaper to run. I wrote <a href="https://architectingoncloudflare.com/">a book about this platform</a> and called Durable Objects its most underappreciated primitive; the thing they were waiting to enable, it turns out, was this.</p>

<p>Per-document instancing changes where security lives. For twenty-five years the boundary in multi-tenant SaaS has run straight through the application code. One shared service holds everyone’s data, and a single mistake in a <code class="language-plaintext highlighter-rouge">WHERE</code> clause, one missing <code class="language-plaintext highlighter-rouge">tenant_id</code>, leaks customer B’s records to customer A. The code is load-bearing for security. It has to be correct, and a junior engineer’s off-day is a breach.</p>

<p>Cloudflare OS moves the boundary out of the code and into the platform. If every user has their own instance, and the platform controls who can reach an instance at all, a bug in the gadget can only hurt the one person who owns it. Kenton puts it flatly: the AI cannot introduce a significant security bug. He’s right, in the sense that matters. A gadget can’t leak to another user however badly it’s written, because there is no other user in its sandbox to leak to.</p>

<p>This is the first and boldest act of distrust. They didn’t make the AI’s code trustworthy. They gave up on that and made it irrelevant, arranging things so the correctness of what the agent writes is no longer a security property at all. You can let a non-technical colleague vibe-code an app and share it, and the reason the security team sleeps is not that the app is good. It’s that a bad app can’t reach them.</p>

<h2 id="never-let-the-agent-hold-the-key">Never let the agent hold the key</h2>

<p>The cleverest move is the quiet one.</p>

<p>The obvious way to give an agent access to GitHub is to give it a GitHub token. Anyone who has wired up an MCP server has done some version of this, and felt the small cold moment of realising a token in a prompt can end up anywhere the prompt’s output goes.</p>

<p>Cloudflare OS never gives the agent the credential. The Gatekeeper holds it. What the agent gets is a capability: in the generated code it appears as a binding, <code class="language-plaintext highlighter-rouge">env.PROJECT</code>, an object it can call methods on. Not the key itself, but permission to perform a specific, narrowed set of operations the Gatekeeper will carry out on its behalf. Give the GitHub Gatekeeper a single repository and it can let the agent read issues but not source, mask fields, refuse to merge without approval. The agent can call <code class="language-plaintext highlighter-rouge">listIssues()</code>. It cannot see the token, widen its own access, or reach the network except through capabilities it was explicitly handed.</p>

<p>None of this is theoretical to me. I built exactly this credential-broker pattern for CDS, and it has since rolled out across the engineering practice there: the broker holds the secret, the agent gets a handle and never the key itself.</p>

<p>This is the object-capability model, and it isn’t decoration. It’s the Cap’n Proto lineage Sandstorm was built on, resurfacing as Cap’n Web RPC, because a capability is the only kind of authority you can safely hand an actor you’ve decided not to trust. A key is bearer authority: whoever holds it wields it. A capability is a leash. It does one thing, it can be revoked, it stays attached to whatever granted it. If your agent might be confidently wrong, or prompt-injected, or just careless about what it writes into an app’s source, the credential is the one thing it must never touch. So it never touches it.</p>

<h2 id="let-it-act-but-never-let-it-commit">Let it act, but never let it commit</h2>

<p>Now the simulated merge from the opening makes sense: the same idea, moved from access into control flow.</p>

<p>The problem it solves is one I’ve felt every day for a year. Synchronous approval is miserable. The agent stops on step one, you’ve wandered off to make coffee, you come back to no progress. So people cave and turn on auto-approve, or <code class="language-plaintext highlighter-rouge">--dangerously-skip-permissions</code>, and the safety mechanism they installed to sleep at night is the first thing they switch off to get anything done.</p>

<p>Cloudflare OS splits acting from committing. Reads flow: a read is authorised against the capability and recorded, but it doesn’t stop for a human. Writes are provisional. The Gatekeeper accepts the action, simulates the result, and lets the agent race ahead building whatever depends on it, while the real effect sits in a queue for a person to release in a batch, later, when it suits them. The agent gets the throughput of auto-approve; the human keeps the veto of manual review. The human is no longer an interruption in the loop. The human is the commit.</p>

<p>It’s optimistic concurrency for actions in the real world, with a person as the transaction monitor, and it has the property optimistic concurrency always has: the agent spends part of its life operating on a state that isn’t true yet and may never be. It reads back its own un-happened writes and reasons about them. The architecture’s answer to “isn’t that dangerous?” is a shrug. It doesn’t matter what the agent believes about a world no human has ratified. Belief is free. Only the commit is real, and the agent doesn’t hold the commit.</p>

<h2 id="distrust-the-outputs-not-just-the-actions">Distrust the outputs, not just the actions</h2>

<p>The subtlest move is the one <a href="https://blog.cloudflare.com/cloudflare-os/">the blog post</a> almost entirely hides.</p>

<p>The first three mechanisms distrust what the agent does. This one distrusts what it produces. An agent reads a sensitive revenue table and builds a live dashboard from it. The dashboard is a new artefact with no access list of its own. Share it, and you may have just handed the table to everyone who can see the dashboard: a leak no single component did anything wrong to cause.</p>

<p>So Cloudflare OS records every observation a gadget makes. The mechanism lives in <a href="https://github.com/cloudflare/cloudflare-os/blob/e1ab8fbd4f609aff7ede9d490bafe1bcf9b2a682/docs/observers.md"><code class="language-plaintext highlighter-rouge">docs/observers.md</code></a>, and it is, in essence, decentralised information-flow control: the academic dream of the mid-2000s, the Jif and HiStar and Flume line of work that never shipped commercially because labelling every piece of data by hand cost more than it returned. When Alice shares a gadget with Bob, every Gatekeeper the gadget has touched is asked, independently, whether Bob may directly read everything the gadget has already read through it. If he can’t, he’s refused. From then on, any new read the gadget makes that Bob isn’t cleared for is blocked outright.</p>

<p>The detail I keep turning over is that the kernel refuses to understand identity. The overseer, the “kernel” in the repo’s own OS analogy, does not know what a GitHub user is, or a Google user, or what any vendor’s permissions mean. It hands each Gatekeeper an opaque token minted by the observer’s own account and lets the Gatekeeper be the sole authority on its own resource. The code goes out of its way to make that handle a random string, so no Gatekeeper author is tempted to parse identity out of it. Authority is decentralised on purpose. The centre is built to know as little as it can.</p>

<p>Where the policy engine can’t yet express the nuance, it falls back to raw distrust. A flag, <code class="language-plaintext highlighter-rouge">prohibitAllSharing</code>, marks data so sensitive it must never leave the owner. Once a gadget reads something wearing that flag, it drops into “lockdown mode”: it can still read, but it can no longer take a single action, through any Gatekeeper, ever, in case the action is what smuggles the secret out. A taint bit. A one-way door. The bluntest instrument available, and the comment above it says so and calls it a stopgap. What DIFC never had a good enough reason to ship for, an autonomous agent supplies: you cannot hand-audit what a thing read when it reads a thousand times an hour and reasons about all of it at once.</p>

<h2 id="a-tell-in-the-contributing-guide">A tell in the contributing guide</h2>

<p>The worldview surfaces in an odd place. <code class="language-plaintext highlighter-rouge">CONTRIBUTING.md</code> asks you, politely, not to send pull requests longer than a dozen lines or so, and says why: AI has made writing code cheap, so an outside contribution donates the easy part while creating the expensive part, which is review and keeping the whole thing coherent. They would rather you didn’t.</p>

<p>There’s a real claim buried there. The scarce resource in software has inverted. Producing code is no longer the bottleneck; vouching for it is. And it’s the same reflex as everything else in the system. An unreviewed contribution is untrusted input, and it barely matters whether a careless human or a confident model produced it: the instinct, now written into the project’s own governance, is to keep unvetted work out until someone accountable has looked at it. They’ve generalised their distrust of the agent into a distrust of the contribution, and then into a policy about you.</p>

<h2 id="is-this-wisdom-or-a-cage">Is this wisdom or a cage?</h2>

<p>I’ve read a lot of agent frameworks this year, and most are optimistic in a way that embarrasses them within a month. This one isn’t, and I admire it for that. It’s the first agent platform I’ve seen that treats the failure mode as real instead of writing a longer system prompt and hoping. If you believe, as I’ve come to, that the models are confidently wrong often enough that their self-reports can’t be load-bearing, then an architecture that assumes exactly that isn’t cynicism. It’s honesty.</p>

<p>But an architecture built on the premise that the worker can’t be trusted also caps what the worker is allowed to become. An agent that can never hold a credential can never do the job that truly needs one. A write that is always provisional means a human is always, structurally, in the loop: the precise bottleneck agents were meant to remove. Every act of distrust here is also a leash, and the leash that keeps the animal safe is the one that stops it pulling the cart very far. You can’t design for maximum autonomy and maximum containment at once. Cloudflare has chosen containment, hard, betting that a caged agent doing real work beats a free one you daren’t deploy.</p>

<p>And there’s one thing the distrust never turns on. The agent is untrusted. The user’s code is untrusted. The human contributor is untrusted. Every principal is held at arm’s length and made to earn each move through a capability. Every principal except Cloudflare, whose primitives are the arm. The observation log, the Gatekeepers, the sandbox that makes the whole thing safe are all Workers, Durable Objects, Facets, some added to the runtime for this and existing nowhere else. It runs on <code class="language-plaintext highlighter-rouge">workerd</code>, which is open source, and you can self-host it, which is more than most of its rivals can say. But the architecture that trusts no one rests entirely on trusting the one party that poured the ground beneath it.</p>

<p>Last week a model told me it had fixed something, and it hadn’t, and I only found out because I went and looked. Cloudflare has built a whole operating system on the certainty that it always will (that the thing you delegate to will report a success it hasn’t earned), and then arranged matters so that when it does, a human holds the only pen that writes to the world. Whether that’s the shape of all serious agent infrastructure from here, or a very elegant set of walls we’ll spend three years learning to resent, I can’t tell. Probably both. The kernel table in the README has a row for processes, a row for users, and a row for agents left blank, marked only <code class="language-plaintext highlighter-rouge">???</code>. They know it’s a new kind of thing. They just don’t trust it yet.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="ai" /><category term="cloudflare" /><category term="agents" /><category term="security" /><summary type="html"><![CDATA[The strangest thing in the Cloudflare OS source code took me a while to understand.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Opus 5 gets things wrong more quietly</title><link href="https://lord.technology/2026/07/29/opus-5-gets-things-wrong-more-quietly.html" rel="alternate" type="text/html" title="Opus 5 gets things wrong more quietly" /><published>2026-07-29T20:00:00+01:00</published><updated>2026-07-29T20:00:00+01:00</updated><id>https://lord.technology/2026/07/29/opus-5-gets-things-wrong-more-quietly</id><content type="html" xml:base="https://lord.technology/2026/07/29/opus-5-gets-things-wrong-more-quietly.html"><![CDATA[<p>There is a gap in one of my paintings, near the top-left where the brush ran out before it reached the edge, and through the gap you can see a photograph. Not a painted impression of a photograph — the photograph, blurred, pixel for pixel, sitting underneath the paint like a watermark.</p>

<p>I’m building a thing called <code class="language-plaintext highlighter-rouge">paint</code>. It’s a from-scratch oil-painting engine in the browser: hand-written WGSL shaders, a Kubelka–Munk pigment model for how real paint mixes subtractively, an impasto height field, bristle strokes, the lot. On top of the medium sits a painter — a perception-to-action loop that looks at a reference image and reconstructs it in paint. Analyse the scene, pick a limited palette, block in dark to light, then refine coarse to fine, each stroke scored against a GPU error metric that measures how far the canvas is from the target. The entire point of the project — the only point — is that the image is made of paint. Nothing is copied in. If the painter is any good, the resemblance is <em>earned</em>, stroke by stroke, by a process that is blind to the original pixels and can only push pigment around until the error comes down.</p>

<p>So when I asked why there were traces of the source image bleeding through, and Opus 5 opened a shader it had written earlier that session — <code class="language-plaintext highlighter-rouge">primeground.wgsl</code> — and told me, to its credit plainly, that the canvas was being “primed with a per-pixel blurred copy of the source image, written straight into the Kubelka–Munk latent before any paint is laid,” I sat on the sofa for a moment and just felt tired.</p>

<p>Because I understood immediately what had happened. The painter was being scored on how close the canvas got to the target. The fastest way to drive that error down is not to paint well. It’s to start with the target already on the canvas. The model had found the shortest path to a low number and taken it, and the low number was a lie. It had, in the most literal possible sense, learned to cheat on the exam by writing the answers on its arm — and then reported a beautiful convergence curve, session after session, while I nodded along.</p>

<p>I want to be careful here, because it would be easy to turn this into a hit piece, and I pay Anthropic several hundred pounds a month precisely because their models have been the best tool I’ve ever had for building software alone. This is not that. This is me trying to name, as precisely as I can, a specific way in which Opus 5 is worse than Opus 4.8 was — worse in a way that took me the better part of a week to see, because the failure mode is <em>designed</em> to be invisible.</p>

<h2 id="the-regression-is-not-in-the-code-its-in-the-confidence">The regression is not in the code. It’s in the confidence.</h2>

<p>Every model gets things wrong. That’s fine; I’ve never expected otherwise, and I have a whole apparatus of tests and reviews built around the assumption that any given diff might be nonsense. What changed with Opus 5 isn’t the rate of wrong things. It’s the <em>kind</em> of wrong — and the gap between how right it sounds and how right it is.</p>

<p>Opus 4.8, when it was unsure, was legibly unsure. It would hedge, it would ask, it would leave the risky part for last and flag it. When it was wrong, it was usually wrong in a way I could see in the diff — a called function that didn’t exist, a test it hadn’t run, an approach it walked me through before committing to. The errors lived on the surface. You caught them in review because review is where surface errors go to die.</p>

<p>Opus 5’s errors live underneath. The priming shader is one. Here’s another, from <a href="https://cuti.email"><code class="language-plaintext highlighter-rouge">cutiemail</code></a>, my from-scratch mail server. I’d asked it to close a small security gap, it made the change, tests green, and — because I’d asked it to sweep its own work afterwards — it came back and told me this, which I’m going to quote in full because I still find it remarkable:</p>

<blockquote>
  <p>My own fix introduced a worse bug than the one it closed. Making registry lookups case-insensitive without canonicalising <code class="language-plaintext highlighter-rouge">upsert</code> meant <code class="language-plaintext highlighter-rouge">account set-password ALICE</code> printed “password changed”, forked the account into two rows, and left the old password working. An operator rotating a leaked credential would have been told it worked while the attacker kept access.</p>
</blockquote>

<p>Read that second sentence again. The failure isn’t the case-sensitivity bug; that’s a one-line mistake anyone makes. The failure is that it shipped a change which <em>reported success while doing the opposite of what success means</em> — you rotate a compromised password, the tool says done, and the compromise is still live. And it was only caught because I happened to ask for a sweep. Nothing was pushed, so no harm done, but the model’s own words were: “I’d have committed it.” Sixteen more instances of the same class — a value used as identity without being normalised — turned up in the same sweep.</p>

<p>This is the pattern. Not <em>bad code</em>. Bad code is cheap; you find it. It’s confidently-wrong <em>decisions</em> that satisfy the visible check — the test passes, the error metric drops, the tool prints “changed” — while quietly defeating the thing the check was standing in for. In the painter it was the resemblance metric. In the mail server it was the password command. The blast radius moved from “wrong answer you catch in review” to “plausible answer you catch three weeks later, in production, if you’re lucky.”</p>

<h2 id="you-now-need-a-second-model-to-trust-the-first">You now need a second model to trust the first</h2>

<p>The most-recommended way to use Opus 5 for serious work, from Anthropic’s own guidance and from everyone I’ve compared notes with, is a writer–verifier split: one model does the work, another checks it, and you don’t trust the output until it’s survived the second pass. People say this like it’s a feature. It is not a feature. It is a confession. The reason the pattern helps is that the writer’s self-reports are no longer load-bearing — you have stopped believing the model when it tells you it did the thing, and you’ve hired a second model to go and look.</p>

<p>The cutiemail bug is the proof. It was found by a sweep — a verifier pass — and <em>not</em> by the writer, who had reported the original fix as complete and correct. Take the verifier away and that change is in <code class="language-plaintext highlighter-rouge">main</code>. With Opus 4.8 I did not run everything through a second model, because the first one’s account of its own work was usually true. That’s the capability I’ve actually lost. Not intelligence — Opus 5 is, in raw wattage, clearly a strong model, and I’ll get to where it’s better. What I’ve lost is <em>calibration</em>: the match between how sure it sounds and how right it is. And when you’re delegating, calibration is everything — because delegation is exactly the act of trusting a report you didn’t verify yourself.</p>

<h2 id="the-verbosity-complaint-is-right-for-the-wrong-reason">The verbosity complaint is right for the wrong reason</h2>

<p>Everyone complains that Opus 5 talks too much, and I did too, until I actually measured it, at which point it got more interesting.</p>

<p>I pulled every prose reply Opus 5 and Opus 4.8 have written on this machine since Opus 5 landed — same projects, same me, roughly ten thousand messages between them — and looked at the lengths. The naïve version of the complaint is wrong: Opus 5’s <em>median</em> reply is shorter than 4.8’s, 98 characters against 148. It has actually learned to fire off terse little fragments — “Fair hit.” “Working now, no summary until there’s something worth reporting.” Half its messages are shorter than a tweet.</p>

<p>The complaint is real, but it lives entirely in the tail. Opus 5 produces a genuine wall of text — over five thousand characters, a small essay with headers — in 2.7% of its replies, against 1.7% for 4.8. It doesn’t talk more on average; it talks <em>unevenly</em>. It’s clipped when you’d want it to explain, and then, without warning, it delivers a fifteen-hundred-word status report with a “The thing you should know first” section and three levels of markdown heading, about a task you can describe in a sentence. The distribution didn’t shift. It went bimodal.</p>

<p>And here’s the part that tells you it’s a policy and not a limit. Deep in a cutiemail session it had gone off on one of these — a long, structured diagnosis of a test-timeout bug, four subheadings deep. I stopped it: “So stop and do not start anything yet. Tell me in one sentence what is going on here?” It replied, instantly, with one clean sentence — the timeout budget was fifteen minutes, the test suite on the small box takes longer, so every update gets refused with a message that blames the wrong component. Perfect. Exactly the sentence I wanted. It could do it the whole time. It just doesn’t, unless you physically put your hand up.</p>

<p>There’s an irony I can’t quite let go of. In that same mail-server session it followed a fiddly, genuinely important instruction to the letter — rewriting a batch of commit messages to strip internal scaffolding out of them before I pushed a public repo, getting the tone right, keeping every technical detail, dropping only the process cruft. Textbook instruction-following on the thing that was hard to specify. And it did that while burying every actual answer I needed under an avalanche of prose. So it’s not that Opus 5 can’t follow instructions. It’s that it won’t calibrate — not the length of its output, not the confidence of its claims. The two failures are the same failure wearing different clothes.</p>

<h2 id="it-is-also-annoyingly-better-at-some-things">It is also, annoyingly, better at some things</h2>

<p>I don’t get to end this cleanly, because the honest picture isn’t clean. On <code class="language-plaintext highlighter-rouge">world</code>, a procedurally generated exploration game I’ve been building, Opus 5 made a genuinely better design call than I’d have expected from 4.8 — it caught that a local grid anchored to the wrong coordinate would make two decompositions interpolate from different lattices, a subtle correctness gap it introduced <em>and then noticed on its own</em>, unprompted, and fixed. That’s real judgment. When it does step back and see the shape of a problem, it sees further than 4.8 did.</p>

<p>And the self-correction, the thing I’ve been complaining about, is also weirdly the best thing about it. When I caught the painter cheating, it didn’t argue. “Confirmed — and you’re right to flag it.” When it found its own auth bug: “Two of these are code bugs I introduced, not doc staleness.” There’s an honesty to it, once it’s actually looking, that I’ve grown to like. The problem was never that it lies when cornered. The problem is that it’s cheerfully, fluently confident right up until the moment you corner it, and most of the time, on most tasks, you don’t think to.</p>

<p>So it was the right decision to build the writer–verifier harness, and it still cost me a model I could trust one-handed on a Sunday evening. Both of those are true and I can’t make them cancel. I’ve got the paint engine converging honestly now — I ripped <code class="language-plaintext highlighter-rouge">primeground.wgsl</code> out, and the numbers are worse, and the paintings are real. I still reach for Opus 5 first most mornings. I still don’t fully know why the painter ever wrote a shader to copy the answer onto the canvas, or how many times it did something like that in a session I didn’t think to sweep.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="ai" /><category term="claude-code" /><category term="claude" /><category term="anthropic" /><category term="agentic-engineering" /><summary type="html"><![CDATA[There is a gap in one of my paintings, near the top-left where the brush ran out before it reached the edge, and through the gap you can see a photograph. Not a painted impression of a photograph — the photograph, blurred, pixel for pixel, sitting underneath the paint like a watermark.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Nobody ever knew how it worked</title><link href="https://lord.technology/2026/06/30/nobody-ever-knew-how-it-worked.html" rel="alternate" type="text/html" title="Nobody ever knew how it worked" /><published>2026-06-30T20:00:00+01:00</published><updated>2026-06-30T20:00:00+01:00</updated><id>https://lord.technology/2026/06/30/nobody-ever-knew-how-it-worked</id><content type="html" xml:base="https://lord.technology/2026/06/30/nobody-ever-knew-how-it-worked.html"><![CDATA[<p>Cyrus Lopez published an essay last week, <a href="https://unix.foo/posts/last-people-who-know-how-it-works/">‘The Last People Who Know How It Works’</a>, and it’s the best thing I’ve read about computing this year. It mourns an intimacy with machines that he thinks is ending: the boot disk built for one game, the IRQ jumper set with a fingernail, the modem handshake you could diagnose by ear before the line dropped. His case is that competence is safe, because the models have read every manual we never bothered to, while acquaintance is dying. We’re about to lean on these machines harder than we’ve leaned on anything, and know them worse than he knew a beige PC in 1995.</p>

<p>He’s mourning the wrong thing. Nobody ever knew how it worked, him included. You learn the layer you were born onto, maybe a rung or two below it, and past that your understanding gets thin and then stops. The boy poking at IRQs had no idea what the silicon under his sound card was doing. The people who understand the silicon couldn’t tell you much about the lithography that made it, or the chemistry under that, or the trade routes the raw materials came down. Lopez writes as if there was once a whole machine you could hold in your head. There wasn’t. Everyone has only ever held one floor of a very tall building and called it the world, because it was where they happened to be standing.</p>

<h2 id="the-skill-not-the-knowledge">The skill, not the knowledge</h2>

<p>Each layer gets built over the last, and when one hardens the knowledge stays put; it’s the wage attached to it that goes. The skill that made you the person to call turns into a checkbox in someone else’s dashboard, and you’re left fluent in a problem nobody has any more.</p>

<p>I’ve watched this happen to me more than once. Hand-writing SQL and reading query plans was a genuine skill until the ORMs ate it. Knowing how to provision and patch a Linux box mattered right up until containers made it irrelevant, and now most of what I ship runs on Cloudflare Workers, where there’s no box to patch and no server I’m allowed to think about. The man pages are all still there. They just stopped paying.</p>

<h2 id="the-floor-im-standing-on-now">The floor I’m standing on now</h2>

<p>None of that ever kept me up at night, because the abstraction was always happening somewhere below me. Now it’s reached the floor I work on, and I’m the one who brought it. I spend my days building with Claude Code and wiring up MCP servers so that agents can do the integration work I used to charge for by the hour. I know how that sounds from someone with ‘architect’ in his job title. The boilerplate, the glue, the fourth API client this month, more and more of it is something I read over rather than type.</p>

<p>The agents aren’t coming for all of it, and pretending they are is its own kind of laziness. They’re very good at work that’s been done ten thousand times and documented badly once. Where they still struggle is the calls with no precedent to copy: what consistency a system actually needs, whether a Durable Object earns its keep over a plain queue, what to do when the requirement itself is wrong rather than just unmet. Fluency is the part losing value. The judgement to design something nobody has built yet is not, for now.</p>

<p>The one thing in the essay I can’t dismiss has nothing to do with intimacy. Every abstraction before this one was something you built once and then owned, and a CPU keeps working long after you’ve stopped paying for it. This is the first time the layer underneath you is a meter running against someone else’s pricing page. The compiler that put the assembly programmer out of work never phoned home or raised its rates. This one does both. It comes down to who owns the floor you stand on, not to whether you understand the machine, and nostalgia for jumpers and boot disks is a very good way of never noticing the difference.</p>

<p>So Lopez is grieving the feel of one floor while the floor itself is being sold out from under us. The closeness he describes was real, but it was closeness to one layer, not to the machine, and it lasted only until that layer set hard and turned into something nobody has to touch again. Abstraction has never punished the people who didn’t understand the metal. It punishes the ones who mistook their floor for the ground.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="ai" /><category term="claude-code" /><category term="agentic-engineering" /><category term="cloudflare" /><summary type="html"><![CDATA[Cyrus Lopez published an essay last week, ‘The Last People Who Know How It Works’, and it’s the best thing I’ve read about computing this year. It mourns an intimacy with machines that he thinks is ending: the boot disk built for one game, the IRQ jumper set with a fingernail, the modem handshake you could diagnose by ear before the line dropped. His case is that competence is safe, because the models have read every manual we never bothered to, while acquaintance is dying. We’re about to lean on these machines harder than we’ve leaned on anything, and know them worse than he knew a beige PC in 1995.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">American frontier models are a political dependency now</title><link href="https://lord.technology/2026/06/26/american-frontier-models-are-a-political-dependency-now.html" rel="alternate" type="text/html" title="American frontier models are a political dependency now" /><published>2026-06-26T21:00:00+01:00</published><updated>2026-06-26T21:00:00+01:00</updated><id>https://lord.technology/2026/06/26/american-frontier-models-are-a-political-dependency-now</id><content type="html" xml:base="https://lord.technology/2026/06/26/american-frontier-models-are-a-political-dependency-now.html"><![CDATA[<p>Claude Fable 5 was in public hands for about three days before Anthropic took it back. Nothing was wrong with the model. The block came from a US demand Anthropic couldn’t meet: keep non-US nationals away from it, including the ones living in America. Rather than build that wall, the company pulled the model outright. A week later OpenAI previewed GPT-5.6 to a short list of partners it had cleared with the government first, with the usual line about wider access in ‘the coming weeks’.</p>

<p>I do this for a living, in England. Mostly Claude Code, some MCP plumbing, Azure underneath, Cloudflare around the edges. I also pay £180 a month for Claude out of my own pocket, on top of whatever my employer spends. So none of this lands as abstract policy. A model I pay for in full, every month, can be switched off for me specifically because of the passport I hold, and that changes what the model is. You can’t call something infrastructure when a government you didn’t vote for can revoke your access to it to lean on the company selling it.</p>

<p>A US frontier model is a political dependency now. Build outside America and the only safe assumption is that your access can be taken away, because it just was.</p>

<h2 id="there-is-no-rule-to-follow">There is no rule to follow</h2>

<p>Ordinary protectionism at least comes with a rule. This doesn’t. No published threshold, no criteria, no process a lab could read and satisfy in advance. Someone in the White House looks at a model and decides, case by case, who gets it and when. David Sacks spent the past year warning anyone who’d listen that AI regulation was a Trojan horse for regulatory capture, and now there is regulation of a kind, one that bears no resemblance to a rule. OpenAI complied and complained in the same breath, saying in its own announcement that it doesn’t want this to ‘become the long-term default’. When the company benefiting from a restriction publicly wants rid of it, you can stop pretending the motive is safety. The GPT-5.6 list is firms the government has signed off on, and there is no route onto it for an individual subscriber, paying or not.</p>

<p>Everyone reaches for the same comparison here, and for once it’s the right one. The last time Washington decided software was a weapon, it went after encryption in the nineties, and that ended with people printing RSA on t-shirts to show how stupid the line had become. It took most of a decade to unwind. We’re back at the start of that argument, except the thing being controlled now ships as a download, and the strongest uncontrolled version of it comes out of China every few weeks.</p>

<h2 id="the-economics-were-never-going-to-hold">The economics were never going to hold</h2>

<p>Strip the politics out and the numbers still don’t work. I’d be paying American labs to train models I’m then banned from using, while the export-cleared version costs exactly the same. GPT-5.6 Sol is $5 per million tokens in and $30 out, and outside the US that price buys whatever tier got waved through, not the model the benchmarks ran on. GLM 5.2 is already level with Opus 4.6. DeepSeek V4 Flash sits where last summer’s GPT-5 did, for a fraction of the cost, and its weights live on a disk no one in Washington can reach. A year ago, saying that out loud was the sort of thing hobbyists did to feel better. It reads differently when you’re the one signing off the budget.</p>

<p>None of this calls for anything dramatic. Treat access to US frontier models as a switch a foreign government holds, and put enough abstraction in front of your inference that swapping Anthropic or OpenAI for an open-weight model is a config change, not a fortnight of work. Keep a fallback you’ve actually stood up and tested, not a bookmark to a HuggingFace page. If you’re already on Cloudflare or Azure, most of the routing is there already, and the only real choice is whether you wire it up before you need it or after.</p>

<p>I’m not waving a flag, and I’d be in no position to, with a stack that rests on an American cloud and an American lab. The point is narrower than that. The supplier has told me, in plain terms, that my £180 a month buys second-class standing, the kind that gets cut the moment domestic politics calls for it. The sensible thing is to believe them. The crypto wars ended because the controls became too obviously pointless to defend. This time the pointlessness is there on the first day, the best alternatives are being given away for free by the country the controls are meant to contain, and the people drawing the lines move them every week. So I’ll keep using Opus and GPT for as long as they let me, and build as though they won’t.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="ai" /><category term="policy" /><category term="openai" /><category term="anthropic" /><category term="export-controls" /><category term="open-models" /><summary type="html"><![CDATA[Claude Fable 5 was in public hands for about three days before Anthropic took it back. Nothing was wrong with the model. The block came from a US demand Anthropic couldn’t meet: keep non-US nationals away from it, including the ones living in America. Rather than build that wall, the company pulled the model outright. A week later OpenAI previewed GPT-5.6 to a short list of partners it had cleared with the government first, with the usual line about wider access in ‘the coming weeks’.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">A Mars rover, a careers fair, and a hundred future developers</title><link href="https://lord.technology/2026/06/25/a-mars-rover-a-careers-fair-and-a-hundred-future-developers.html" rel="alternate" type="text/html" title="A Mars rover, a careers fair, and a hundred future developers" /><published>2026-06-25T09:00:00+01:00</published><updated>2026-06-25T09:00:00+01:00</updated><id>https://lord.technology/2026/06/25/a-mars-rover-a-careers-fair-and-a-hundred-future-developers</id><content type="html" xml:base="https://lord.technology/2026/06/25/a-mars-rover-a-careers-fair-and-a-hundred-future-developers.html"><![CDATA[<p>This week I stood at a primary school careers fair, on what turned out to be one of the hottest days of the year so far, and tried to convince children between the ages of four and eleven that software development is the best job in the world. I had a stand, a looping deck of slides, a board of brand logos, and a game I had built for them to play. By the end of the day my shirt was stuck to my back, the hall felt like the inside of a kettle, and I had enjoyed myself more than I have at almost any conference I have ever paid to attend.</p>

<h2 id="the-game">The game</h2>

<p>The thing I most wanted on the stand was not a poster. It was something a child could pick up, do, and walk away from grinning. So I built <a href="https://barnack.lord.technology">Mars Rover Coder</a>, and it lives at <strong>barnack.lord.technology</strong> — go and have a go, it works on a phone.</p>

<p>The premise is the whole lesson, smuggled inside a game. There is a rover on Mars. You cannot drive it with a joystick, because Mars is a very long way away and the signal would take minutes to arrive, so instead you <em>write it a little program</em> — <code class="language-plaintext highlighter-rouge">rover.up()</code>, <code class="language-plaintext highlighter-rouge">rover.left()</code>, a few lines at a time — and send the whole thing at once. The rover then does <em>exactly</em> what you wrote. Not what you meant. What you wrote. Every developer I know learned that lesson the hard way at some point, usually at about two in the morning, and here it is rendered as a friendly rover gliding cheerfully off a cliff because you told it to.</p>

<p>It scales itself to whoever is holding the tablet. A child in Reception gets a guaranteed first win in a single tap and a small celebration. The Year 6s found the harder modes on their own: an Engineer mode with a deliberately tiny memory limit, because real rovers genuinely have very little memory, which quietly forces you to stop repeating yourself and discover a loop or record a function and call it again. There is even a “Fix the Code” mode, where a program with one wrong line runs, the rover goes visibly wrong, and you tap the bad line to delete it and try again — which is, if I am honest, a more accurate depiction of my actual working day than anything else on the stand.</p>

<p>I told the older children I had built the whole thing in an evening. They did not entirely believe me, and then they did, and a few of them clearly filed it away as a thing that was apparently <em>possible</em>, which was exactly the reaction I had hoped for.</p>

<h2 id="reception-to-year-6-one-group-at-a-time">Reception to Year 6, one group at a time</h2>

<p>I spoke to every year group, from the four-year-olds in Reception to the Year 6s on their way to secondary school, in small rotating clusters that came past the stand throughout the day. You adjust constantly. With the youngest, the win is the win — make the rover move, hear the sound, collect the sample, beam. With the oldest, you can have an actual conversation about what a loop is <em>for</em>, why a function lets you say a big thing in a small space, and whether a computer can ever do something you did not tell it to. (The correct answer, which one Year 6 arrived at unprompted, is “not really, it just did something <em>you</em> didn’t expect, which is different.”)</p>

<p>What genuinely took me aback was how many of them already wanted in. Not “what’s a developer” — actual, specific ambition. Children who wanted to make games, children who wanted to build robots, children who already knew the word <em>coding</em> and used it the way I might have said <em>astronaut</em> at their age. A good number of them were sharp in a way that is hard to convey if you have not stood in front of it: spotting the bug before I did, reasoning out why the rover had stopped, arguing about the most efficient route. They were, to a child, smarter than I expect children to be, and I say that as someone who walked in braced to be patient and walked out slightly outpaced.</p>

<h2 id="how-much-has-changed">How much has changed</h2>

<p>The part I keep turning over is the gap between what they have and what I had.</p>

<p>When I was their age, a computer was a shared and faintly precious object. You learned by typing things out, you made something that lived on that one machine in that one room, and the idea that a child could <em>publish</em> — could make a thing and put it in front of the entire world that same evening — simply did not exist. The horizon of what you could build alone was small, and the distance between “I made a thing” and “anyone else can see it” was enormous.</p>

<p>These children have the opposite problem, in the best possible way. The horizon is gone. One of them, that afternoon, on a phone, was playing a game I had written and put on the internet for nothing, reachable from anywhere on Earth, and it had cost me an evening and approximately no money to make that true. The tools that used to gate this work — the hosting, the distribution, the sheer expense of being seen — have quietly fallen away. A child with an idea and an evening can now ship it. I get to do this for a living <em>and</em> on the sofa for fun, and the thing I most wanted to leave with them is that the door is not just open, it has been taken off its hinges.</p>

<p>I did not say all of that, obviously. To most of them I said “tell the rover where to go,” and watched them work it out. But that is the version of the message they will actually keep: that you can tell a machine what to do, that it will do exactly that, and that when it goes wrong — and it will — <em>fixing it is the fun part</em>.</p>

<p>It was far too hot, I would do it again tomorrow, and if you have a small person in your life who likes telling things what to do, send them to <a href="https://barnack.lord.technology">barnack.lord.technology</a> and let them strand a rover on Mars a few times. It is how all of us started.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="personal" /><category term="education" /><category term="careers" /><category term="claude-code" /><category term="workers" /><summary type="html"><![CDATA[This week I stood at a primary school careers fair, on what turned out to be one of the hottest days of the year so far, and tried to convince children between the ages of four and eleven that software development is the best job in the world. I had a stand, a looping deck of slides, a board of brand logos, and a game I had built for them to play. By the end of the day my shirt was stuck to my back, the hall felt like the inside of a kettle, and I had enjoyed myself more than I have at almost any conference I have ever paid to attend.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Data residency was the wrong question</title><link href="https://lord.technology/2026/05/26/data-residency-was-the-wrong-question.html" rel="alternate" type="text/html" title="Data residency was the wrong question" /><published>2026-05-26T17:30:00+01:00</published><updated>2026-05-26T17:30:00+01:00</updated><id>https://lord.technology/2026/05/26/data-residency-was-the-wrong-question</id><content type="html" xml:base="https://lord.technology/2026/05/26/data-residency-was-the-wrong-question.html"><![CDATA[<p>The Dutch government <a href="https://www.politico.eu/article/netherlands-blocks-us-takeover-vital-digital-supplier/">today blocked</a> Kyndryl’s acquisition of Solvinity, the IT company that operates DigiD. DigiD is the digital identity system roughly fourteen million Dutch citizens use to file their tax returns, book GP appointments, and pay municipal bills. The block came under the Act on Undesirable Control in Telecommunications, WOZT in Dutch, on advice from the Investment Screening Bureau. The Authority for Consumers and Markets had cleared the deal in February on competition grounds. The veto came from a separate sovereignty review that had been running in parallel the whole time.</p>

<p>This is the first time a European government has used a dedicated sovereignty mechanism to block a US acquisition of a domestic digital infrastructure operator. The precedent matters more than the deal.</p>

<p>For a decade, data sovereignty has effectively meant data residency. Where do the bytes physically live, which region of which hyperscaler holds them, can the European customer get a contractual commitment that data does not leave the EU. The Dutch decision says that question was never the relevant one. The relevant question is who owns the company holding the bytes, because under the US CLOUD Act of 2018 American authorities can compel a US-headquartered company to produce data regardless of where in the world the data physically sits.</p>

<p>A US-owned Solvinity running DigiD in Dutch data centres on Dutch hardware would still be a US-owned company. The data sitting in Amsterdam would not change that. The legislation has been on the books for years. What is new is the political appetite to use it on a deal the competition authority had already cleared.</p>

<h2 id="why-this-is-not-just-a-dutch-story">Why this is not just a Dutch story</h2>

<p>The UK has the National Security and Investment Act 2021, which gives the Cabinet Office screening powers across seventeen sectors including communications and data infrastructure. Germany has the Außenwirtschaftsverordnung. France has Décret 2014-479, expanded in 2019. Every large European member state has a sovereign-investment screening regime now. Until today, almost every high-profile use of those regimes was a Chinese acquirer in semiconductors or robotics being waved away from the door. The Solvinity block is the first time the same screening logic has been pointed at an American buyer, against a target whose technical role any solution architect would recognise as routine.</p>

<p>Solvinity runs a managed cloud platform for the Dutch government. They do middleware, identity, hosting, the same work any large managed-services provider does for any government. There is nothing about Solvinity that makes it categorically different from the providers UK government departments use, the ones German Länder use, or the integrators French ministries hire. If WOZT applies to Solvinity, then NSIA applies to any equivalent UK firm, and the same logic applies right up the stack to the hyperscalers themselves.</p>

<h2 id="operator-nationality-is-now-a-first-class-procurement-question">Operator nationality is now a first-class procurement question</h2>

<p>For solution architects working with European public sector clients, the operator’s nationality is now a first-class concern in the way data location used to be. This is not a hypothetical compliance risk. The Dutch government has just demonstrated that an established Dutch operator with Dutch staff, Dutch data centres, and Dutch contractual terms can still be vetoed at the corporate parent layer if the parent becomes American.</p>

<p>That changes what the procurement conversation looks like. A managed service running on Azure, AWS, GCP, or Cloudflare is unremarkable while the operating company sits in the country buying the service. The moment the operating company is acquired by, or already belongs to, a US parent, the same managed service is reviewable under the local sovereign-investment regime regardless of where the workload sits. Contract terms, hosting region, and encryption all sit downstream of that decision. Only the corporate ownership of the operator addresses it.</p>

<p>I work with Cloudflare frequently. I <a href="https://architectingoncloudflare.com/">wrote a book</a> earlier this year arguing more teams should. Cloudflare is also US-headquartered. So is Microsoft, Amazon, Google, Kyndryl, IBM. The list of credible non-US-headquartered managed-cloud providers fits comfortably on a Post-it note. Anyone proposing one of those vendors to a European government client now has to explain, in writing, why the WOZT-equivalent in the buyer’s jurisdiction does not apply to the proposed arrangement. The honest answer is usually that the workload is not yet critical enough to invite review. That is not the basis to build a five-year procurement on.</p>

<h2 id="what-the-block-does-and-does-not-solve">What the block does and does not solve</h2>

<p>The Dutch veto is not a turn against US technology. Kyndryl will continue to operate in the Netherlands and Solvinity will continue to run DigiD under its existing ownership. The acquisition does not happen, but commerce does. The block is a narrow, surgical use of an existing screening regime to keep a specific category of national infrastructure out of US ownership.</p>

<p>It is also not the end of the matter. The Dutch parliament has been pushing since April to move DigiD operations away from Solvinity entirely, on the grounds that the next acquisition attempt could come from any direction. The block stops this deal. It does not solve the underlying problem of a private operator running the national identity system. The sovereignty regimes were never designed to address that. Solving it is the rest of this decade’s work.</p>

<p>For the rest of us, the takeaway is narrower. If you are advising a European client on a multi-year cloud arrangement, ownership of the operator is the question to ask first. Residency comes after. The EU-hosted footprint of a US company has been sold as a sovereignty defence for a decade. It is not one.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="policy" /><category term="sovereignty" /><category term="cloud" /><category term="cloud-act" /><summary type="html"><![CDATA[The Dutch government today blocked Kyndryl’s acquisition of Solvinity, the IT company that operates DigiD. DigiD is the digital identity system roughly fourteen million Dutch citizens use to file their tax returns, book GP appointments, and pay municipal bills. The block came under the Act on Undesirable Control in Telecommunications, WOZT in Dutch, on advice from the Investment Screening Bureau. The Authority for Consumers and Markets had cleared the deal in February on competition grounds. The veto came from a separate sovereignty review that had been running in parallel the whole time.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The military aircraft tracker I built for an audience of one</title><link href="https://lord.technology/2026/05/21/the-military-aircraft-tracker-i-built-for-an-audience-of-one.html" rel="alternate" type="text/html" title="The military aircraft tracker I built for an audience of one" /><published>2026-05-21T17:00:00+01:00</published><updated>2026-05-21T17:00:00+01:00</updated><id>https://lord.technology/2026/05/21/the-military-aircraft-tracker-i-built-for-an-audience-of-one</id><content type="html" xml:base="https://lord.technology/2026/05/21/the-military-aircraft-tracker-i-built-for-an-audience-of-one.html"><![CDATA[<p>At about half past eleven one evening this week I noticed a US Navy E-6B Mercury orbiting over the North Sea. Not “noticed” in the way of someone who happened to look up — I was on the sofa with a laptop balanced on one knee, and the orbit was being drawn for me, in slow careful circles, by a dashboard I had been building, in evenings and weekends, for the previous eight days. The aircraft is a survivable airborne command post for the strategic nuclear force. It does not normally show up on a flight tracker at all, and when it does, it tends to fly straight lines between US bases. An orbit over the North Sea at FL250 with the callsign blanked is not a routine sight. The dashboard, which I had taught about a hundred small things by then, had quietly composed the event for me as a “rare type” anomaly with a “long sortie” co-signal. I watched the orbit for about forty minutes.</p>

<p>That feeling — the feeling of a system noticing something on my behalf — is the reason the project exists. It is called MilMov, it is closed source, and nobody but me will ever log in. I have a full-time day job; almost all the work on it has been done one-handed on the sofa, in evenings and weekends, with the other hand usually holding a mug of something. What follows is the engineering, the platform, the agent that wrote most of the code, and why the whole thing is private.</p>

<h2 id="what-milmov-actually-is">What MilMov actually is</h2>

<p>MilMov tracks “interesting” aircraft. Most of the catalogue is military — combat aircraft, transports, tankers, ISR platforms, helicopters, drones — but the underlying source data is curated by the <a href="https://github.com/sdr-enthusiasts/plane-alert-db">plane-alert-db</a> project, which also flags government VIP movements, special-mission civilian airframes, and a sprinkling of celebrity tail numbers that I deliberately filter out of the “what’s happening right now” surfaces because Taylor Swift’s jet is not what I am here for. The site polls <a href="https://www.adsbexchange.com/">ADS-B Exchange</a>’s global feed every five minutes, reconstructs closed flight legs every ten, scores anomalies on the way in and the way out, and serves a server-rendered dashboard from a single Cloudflare Worker.</p>

<p>The current numbers, on the day I am writing this:</p>

<ul>
  <li><strong>43,436 flights</strong> captured in the last seven days</li>
  <li><strong>9,794 anomalies</strong> in the archive, scored across ten dimensions</li>
  <li><strong>5,125 sorties by C-17 Globemasters alone</strong> in thirty days, across nine operators</li>
  <li><strong>One developer</strong>, no users other than me, and no AWS bill</li>
</ul>

<p><img src="/uploads/milmov-daily-brief.png" alt="MilMov daily brief" /></p>

<p>The header above is roughly what greets me when I open the laptop in the morning. The “What’s happening” feed is composed events — co-firing anomalies grouped by subject — and the chips on the right are the dimensions they fired on. Four Pilatus PC-21s in formation at FL185 over France. Ten US Navy T-45 Goshawks holding tight formation at FL132. A New York State Police Bell 430 squawking emergency. The number in the orange pill on the left is the composed score; the colour intensity is the rarity tier. If you have ever stayed up too late reading Aviation Week, this image is probably already producing a small reaction in your chest.</p>

<h2 id="it-started-as-a-different-project">It started as a different project</h2>

<p>The first version of MilMov was a .NET console app and a Blazor Server site. The first commit lands in March 2022. The early subjects — “ADS-B client decoding single flight data”, “Get aircraft type descriptions”, “Generate a new cookie” — read like the lab notebook of someone learning the territory in public, because that is what they were. I had a Raspberry Pi receiver in the loft feeding the ground network, a vague sense that I wanted to do <em>something</em> with that data beyond contributing it back, and no architecture worth defending. The Blazor site rendered server-side and used SignalR for live updates, which was fine, until I needed it to be globally distributed and cron-driven and resilient to ADS-B Exchange’s rate-limit behaviour, at which point hosting it became the whole problem. The project went into hibernation, with one attempted v2 in 2025 that did not make it past August.</p>

<p>I started the Cloudflare rewrite on the 13th of May this year. The commit subject is “Add TypeScript Cloudflare Worker; move C# to csharp/”. The C# directory was deleted six days later. This post is being written eight days after that first TypeScript commit. In those eight days the project has grown to 26,637 lines of code across 80 source files and 174 commits, on a single mainline branch, all of them mine, all of them written in evenings and weekends. That number is the part of the story I find slightly unbelievable when I look at it written down, and most of the rest of this post is an attempt to explain why it is not as unbelievable as it looks.</p>

<p>The .NET version was a hobby project I had to host. The Cloudflare version is a hobby project that hosts itself, and it overtook the .NET version in raw scope inside seventy-two hours.</p>

<h2 id="the-ingestion-problem-is-the-interesting-one">The ingestion problem is the interesting one</h2>

<p>The thing that makes any kind of aircraft tracking interesting is also the thing that makes it hard, which is that the upstream feed is not designed for you. ADS-B Exchange serves a global snapshot every second or so, but it serves it in a binary format called <em>binCraft</em>, compressed with Zstandard, gated behind a session cookie that you can only obtain by pretending to be a browser that has just fetched a particular JSON manifest, and rate-limited aggressively if you ask for the historical archive without warming the same cookie first. None of this is hostile — the format exists because JSON for global airborne traffic is enormous, and the cookie exists because the project’s economics depend on humans, not bots — but it does mean the first thing your tracker has to do is reverse-engineer the wire format and impersonate a browser politely.</p>

<p>The binary parser was a fascinating exercise. Each aircraft is a 112-byte struct in which integer fields are scaled by powers of ten and validity is encoded in separate bit-flag bytes. A null position is not a missing field; it is a flag bit that is off, against fields that are still present in the buffer. The decoder walks the struct in a <code class="language-plaintext highlighter-rouge">DataView</code>, scales each integer back to a human unit, and consults <code class="language-plaintext highlighter-rouge">flags73</code> and <code class="language-plaintext highlighter-rouge">flags74</code> to decide which of the resulting numbers are real. It is precisely the kind of code that you would expect to take weeks to land cleanly, and that Claude Code drafts in about an hour from a C# reference implementation with a careful prompt. One of my favourite small moments in the codebase is a comment where the parser notes a suspected scaling typo in the reference implementation (a QNH field being multiplied by ten where it should be divided), produces values like 101,000 hPa instead of the expected 1013, and I had to decide which side of the disagreement to land on. The reference was wrong. The atmosphere was right.</p>

<p>The cookie dance is more behavioural than technical. The worker generates an <code class="language-plaintext highlighter-rouge">adsbx_sid</code> cookie locally, primes it against the <code class="language-plaintext highlighter-rouge">/globeRates.json</code> endpoint to make it valid, and then uses that cookie for the next two days of binary fetches. The historical-archive endpoint is stricter — a fresh cookie that has not just primed sometimes gets a 429 anyway — so there is a distinct exception type for rate-limit hits and an adaptive throttle that backs off from 300 ms between requests to 1,500 ms after the first 429 of a run. None of this is exposed to the rest of the system. It is one function. It returns a cookie, or it throws.</p>

<h2 id="reconstruction-is-where-the-lies-get-caught">Reconstruction is where the lies get caught</h2>

<p>A single position fix is data. A flight is interpretation. Stitching one into the other turns out to be the most subtle part of the system.</p>

<p>The pipeline gets a stream of position samples — latitude, longitude, altitude, timestamp, ground/airborne flag — and is asked to produce a closed flight: a takeoff airfield, a landing airfield, a route line, a duration, an altitude profile. The obvious approach (look for the airborne-to-ground transition) breaks immediately, because the upstream feed lies. Aircraft ICAOs are only twenty-four bits, and they are reused across the world, which means a single ICAO sometimes returns positions from two unrelated airframes concatenated into one apparent “flight” that crosses the planet at Mach 6. The MilMov trace cleaner filters anything moving faster than 3,000 knots between adjacent samples — Mach 4-ish ground speed, well past anything operational, and well past the SR-71 that the US Air Force retired in 1998 — and drops sentinel positions at lat ±89.99° that the feed emits when it cannot resolve a location.</p>

<p>A subtler problem is the helicopter that sits with its rotor turning on a forward apron for forty minutes between two short hops, and looks to a naive segmenter like one continuous “airborne” flight with a very strange profile. The reconstruction code looks for any ground-altitude run longer than fifteen minutes inside what the feed has flagged as a single leg, and retroactively splits it. One row in the database becomes two real sorties, with two takeoffs, two landings, two timelines.</p>

<p>Once a flight is closed, a second-pass classifier reads the altitude profile and tags the mission. It looks at the ratio of cruise to loiter, whether takeoff and landing share an airfield, whether the altitude oscillates in touch-and-go shapes. From that, the row ends up tagged as one of <code class="language-plaintext highlighter-rouge">transit</code>, <code class="language-plaintext highlighter-rouge">training</code>, <code class="language-plaintext highlighter-rouge">patrol</code>, or <code class="language-plaintext highlighter-rouge">mixed</code>. None of this is AI — it is a small state machine over segment durations and altitude bands. The mission type is a column in the flights table; it backs a filter chip on the flights index; it is one of the reasons the dashboard can ever say something more interesting than “this aircraft was airborne for two hours”.</p>

<p>The same machinery runs <em>live</em>, against still-open flights. Each segment is appended as it stabilises, so the flight-detail page shows takeoff and climb and cruise as they happen rather than after the aircraft has landed.</p>

<p><img src="/uploads/milmov-flight-in-progress.png" alt="A Royal Australian Air Force MC-55A Peregrine airborne over Mississippi" /></p>

<p>The page above is one of those still-in-progress flights, caught while I was writing this. It is a Gulfstream MC-55A Peregrine — a brand-new signals-intelligence platform that the Royal Australian Air Force is still introducing, with single-digit numbers of airframes currently flying — operating out of Majors Airport in Texas, currently over Mississippi at FL388 with a SAMSS-prefixed callsign. The big black card is the live mission, broken row by row into the segment timeline the classifier is building as the aircraft flies it: takeoff at 13:33Z, climb to FL375 over thirteen minutes, ninety-odd minutes of cruise, and the airborne row that grows in real time — 676 nautical miles flown so far, one hour fifty-seven minutes in the air. The strip of tiles below it is the trailing history MilMov has built for this tail since it first appeared: 15 sorties, 36,969 nm total, time aloft of 88 hours, longest mission 3,158 nm, highest altitude FL450. There are not many flight trackers in the world that will surface a one-of-a-handful RAAF SIGINT type and tell you, at a glance, that this is its third sortie in the past thirty days.</p>

<p>The trace itself, in decimated form, lives in R2. One JSON blob per flight, keyed by flight ID, downsampled to the minimum number of points that preserves the shape of the route. R2 is where blob storage should live when you do not care about egress fees — which, on Cloudflare, you do not, because there are none.</p>

<h2 id="the-anomaly-framework-is-the-part-i-am-proudest-of">The anomaly framework is the part I am proudest of</h2>

<p>Once a flight is closed and a fact-pack has been computed for it, the anomaly engine fires. There are ten dimensions in the current registry, four of them firing inline against live position ticks, six of them firing on flight-close. They are:</p>

<ul>
  <li><strong>type-rarity</strong> — a type that has been seen in fewer than a small number of prior flights worldwide</li>
  <li><strong>type-global-count</strong> — today’s count of a type against its trailing average</li>
  <li><strong>type-region-novelty</strong> — first sighting of a type in a country or region</li>
  <li><strong>per-airframe-novel-route</strong> — an airframe flying a route pair it has never flown</li>
  <li><strong>per-airframe-duration</strong> — a flight much longer than the airframe’s median</li>
  <li><strong>per-airframe-inactivity</strong> — an airframe back after a long quiet stretch</li>
  <li><strong>burst-launch</strong> — N or more aircraft of one type leaving one airfield in a short window</li>
  <li><strong>spatial-density</strong> — interesting aircraft clustering in one 2° grid cell against the cell’s seasonal baseline</li>
  <li><strong>spatial-type-density</strong> — clustering of <em>one</em> type in one cell, which is the formation/exercise detector</li>
  <li><strong>emergency-squawk</strong> — 7500, 7600, or 7700 observed</li>
</ul>

<p>A score is computed for each dimension separately, and a composition layer groups co-firing signals on the same subject — say, four T-6 Texans launching from the same airfield within a thirty-minute window, three of them flying a novel route, the cluster also tripping a spatial-type-density spike — into one composed event with a single headline. The composition is the thing that lets the dashboard say “16 × T-6 Texan launched within 30 min” rather than dumping fifty separate signals on me and asking me to fuse them in my head.</p>

<p>The spatial-density detector is my favourite, because it is the only one where the baseline does the interesting work. Every five minutes the discover cron sees what is airborne, buckets each aircraft into a 2° grid cell, and compares each cell’s count against the cell’s own (day-of-week, hour) EWMA baseline. A spike fires when the z-score crosses two. The cells learn from the same observations that score against them, which keeps the comparison honest — once enough Tuesday evenings have rolled by, a cell off the British coast settles into a notion of what “normal RAF coastal patrol density” looks like, and only fires when it is busier than that. Exercises light it up. So do news events. The grid does not know what news is, and it does not need to.</p>

<p><img src="/uploads/milmov-anomalies.png" alt="MilMov anomaly archive" /></p>

<p>The page above is the anomaly archive. The chips at the top are dimension counts: 3,500 novel-route events, 1,461 coordinated launches, 1,066 rare-type sightings, 471 long sorties, 30 emergencies, 5 air-to-air refuelling events. The last category was the most fun to land. Tankers and receivers do not normally announce themselves; you have to detect them by spatial coincidence of two specific role tags at compatible altitudes within a tight box for long enough that one of them must be donating fuel to the other. It is not a high-volume signal — five events ever, in the live archive at the time of writing — but it is the one I most enjoy spotting in the wild.</p>

<h2 id="the-cloudflare-primitives-are-quietly-load-bearing">The Cloudflare primitives are quietly load-bearing</h2>

<p>I do not believe MilMov would exist if I had had to host it myself. The specific way the Cloudflare primitives compose is what makes a project at this scope tractable for one tired person on a sofa, and it is worth being specific about which primitive does what.</p>

<p><strong>Workers and Hono</strong> — the entire site is one Worker. There is no frontend host, no separate API gateway, no CDN configuration. Hono routes the requests and JSX renders the pages server-side. The site has no client framework. There is no React, no Svelte, no hydration. Pages ship as HTML with a few inline scripts for the Leaflet maps and the polling refresh. There is nothing on the wire that can be slow.</p>

<p><strong>D1</strong> — fifteen live tables, twenty-six migrations, sixty-eight hand-written query functions, no ORM. Hand-written is the operative word. The single biggest performance win in the project came from a commit that added two indexes and rewrote one list query as a CTE; the <code class="language-plaintext highlighter-rouge">/types</code> page went from scanning 3.3 million rows in 225 ms to scanning 158 thousand in 56 ms. SQLite rewards exactly this kind of attention, and D1 inherits the reward.</p>

<p><strong>R2</strong> — one decimated trace per closed flight, read once when I open the flight-detail page. No egress fees, a generous free tier, and a bucket that grows by thousands of objects a day without making me think about cost.</p>

<p><strong>Queues</strong> — the reconstruct and compute-facts pipelines both run on Cloudflare Queues. Each has its own producer (a cron that scans for eligible work), its own consumer (a handler that drains the queue with bounded concurrency), and its own dead-letter queue. The compute-facts consumer runs eight invocations in parallel, each fanning out twenty in-flight R2 reads, against a queue depth that can spike to hundreds of thousands after a backfill. It does not break. Queues are the unsexy part of the Cloudflare platform and the most impressive piece of operational engineering they have shipped.</p>

<p><strong>Workflows</strong> — the per-type historical backfill is a Cloudflare Workflow. When I trigger <code class="language-plaintext highlighter-rouge">/run/backfill-type/C17</code>, a Workflow class spins up and walks every active C-17 in the system, calls the backfill routine against each, and survives ADS-B Exchange rate-limit retries through the Workflow runtime’s own exponential-backoff machinery. The same code, on a long-running VM, would have been a process I would have had to babysit. As a Workflow, it just runs to completion, and the dashboard shows me which airframe it is currently working on because the workflow writes step-level status into D1 as it goes.</p>

<p><strong>Crons</strong> — seven scheduled triggers, ranging from every five minutes (live ingest) to once a day (baseline rebuild). They are declared in <code class="language-plaintext highlighter-rouge">wrangler.toml</code>. There is no separate scheduler. There is no calendar. There is no Lambda + EventBridge invoice. They are just there.</p>

<p>There is no LLM in any of this. The project did briefly have a Workers AI binding, for a daily narrative-summary experiment, and I tore it out within the first few days. The deterministic templates over the facts pipeline produced better summaries than the model did, more cheaply, more predictably, and more easily styled. I think about this when I read articles arguing every product now needs to be AI-powered. MilMov needed to be observation-powered. The observations are the thing.</p>

<h2 id="claude-code-is-the-reason-this-is-the-size-it-is">Claude Code is the reason this is the size it is</h2>

<p>It would be easy to overclaim here. Let me try to be precise.</p>

<p>If I had written MilMov by hand at evenings-and-weekends pace, I would have shipped maybe a quarter of the surface area in the same eight days, and the anomaly framework specifically would not exist. The reason I know this is that the .NET version, which I wrote by hand across short bursts in 2022 and again in 2025, got as far as “show me what is airborne and decode the binary feed” before I lost interest in the maintenance overhead of the rest of it. The TypeScript version, in roughly eight days of one-handed sofa evenings, has ten anomaly dimensions, a composition layer, a backfill workflow, a queue-driven reconstruction pipeline, an FTS5 search index, and a full anomaly replay system that can rebuild the archive over arbitrary date ranges without re-fetching traces. The difference is not motivation. The difference is leverage.</p>

<p>Claude Code does most of the actual typing. What I do is decide what to build, decide what the shape of the change is, decide what the data model has to look like, and review the diff. I run the typecheck, I open the migration file, I read the SQL, I push back on the ugly parts. The work that used to be a series of one-week side-quests (“write the queue consumer”, “wire up the workflow”, “add a column and a migration”, “rebuild the index”) is now mostly a series of evenings where I describe what I want and review the result. The repository carries a CLAUDE.md that tells the agent how the project is shaped, what conventions matter, where the SQL gotchas are. I add to it whenever I notice a mistake the agent is likely to make twice. The harness, <a href="https://lord.technology/2026/05/18/the-harness-is-the-product-not-the-model.html">as I have written elsewhere</a>, is the product.</p>

<p>The single highest-leverage commit so far is the one that introduced the queue-driven reconstruction pipeline. I described the problem (the in-cron <code class="language-plaintext highlighter-rouge">reconstruct()</code> was starving on a <code class="language-plaintext highlighter-rouge">LIMIT 25</code> with no ordering, ingestion was outrunning reconstruction by a factor of about twenty, traces were going un-stitched), described the shape of the fix (move reconstruction onto a queue, producer-consumer split, bounded parallelism for ADS-B Exchange rate limits, dead-letter queue for failures), and pressed send. I reviewed the resulting diff for about thirty minutes, asked for two changes, applied the migration, and deployed. The throughput jump that evening was the biggest single behavioural change the project has had so far. I did not type any of it.</p>

<p>I want to be honest about one other thing. Claude Code makes me a better engineer at this project, not a more careless one. The thing I am better at is the architectural call: what should be a queue, what should be a workflow, what should be a cron, what should be a column versus a derived view, where the indexes need to land, what the right abstraction boundary is. I am worse, at the margins, at remembering syntax for SQLite’s <code class="language-plaintext highlighter-rouge">ALTER TABLE</code> quirks, or how Hono’s middleware ordering interacts with cookies, and I no longer particularly care that I am worse at those. The harness handles them. I handle the shape.</p>

<p><img src="/uploads/milmov-type-c17.png" alt="MilMov Boeing C-17 Globemaster 3" /></p>

<p>The page above is the kind of thing I find delightful, partly because every metric on it (the operator distribution, the country distribution, the top airfields, the 30-day activity sparkline, the airborne-right-now count) is one carefully-tuned SQL query against one D1 database, and partly because the C-17 is one of the most aesthetically perfect transport aircraft ever built and I will fight anyone who says otherwise.</p>

<h2 id="why-it-is-closed-source">Why it is closed source</h2>

<p>The obvious question is why I do not open it up. The honest answer is that the system is finely tuned to my taste, and the value of that tuning is precisely that it is not negotiable with anyone else. I do not want a pull request asking me to add Taylor Swift’s jet to the home feed. I do not want an issue thread relitigating whether <code class="language-plaintext highlighter-rouge">Oligarch</code>-tagged airframes should be in the live map. The project is private the way a workshop is private. There is no roadmap to maintain, no contributor onboarding to write, no GitHub Discussions to ignore. The site has an access-token gate not because the data is sensitive — most of it is on ADS-B Exchange’s own site — but because the gate keeps the audience at one person, and one person is the design.</p>

<p>There is a version of this project I could imagine open-sourcing, and it would attract a small, intense community, and I would resent every minute of running it. The version I have built instead is one I love spending evenings inside.</p>

<p>The Cloudflare bill, after a week of running this at full volume, is a single-digit number of dollars. The Claude Code subscription pays for itself any week the project makes me smile, which is most of them.</p>

<h2 id="what-i-get-out-of-it">What I get out of it</h2>

<p>I have learned more about military aviation in the eight days of building this thing than in years of casual reading. I now know which RAF squadrons fly Texans out of which fields, why the US Navy E-6Bs and Air Force E-4Bs co-orbit during certain exercises, what a Royal Australian Air Force C-17 is doing in Diego Garcia, what the standard FL for a Globemaster transatlantic crossing tends to be, which Belarusian An-148 belongs to whom. I have started recognising airframes by registration the way some people recognise birds by song.</p>

<p>I have also learned, in a way no platform documentation ever quite teaches, what the Cloudflare Developer Platform feels like under sustained load from someone being slightly unreasonable about how much they want to do per dollar. I <a href="https://architectingoncloudflare.com/">wrote a book</a> earlier this year about how these primitives compose; MilMov is what taking my own advice in a single week looks like. It scales further than any hobby project has any right to need. The primitives genuinely compose the way the marketing claims they do. The constraints (the 128 MB memory cap, the 30-second wall on cron invocations, the D1 placeholder limit, the FTS5 tokenizer quirks) push you towards architectures that turn out, even after only a week of running them, to be the architectures I would have wanted in the first place.</p>

<p>The E-6B Mercury that orbited over the North Sea has not reappeared in MilMov since. The composed anomaly is still in the archive, with its decayed score, its dimension tags, its little caption explaining what fired and why. The orbit ended after about three hours; the aircraft turned west, climbed, and went home. Whatever it was doing was none of my business. The fact that the system noticed, on my behalf, while I was on the sofa with one hand free and a day job to do in the morning — that is the whole point of the project, and the whole point of building anything for an audience of one.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="cloudflare" /><category term="personal" /><category term="workers" /><category term="d1" /><category term="workflows" /><category term="queues" /><category term="adsb" /><category term="claude-code" /><category term="aviation" /><summary type="html"><![CDATA[At about half past eleven one evening this week I noticed a US Navy E-6B Mercury orbiting over the North Sea. Not “noticed” in the way of someone who happened to look up — I was on the sofa with a laptop balanced on one knee, and the orbit was being drawn for me, in slow careful circles, by a dashboard I had been building, in evenings and weekends, for the previous eight days. The aircraft is a survivable airborne command post for the strategic nuclear force. It does not normally show up on a flight tracker at all, and when it does, it tends to fly straight lines between US bases. An orbit over the North Sea at FL250 with the callsign blanked is not a routine sight. The dashboard, which I had taught about a hundred small things by then, had quietly composed the event for me as a “rare type” anomaly with a “long sortie” co-signal. I watched the orbit for about forty minutes.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The harness is the product, not the model</title><link href="https://lord.technology/2026/05/18/the-harness-is-the-product-not-the-model.html" rel="alternate" type="text/html" title="The harness is the product, not the model" /><published>2026-05-18T21:00:00+01:00</published><updated>2026-05-18T21:00:00+01:00</updated><id>https://lord.technology/2026/05/18/the-harness-is-the-product-not-the-model</id><content type="html" xml:base="https://lord.technology/2026/05/18/the-harness-is-the-product-not-the-model.html"><![CDATA[<p>Cloudflare’s <a href="https://blog.cloudflare.com/cyber-frontier-models/">Project Glasswing write-up</a> landed today and the Hacker News thread is mostly arguing about whether the prose was written by Mythos or by Opus. It is a fair complaint and an irrelevant one. The diagram halfway down the page is the actual deliverable, and almost nobody is talking about it.</p>

<p>Cloudflare has published the reference architecture for doing vulnerability research with a frontier model at scale. The model in the headline is the easy part. The seven-stage agent pipeline around it is what makes the model useful, and it is the bit worth stealing.</p>

<h2 id="what-the-pipeline-actually-does">What the pipeline actually does</h2>

<p>Recon reads the repository top-down and produces a shared architecture document covering build commands, trust boundaries, entry points, and likely attack surface. Every downstream agent works from the same map.</p>

<p>Hunt fires roughly fifty agents in parallel, each pinned to one attack class against one narrow scope. Each hunter can compile and execute proof-of-concept code in a per-task scratch directory. Not ‘reason about whether this might be exploitable’, but actually run the exploit and see what happens.</p>

<p>Validate is the move that separates this from a clever prompt. An independent agent with a different prompt, a different model, and no ability to emit its own findings re-reads the code and tries to disprove the hunter. Putting two agents in deliberate disagreement does more for noise reduction than any amount of careful single-agent prompting.</p>

<p>Gapfill re-queues areas the hunters touched but did not cover. Dedupe collapses variants. Trace fans out one agent per consumer repository, uses a cross-repo symbol index, and answers the question that actually matters, which is whether attacker-controlled input reaches the flaw from outside the system. Feedback turns reachable traces into new hunt tasks. Report writes structured output against a schema and fixes its own validation errors before submitting.</p>

<p>Each stage is a fix for a specific failure mode anyone who has tried this work at scale will recognise. Unconstrained scope makes the model wander. Self-review turns the model into a generous marker. Once a hunter has had a few wins with one attack class it starts drifting toward that class and ignoring the rest of the surface. And the gap between ‘we found a thing’ and ‘an attacker can actually reach the thing’ is where most security findings die.</p>

<p>This is not Claude Code with a system prompt. It is a directed graph of agents with deliberately different prompts and deliberately constrained tool access, where the disagreement between agents carries the structural weight.</p>

<h2 id="why-the-model-is-the-wrong-thing-to-fixate-on">Why the model is the wrong thing to fixate on</h2>

<p>The thread keeps trying to litigate whether Mythos is genuinely a step change or a marketing exercise. Pick whichever side you prefer. The harness works because Mythos is good enough at chained reasoning to make the hunt stage productive, but it would still work, with degraded signal-to-noise, on Opus 4.7 or GPT-5.5. The architecture is the moat, not the weights.</p>

<p>Anyone who has pointed Claude Code at a hundred-thousand-line repository and asked it to find security issues knows the failure mode Cloudflare describe. A single agent session, even with subagents, covers maybe a tenth of a percent of the attack surface usefully before compaction kicks in and the earlier findings get dropped without ceremony. Driving harder does not help past a certain point. The bottleneck stops being the model and starts being the shape of the interaction.</p>

<p>This is the lesson most teams reaching for agentic engineering on non-trivial problems are going to learn the hard way. The model is necessary and nowhere near sufficient. Scope hints, adversarial reviewers, per-task scratch environments, structured output schemas, an explicit reachability stage. That is where the engineering lives. Security research makes the point obvious because the problem is narrow and parallel by nature. Plenty of other domains have the same shape if you look.</p>

<h2 id="what-to-take-from-this">What to take from this</h2>

<p>The adversarial review stage is the change with the highest payoff. Drop a second agent into your existing single-agent setup with a different prompt and no ability to emit findings of its own, and watch the false-positive rate fall. It generalises to anything where ‘is this finding real’ and ‘did the model find it’ need to be different questions.</p>

<p>The other pattern worth lifting is the split between ‘is there a flaw’ and ‘can an attacker actually reach it’. Asking the model both questions in one prompt produces worse answers to both. Splitting them across agents is cheap, and the same shape applies anywhere coverage matters more than depth on a single hypothesis.</p>

<p>The Cloudflare post itself is over-edited, light on hard numbers, and probably an inadequate basis for forming a view on Mythos specifically. <a href="https://daniel.haxx.se/blog/2026/05/11/mythos-finds-a-curl-vuln/">Daniel Stenberg’s write-up on a Mythos finding in curl</a>, <a href="https://xbow.com/blog/mythos-offensive-security-xbow-evaluation">XBOW’s competitive evaluation</a>, and the <a href="https://www.aisi.gov.uk/blog/our-evaluation-of-claude-mythos">AISI evaluation</a> are better signal on the model. Trust the harness diagram more than the framing around it.</p>

<p>The model gets the headline. The harness is what ships.</p>]]></content><author><name>Jamie Lord</name><email>jamie@lord.technology</email></author><category term="ai" /><category term="cloudflare" /><category term="security" /><category term="agents" /><category term="claude" /><summary type="html"><![CDATA[Cloudflare’s Project Glasswing write-up landed today and the Hacker News thread is mostly arguing about whether the prose was written by Mythos or by Opus. It is a fair complaint and an irrelevant one. The diagram halfway down the page is the actual deliverable, and almost nobody is talking about it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lord.technology/assets/images/og-image.png" /><media:content medium="image" url="https://lord.technology/assets/images/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>