TramPuls

TramPuls beantwortet eine Frage mit gemessenen Zahlen statt Bauchgefühl: Wie pünktlich ist eine Linie der RNV wirklich, und was ist ausgefallen? Dafür schreibt eine selbst gebaute Pipeline aus Go, DuckDB und dbt den offenen Echtzeitdatenstrom des Verkehrsverbunds Rhein-Neckar seit dem 27.08.2026 lückenlos mit, weil es sonst kein Archiv davon gibt.

Rolle
Alleinentwickler, privates Projekt
Zeitraum
seit August 2026
Stack
Go, DuckDB, dbt, Parquet, Docker
Status
Live
TramPuls-Weboberfläche mit Pünktlichkeits-Kennzahlen für Tram- und Buslinien der RNV
TramPuls, Stand 28.09.2026

Das Problem

Wer im Rhein-Neckar-Raum täglich mit Tram oder Bus der RNV fährt, kennt die Zuverlässigkeit seiner Linie nur aus eigener Erfahrung – nachprüfen kann er sie nicht. Der offene Echtzeitstrom des Verkehrsverbunds (GTFS-RT) zeigt nur den aktuellen Zustand und hat kein Archiv. Was niemand mitschreibt, ist unwiederbringlich weg.

Der Aufbau

Ein Collector in Go liest den GTFS-RT-Feed des VRN alle 30 Sekunden, filtert auf RNV-Fahrten und schreibt stündlich ZSTD-komprimierte Parquet-Dateien auf ein persistentes Volume. Ein zweites Go-Programm lädt täglich den Sollfahrplan, versioniert ihn und leitet daraus die Filterliste ab, gegen die der Collector prüft. dbt-duckdb transformiert die Rohdaten in drei Schichten – staging, intermediate, marts –, DuckDB liest die Parquet-Dateien dabei direkt vom Dateisystem, ganz ohne eigenen Datenbankserver. Ein Exporter schreibt aus den fertigen Marts JSON-Dateien, die eine statische Vite/TypeScript-Seite ohne Framework-Runtime lädt. Das Ganze läuft als Docker-Stack auf einem eigenen Server, deployt über Coolify.

Die harte Nuss

Am 30.08.2026 veröffentlichte der VRN vorab eine neue Fahrplanperiode – der Echtzeitstrom sendete aber weiter Kennungen der laufenden Periode. Die Filterliste passte plötzlich nicht mehr zum Feed: Statt rund 905 Fahrten je Abruf erkannte der Collector nur noch 53, die Auflösbarkeit fiel von 99,1 % auf 17,0 %. 16 Stunden lang verwarf das System neun von zehn RNV-Meldungen, ohne dass ein Prozess abstürzte oder ein Health-Check anschlug – aufgefallen ist es erst beim Lesen der veröffentlichten Zahlen. Die Filterliste entsteht seitdem aus der Vereinigung der letzten 21 Tagesversionen des Fahrplans statt nur der jüngsten.

Verworfen

  • gtfs.de statt dem VRN-Feed als Quelle: 69-faches Datenvolumen, keine Ausfallkennzeichnung, rotierende Haltestellen-IDs – in jeder gemessenen Kategorie schlechter.
  • DuckDB-WASM oder Evidence.dev statt vorgerechneter JSON-Dateien: DuckDB-WASM hätte rund 3 MB vor der ersten Zahl gekostet, das Ladebudget der Seite liegt unter 150 KB JavaScript.

Qualität

  • 36 Go-Unit-Tests laufen tabellengetrieben gegen einen echten Feed-Abruf, grün (Stand 30.08.2026).
  • 73 dbt-Tests – Eindeutigkeit, Wertebereiche, Fremdschlüssel, elf projekteigene Prüfungen –, grün (Stand 28.08.2026).
  • Im Betrieb läuft eine stündliche Prüfung über neun Kennzahlen wie Feed-Alter, Auflösbarkeit und Plattenplatz.
  • Bekannte Lücke: Vier Straßenbahnlinien (4, 4A, 6, 6A) fehlten im VRN-Verbundfeed komplett – 0 Beobachtungen bei 78.414 Soll-Halten, obwohl die RNV-eigene Quelle openRNV 95–100 % Abdeckung liefert. Seit dem 16./17.09.2026 liefert der VRN-Feed sie wieder.

Ergebnis und Gelerntes

Der Collector sammelt seit dem 28.08.2026, 13:09 Uhr, durchgehend – über 21 aufgezeichnete Betriebstage kamen bis zum 20.09.2026 817.106 gemessene Tram- und 941.265 gemessene Bus-Halte zusammen, am 22.09.2026 waren 107 Linien exportiert, 86 davon mit auswertbaren Halten. Zwei Serverausfälle (ein Hosting-Ausfall am 15.09., ein Neustart am 24.09.) übersteht das System seither ohne Datenverlust, beide erkannte die stündliche Prüfung korrekt. Im Nachhinein hätten Monitoring und Benachrichtigung von Anfang an stehen müssen: Sowohl ein 16 Stunden stiller Datenverlust am 30.08. als auch eine 21,5 Stunden eingefrorene Website am 01.09. passierten, bevor beide vollständig eingerichtet waren. Ein Backup fehlt bis heute bewusst – offen, mit höchster Priorität.

KI Assistent

Frag mich, was du wissen willst

Hier antwortet eine KI (gpt-oss-120b, betrieben bei Groq), nicht ich persönlich. Sie kennt nur die Inhalte dieser Seite und kann sich irren – verbindlich ist, was auf der Seite steht. Deine Frage wird zur Beantwortung an Groq übertragen. Mehr dazu