Seven parts of localhost. Time to find out what happens when the coordinator leaves my laptop.
This is the last part of the series, and it has three jobs: ship the thing to a real URL, show you the production numbers, and then be honest about what I built. Not the pitch-deck version. The scorecard. (There is one later part, written when the deploy below fell over in production: part 9.)
Shipping it
The coordinator now runs on Cloud Run in Inoltro's GCP project, fronted by an external HTTPS load balancer with Cloud Armor and a Google-managed wildcard cert, DNS on Cloudflare. It's live at pi.inoltro.tech.
(Update, July 2026: it no longer runs on Cloud Run. Days after this post, the single pinned instance wedged under sustained WebSocket load, and the coordinator moved to a plain VM behind the same edge. The URL and everything below still stand; the platform underneath changed. The postmortem is part 9.)
The single most important deploy decision was also the least fashionable one: Cloud Run with min_instances = max_instances = 1. One instance, forever. The coordinator holds the entire grid in memory: connected nodes, in-flight work units, trust scores, the running totals. If Cloud Run scaled it to two instances, I'd have two half-grids that each believe they're the whole grid. Split brain, by autoscaler. Pinning to a single instance looks like defeat if you think of Cloud Run as "serverless," but it's really just "a container Google keeps alive with TLS and a deploy pipeline attached," and for a stateful WebSocket coordinator that's exactly the right amount of platform. Part 4 made this argument in theory. Production didn't change my mind.
The actual pain wasn't the architecture. It was the plumbing. Two gotchas earned their place in this writeup.
Gotcha one: my machine had five credentialed gcloud accounts, and the active one belonged to the wrong org. Every gcloud command needed explicit --account and --project flags or it would cheerfully act on someone else's infrastructure. Worse, gcloud auth login and Application Default Credentials are two different credential stores: gcloud commands worked while Terraform failed auth, because Terraform reads ADC. And docker push doesn't take an account flag at all; the gcloud credHelper uses whatever account is active, so pushing an image meant switching the active account, pushing, and switching back. None of this is exotic knowledge, but it cost me a real evening, and the fix is a habit: on any machine with more than one Google identity, never trust the implicit account. Pass it explicitly, every time.
Gotcha two: the org's Domain Restricted Sharing policy blocked allUsers. A public Cloud Run service needs the allUsers member on its invoker role, and DRS exists specifically to stop people from granting things to allUsers. My first instinct was to route around it: the service sits behind a load balancer with Cloud Armor anyway, so surely the service itself doesn't need to be public. It does. An external HTTPS load balancer does not authenticate to Cloud Run; it just forwards traffic, so the service behind it still has to accept unauthenticated requests. The honest framing is that the LB and Cloud Armor are the real gate, and allUsers is plumbing that lets the gate reach the door. The fix was a project-level DRS override, scoped and documented, rather than weakening the policy org-wide. If your org has DRS turned on and you want a public Cloud Run service, this is not optional and there is no clever bypass. Budget for the policy conversation.
There were more bruises (a Cloud Build service account that couldn't read its own source bucket, two Terraform module bugs that only surfaced at apply), but those two carried the real lessons: identity is the hard part of GCP, and org policy beats architecture diagrams every time.
The live numbers
With the coordinator public, real browsers joined. Not simulated nodes, actual 16-core machines opening a tab. Here's what pi.inoltro.tech/statz reported when I froze the numbers for this post:
- 12.1 billion darts, all verified through the R=2 redundancy scheme from part 6
- piEstimate: 3.14160797, an error of roughly 1.5e-5 against the real thing
- Canaries: 1996 of 2000 passed, 0 failed, 0 conflicts. The gap is units that never came back before their node vanished, not wrong answers; they went back in the queue
- 224 work units reassigned as tabs closed and laptops slept, with zero errors and zero lost work
Every mechanism the series built showed up in that list. Determinism from part 2 is why byte-equality verification worked at all. The healing from part 5 is those 224 reassignments happening silently. The trust machinery from part 6 is the clean canary record. Twelve billion darts computed by strangers' browsers, and I can defend every one of them.
I want to be precise about what that proves. It proves the system works: untrusted, flaky, anonymous nodes produced a verified result in production. It does not prove the system is worth running as a business. That's the next section.
The honest scorecard
This is not a compute business. Three walls, and I hit all of them.
First, the verification tax. Trust costs 2.5 to 2.9x in measured overhead, because every unit runs at least twice plus canaries plus tiebreaks. That's not an implementation flaw I can optimize away; it's the price of accepting work from nodes I can't audit.
Second, browser nodes are flaky by design. Tabs close, laptops sleep, phones thermal-throttle within minutes. The grid heals through all of it, but healing is overhead too, and it means throughput planning on this substrate is weather forecasting.
Third, and decisively: anyone who actually needs bulk compute will price cloud spot instances, and spot instances win. They're cheap, they don't lie, they don't need R=2, and they don't disappear when someone finishes reading a webpage. For browser compute to beat spot pricing after a near-3x tax, the compute would have to be essentially free at scale, which means extracting it from visitors, which brings us to the dead end.
The dead end: monetizing visitor CPU. This idea gets reinvented every few years and it always ends the same way. Coinhive tried it with mining and became a malware category. The value of one visitor-hour of CPU is tiny, informed consent doesn't survive contact with scale, and the entire model reads as "the website is stealing my battery." I looked at this door long enough to describe it. It stays closed.
The real niches. Two slices survived the pruning, and they're genuinely good.
Zero-install citizen science. BOINC-style volunteer computing has always died at the installer; asking someone to download and run a daemon filters out almost everyone who was curious enough to click. A browser grid removes that step entirely. Open a page, you're contributing, close it, you're done. For projects whose bottleneck is volunteers rather than raw FLOPS, that funnel change matters more than the verification tax.
CS education. This system makes distributed systems visible in a way slides never will. Open two tabs and watch a global computation split between them. Kill one mid-work and watch the units reassign in real time. Inject a lying node and watch it get caught and ejected in front of a class. Every abstract concept in a distributed systems course has a button here.
What it genuinely is. A proof of capability, and one reusable primitive. The proof: I can take a problem from a Rust kernel to a verified, healing, production grid on GCP, and show my work at every layer. The primitive is the more interesting artifact: verifiable compute over untrusted nodes. A deterministic kernel, redundant assignment with byte-equality, salted canaries, and per-node trust scores compose into a small machine that answers "how do I trust work from workers I don't control?" That question shows up well beyond browser tabs, and part 7 showed the machine is already workload-agnostic.
One last thesis check. The series opened with serverless-first as the right default for an early build, and after eight parts I still believe it. Everything stateless in this system lives happily on managed platforms, and the one component that bent the rule, a stateful WebSocket coordinator pinned to a single instance, bent it for a reason I can state in one sentence. That's what a good default looks like: you follow it until you can articulate exactly why you shouldn't.
So that's the series. A pi estimator that was never about pi, a grid that heals, a verifier that catches liars, a deploy with receipts, and a verdict I can stand behind: not a business, but a real capability, honestly measured.
Previously in this series: It was never about pi. There is one later part, written when this deploy wedged in production: When the pinned instance wedged.