All posts
Dev Log·5 min read

What shipped this spring: five countries and a grid endpoint

A build-in-public roundup. May and June were mostly coverage, and the plumbing that made coverage cheap. Here is the honest list - including the things that did not ship.

I do not post enough plain build-in-public updates, so here is one: what actually shipped over the last couple of months, what is running now, and - because honesty is the whole point of these - what I said I would do and did not.

The headline is coverage. Five countries went live at 4 km in five weeks: Switzerland on 7 May, Slovenia on 14 May, Austria on 21 May, Czechia on 28 May, and Germany on 4 June. With the UK that makes six countries on the API today, all serving the same fields, four cycles a day, the same JSON contract whether you query the Long Mynd or the Bernese Oberland. Germany is by some distance the heaviest of the six at around 54 minutes a cycle; Slovenia is the lightest at about 9.

None of that would have been affordable without the plumbing underneath it, which is the part I am actually proud of. The scheduler moved from a pile of staggered per-country timers to a single sequential batch that runs every live country once per cycle, holds one global lock so runs cannot overlap, records any country that fails and carries on, and exits non-zero if anything broke. Every domain now carries its own timezone so the local-clock fields are right in Ljubljana and Prague and Berlin, not just London. Every country has its own heartbeat, so a German failure cannot hide behind a healthy UK run. And the publication mapping that decides which R2 prefix a run lands under moved into code rather than environment variables, after an early scare where a Swiss run nearly published under the UK prefix.

On the API itself, the big one was the grid endpoint. `/v1/grid` serves one field, one hour, as a bounded slice, which is the shape you need to build a map layer without firing thousands of point requests. It shipped alongside two proper kinematic fields, `horizontal_convergence_s1` and `horizontal_divergence_s1`, computed from the 925 hPa wind, which are far closer to real convergence-line-finding inputs than the old scalar proxy. There is a full post on the grid endpoint and one on reading the convergence fields.

Operationally, two smaller things landed that keep the lights on: a retention helper that prunes old run directories so four cycles a day do not fill the disk in a fortnight, and the first brick of the validation pipeline - a baseline-versus-candidate diff at named pilot sites. Neither makes a forecast better, both are what let the interesting work keep running unattended.

Now the honest part: what did not ship. The 2 km UK domain is still a roadmap item waiting on a second worker. The public validation dashboard does not exist yet - the diff harness is the layer underneath it, not the dashboard itself. The site now has public explore examples and club enquiry pages, but self-serve club management still needs saved widget IDs, allowed domains, and cache-first summaries before it belongs in the account dashboard.

What is next, in rough order: validation against radiosondes - the dense German upper-air network is what finally makes that worth the engineering - then the 2 km work on a second worker, then Spain, which is benchmarked and waiting for a slot its runtime will not blow up. If you are building on the API and something on that list is blocking you, tell me, because the order is not fixed. The coverage page tracks what is live.

Written by JadeMore in Dev Log