| platform-engineering / python / data-engineering / case-study / iot

Eine Batterie-Analytics-Plattform für 100k+ IoT-Geräte bauen, allein

Ein Entwickler, acht Repositories: eine getestete Kapazitäts-/Laufzeit-Bibliothek im internen PyPI, Dagster-Ingestion, FastAPI-Services, Dashboards und Monitoring. Wie aus einem Batterie-Vorhersageproblem eine vollständige produktive Plattform wurde.

Ein Batterie-Vorhersageproblem bleibt kein Vorhersageproblem.

Es beginnt als Modell. Wann ist die Batterie dieses Thermostats leer? Dann kommt die Realität. Die Schätzung braucht Felddaten, und die Felddaten brauchen eine Pipeline. Die Pipeline braucht einen Zeitplan. Die Schätzung braucht einen Service, damit andere Systeme sie lesen können. Der Service braucht ein Dashboard, damit Menschen ihm vertrauen. Das Dashboard braucht Monitoring, damit Ausfälle bemerkt werden. Das Ganze muss deploybar und rückrollbar sein.

Am Ende hat man kein Modell. Man hat eine Plattform.

So wurde aus einem Kapazitäts- und Laufzeit-Schätzproblem für 100.000+ IoT-Thermostate ein Acht-Repository-Produktivsystem, das ich end-to-end gebaut habe und verantworte.

Die Form des Systems

Die Plattform ist nicht ein Service. Sie ist eine kleine Menge von Komponenten, jede mit genau einer Aufgabe.

Felddaten   -> Ingestion (Dagster -> Parquet/MinIO)
            -> Schätzbibliothek (Kapazität + Laufzeit, typisiert, getestet, internes PyPI)
            -> Services (FastAPI: Schätzungen pro Gerät, Fleet-Abfragen)
            -> Dashboards (Streamlit für Analysten, firmeneigenes Vue-Dashboard für das Produkt)
            -> Monitoring (Health-Checks, Alerting)

Die wichtigste Entscheidung war, die Schätzlogik zu einer Bibliothek zu machen, nicht zu einem Skript, das in einer Pipeline vergraben ist.

Die Bibliothek ist der Kern

Die Kapazitäts- und Laufzeitschätzung lebt in einer einzigen typisierten Python-Bibliothek, veröffentlicht in einem internen PyPI.

Sie hat volle Testabdeckung und strikte Typprüfung. Das klingt nach Overhead für ein internes Tool. Es ist das Gegenteil. Die Bibliothek wird von der Ingestion-Pipeline, dem Diagnose-Tool pro Gerät, dem Fleet-Reporting und der Evaluierungspipeline genutzt. Würde die Schätzlogik ihr Verhalten still ändern, würden vier nachgelagerte Systeme gleichzeitig abdriften.

Sie als versionierte, getestete, installierbare Paket zu bauen bedeutete, dass jeder Consumer eine bekannte Version pinnt, und eine Algorithmusänderung ein bewusstes Release war, kein Versehen.

Die Schätzlogik wird an vier Stellen genutzt. Also wird sie wie eine Abhängigkeit versioniert, nicht wie ein Notebook editiert.

Ingestion ist absichtlich langweilig

Die Ingestion-Seite nutzt Dagster, um Gerätetelemetrie zu ziehen, Laufzeit- und Kapazitätsdatensätze zu bauen und sie als partitioniertes Parquet in MinIO zu speichern.

Partitionierung nach Zeit und Speicherung in einem Object Store klingt nach Over-Engineering für Batteriedaten. Aber die Flotte besteht aus 100.000+ Geräten, die kontinuierlich Telemetrie produzieren. Einen Monat neu zu verarbeiten sollte nicht heißen, alles neu zu verarbeiten, und ein Re-Run sollte günstig und idempotent sein. Langweilige, partitionierte, wiederholbare Ingestion ist das, was den Rest der Plattform ruhig hält.

Services und Dashboards: Vertrauen braucht eine Oberfläche

Eine Vorhersage, die niemand inspizieren kann, ist eine Vorhersage, der niemand vertraut.

Also stellt die Plattform ihre Schätzungen auf zwei Wegen bereit. FastAPI-Services beantworten Maschinenfragen: Was ist die Schätzung für dieses Gerät, diese Flotte, diesen Kunden. Eine Diagnose-Oberfläche pro Gerät beantwortet die menschliche Frage: Warum hat das System das für jenes Thermostat vorhergesagt. Und die Schätzungen auf Flottenebene sind in das bestehende Vue-Dashboard der Firma integriert, wo Produktteam und Kunden ohnehin hinschauen.

Dieser letzte Punkt ist wichtig für Ehrlichkeit über den Umfang. Ich habe nicht das Firmen-Dashboard gebaut. Ich habe die Batterie-Analytics gebaut, die es speisen, und sie in ein Frontend integriert, das andere Ingenieure verantworten. Zu wissen, wo das eigene System endet, gehört dazu, es zu verantworten.

Monitoring schließt den Kreis

Die Plattform beobachtet sich selbst. Health-Checks und Alerting fangen Ingestion-Ausfälle, veraltete Datensätze und Datenqualitätsprobleme ab, bevor sie die Menschen erreichen, die von den Zahlen abhängen.

Das ist der Unterschied zwischen einem Projekt und einem System. Ein Projekt produziert einmal eine Ausgabe. Ein System produziert weiter korrekte Ausgaben und sagt dir, wenn es das nicht kann.

Was es mich gelehrt hat, es allein zu bauen

Das Ganze allein zu machen, vom Algorithmus bis zur UI-Integration, erzwang eine Disziplin, die ein größeres Team überdecken kann.

Jede Komponente musste einfach genug sein, dass eine Person sie im Kopf behalten und betreiben kann. Das trieb mich zu einer getesteten Kern-Bibliothek, langweiliger wiederholbarer Ingestion, dünnen Services und Monitoring, das laut ausfällt. Nicht weil das elegant ist, sondern weil es der einzige Weg ist, wie ein Entwickler acht Repositories verantworten kann, ohne dass das Ganze fragil wird.

Die Batteriefrage war der einfache Teil. Sie in Infrastruktur zu verwandeln, von der eine Firma abhängen kann, war die Arbeit.