cloud
// ~/projects/magellan/cloud.ts
const cloud = {
status: "active",
started: "2026-09-19",
tags: ["typescript", "cloudflare", "d1", "r2"],
repo: "https://github.com/fabbrito/magellan-cloud",
};Two Cloudflare Workers. One ingests what devices send; the other answers queries for clients such as Grafana. Readings land in D1, and every raw upload is archived in R2.
Why it stays dull
The cloud knows sources, metrics and readings, and never the word “inverter”. It stores whatever a device’s manifest declares, so the variety stays on the device and the cloud rarely needs a deploy.
Decisions
- Duplicates are expected. A device retries until it hears back, so the same batch can arrive twice. Each reading is keyed by its source and time, and a repeat simply collides and vanishes.
- The archive is the record. R2 keeps every upload exactly as sent. D1 is an index over it and can be rebuilt from it.
- Cloudflare, still on the free tier. Workers, D1 and R2 are cheap enough that leaving the free tier has never come up. Staying lean is still a habit: D1 writes per day are what every storage choice is weighed against, so the room stays there when the fleet grows.
- One token, one device. Each device has its own revocable credential, and the credential, not the URL, decides which device is talking.
- No UI. An early version had a single-page dashboard of its own. I dropped it after a first prototype: charting is solved elsewhere, and every hour spent on it was an hour off capture and resilience. The cloud serves data and health; charts, dashboards and alerts belong to the client.